0

I am trying to parse a local text file (output2.txt) using JavaScript. The file contains 2D coordinates that I need to use for automated triangulation. The project's end goal is to read the 2D coordinates from this local file, and include them in automated triangulation in order to create a 3D model in the browser.

I have been using calls to the alert method to see if the code runs through certain relevant parts. chunk is the part of the text file currently being read, yet alert(chunk); always returns a single 0 and never something familiar from the text file. Why would this occur?

When I run the code as is, no data points or faces appear on the screen. The alert method output would imply there is nothing in the text file but zeroes. I suspect that because I always read 0 from the text file, I never reach the part of the for loop that would execute body_components.get(name).vertices.push(vertex); thus never pushing any vertices to use for the automated triangulation, leading to nothing appearing on the screen.

My team consulted this for automated triangulation, and this for accessing a local file using JavaScript. Additionally, searching Stack Overflow for answers gave us this, but I believe the situation in that thread is different, as the text file I have contains more than just one character, and because my team's code is in JavaScript instead of Java.

Shown below is the code for the automated triangulation method, and the code for reading the file. I have also included a segment of output2.txt for reference.

Thank you in advance for your help.

Code:

for (var value in body_components.values()) {
        var triangles = THREE.ShapeUtils.triangulateShape(value.vertices, holes);
        for( var i = 0; i < triangles.length; i++ ){
            value.faces.push(new THREE.Face3( triangles[i][0], triangles[i][1], triangles[i][2]));
        }

        var mesh = new THREE.Mesh(value, material);
        scene.add(mesh);
    }


    function parse(){
        alert("I am now inside the parse method!"); //works
        $.ajax({
            url:'http://localhost/human_output/output2.txt',
            success: function (data){
                //be wary of what a line in the output file contains, where it starts and ends.
                alert("I have accessed output2!"); //works (yay~)
                for (var entry in data.split('\n')) {
                    alert("I am in the for loop, looking at a line!");
                    //^works
                    var count = 0;
                    var name;
                    var layer_z_coordinate;

                    for (var chunk in entry.split('\s')) {
                        alert("I am looking at something after a space. Chunk:"); //works
                        alert(chunk);
                        if (/[0-9]+/.test(chunk)) {
                            //chunk is the layer number
                            alert("I am looking at a number."); //works
                            alert("Here is a chunk:");
                            alert(chunk);
                            layer_z_coordinate = parseInt(chunk) * (-1);
                            zString = layer_z_coordinate.toString();
                            alert("here is layer_z_coordinate made into a String:");
                            alert(zString); //works. this always gives me 0?

                        } else if (/[^0-9]+/.test(chunk)) {
                            //chunk is the name or a lone '|', so check if it exists, make it if necessary
                            alert("I am looking at a non-number 01.");
                            if (!body_components.has(chunk) && toString(chunk) != "|") {
                                name = chunk;
                                var geo = new THREE.Geometry();
                                alert(name + "hello?");
                                body_components.set(name, geo);
                                alert("I am looking a non-number 02.");
                            }

                        } else {
                            //chunk is the entire block of coordinates
                            alert("I am looking at neither a number nor a non-number?");
                            for (var coordinatePair in chunk.split(':')) {
                                alert("I just split a :");
                                if (count % 10 == 0) { //every 10th coordinate?

                                    var xy = coordinatePair.split(',');
                                    var vertex = new THREE.Vector3(parseInt(xy[0]), parseInt(xy[1]), layer_z_coordinate);
                                    body_components.get(name).vertices.push(vertex); 
                                    //retrieves the corresponding geo(metry) for 'name'
                                    alert("I just pushed the vertices!");
                                }

                                count++;
                            }
                        }
                    }
                }
            }
        });
    };

output2.txt sample:

1 | human|man|woman|person|homo sapiens | 309,257:310,257:309,257:308,258:309,257:306,258:307,258:308,258:305,258:306,258:360,290:360,291:360,292:361,293:361,294:361,295:361,296:362,297:362,298:362,299

1 | medulla oblongata | 121,650:121,650:121,650

1 | pancreatic duct|duct of Wirsung | 374,298:374,296:374,297:374,298:374,294:374,295:374,296:373,294:374,294:373,293:336,331:336,332:337,333:337,334:338,335:338,336:339,337:339,337:339,338:340,339:422,420:422,420:423,420:424,420:425,420:425,420:426,420:426,420:426,419:426,420:442,386:443,386:443,386:443,385:444,384:444,384:444,383:444,384:444,383:444,383:445,382:445,382:445,381:445,382:445,380:445,381:445,378:445,379:445,380:445,378:414,325:412,324:413,324:414,325:412,324:412,322:412,323:412,324:411,321:412,322:377,298:375,298:376,298:377,298:375,298:375,298:375,299:375,299:374,298:375,299

Community
  • 1
  • 1
  • There's no point in a runnable snippet that has no chance of running. You should reduce your code to just what is required to reproduce the behaviour, e.g. remove all the AJAX parts and post just the parsing part with the sample text as input. – RobG Apr 11 '17 at 05:00
  • Whoops, you're right @RobG! I changed the runnable snippet to a code sample instead. The way I am accessing the data (the text file contents) is using AJAX though, the sample text is a part of the data. Should I remove the AJAX parts regardless? I felt that while not all of this code contributed directly to the parsing error, everything is still interconnected. – Sue Techie Apr 11 '17 at 22:10
  • The [*success callback function*](https://api.jquery.com/ajaxSuccess/) will be passed the request object, which has a *text* property that can be passed to the parse function. The code above is just to show how to approach parsing it, please modify to suit whatever you want to do. – RobG Apr 11 '17 at 23:18

1 Answers1

0

In the code:

for (var chunk in entry.split('\s')) {
  alert("I am looking at something after a space. Chunk:"); //works
  alert(chunk);

you are creating a new Array on every iteration. chunk will be assigned the property names of the Array, probably starting with 0 so alert(chunk) always returns 0 (and possibly goes into an endless loop).

If you are trying to parse the output2.txt sample, then perhaps the following is a start. It splits the text into records on the newline character, then processes each record by splitting off what appear to be text fields separated by '|' characters, then creates an array of arrays of what appear to be coordinate pairs separated by a colon ':' character.

Any further processing is up to you, hopefully this gets you started.

var text = '1 | human|man|woman|person|homo sapiens |  309,257:310,257:309,257:308,258:309,257:306,258:307,258:308,258:305,258:306,258:360,290:360,291:360,292:361,293:361,294:361,295:361,296:362,297:362,298:362,299' + 
'\n' +
'\n1 | medulla oblongata | 121,650:121,650:121,650' +
'\n' +
'1 | pancreatic duct|duct of Wirsung |  374,298:374,296:374,297:374,298:374,294:374,295:374,296:373,294:374,294:373,293:336,331:336,332:337,333:337,334:338,335:338,336:339,337:339,337:339,338:340,339:422,420:422,420:423,420:424,420:425,420:425,420:426,420:426,420:426,419:426,420:442,386:443,386:443,386:443,385:444,384:444,384:444,383:444,384:444,383:444,383:445,382:445,382:445,381:445,382:445,380:445,381:445,378:445,379:445,380:445,378:414,325:412,324:413,324:414,325:412,324:412,322:412,323:412,324:411,321:412,322:377,298:375,298:376,298:377,298:375,298:375,298:375,299:375,299:374,298:375,299';

function parseText(s) {

  // Split text on newlines to get records
  var records = s.split(/\n/)

  // Process each record, split fields from coords
  var result = records.reduce(function(acc, rec) {

    // If the record has some data, indicated by a '|' character
    if (/\|/.test(rec)) {

      // remove whitespace around the '|' separator
      rec = rec.replace(/\s*\|\s*/g, '|');
    
      // Get the text fields
      var idx = rec.lastIndexOf('|');
      var obj = {fields: rec.substring(0,idx).split(/\|/)};
      
      // Get the coordinates
      obj.coords = rec.substring(idx+1).split(':').map(function(v) {
        return v.split(',');
      });

      // Add to accumulator
      acc.push(obj);
    }

    return acc;
  }, []);
  return result;
}

console.log(parseText(text));
RobG
  • 142,382
  • 31
  • 172
  • 209
  • thank you for this code. If I want to incorporate this into the project and still need to use AJAX, do I need to convert my text file contents to a String? If so, would you know how to do that? I was only able to find this thread (http://stackoverflow.com/a/196510) on putting the text file contents into a variable, but using this code with yours gave me a "Uncaught TypeError: s.split is not a function" error, perhaps implying that I do need to find some other way to convert my file contents to a String. – Sue Techie Apr 11 '17 at 22:21
  • Also, you stated the result of parseText(text) is an array of arrays. To distinguish better, I will call the main array, Array, and the arrays inside of Array, coor_Arrays. Is the datatype in each coor_Array an Object? I am trying to parse within each coor_Array to output two numbers, the x and y coordinates, now, but I can only output one thing. – Sue Techie Apr 11 '17 at 22:56