0
votes

I 'd like to load an STL, list all its vertices and get the vertices they are connected to so I can calculate their angles and distance. Would it be possible to do this with three.js ?
My idea is to load low poly stl and create connectors that I could 3D print and assemble with rods, to recreate a wireframe representation of the stl in real life. For example, load a cube stl file, and create 8 connectors that would each have 3 branches, something like the image below. enter image description here

1
yes it would be possible to do with three.js. - gaitat

1 Answers

0
votes

The way this question is worded, you really should have applied a bounty. but I was curious about how to do it, because I like your idea. Note though that even a simple stl or obj file could contain thousands of edges. That's a lot of dowels to print. Even a simple, rough sphere can contain hundreds of edges.

This function returns a list of edges and nodes.

The edges list is very simple. Each array position is an ID, and the value is the length of the edge. For example if you need to find the length of edge 15, just find edges[15]. The value will be the length of the line.

The nodes contain a list of their own edges. I believe these are stored counterclockwise, but, you'll want to test that. The winding order of each node will determine if your vertices print correctly and may still need to be resolved. These look like [0,2,4] for example. You can use these values to find their lengths. The nodes also contain an angle object. These angles are kept in a list in the same order as the edges. The property name of each node is it's local position in space delimited by a colon. For example a node's unique name might look like: "19.09830093383789:190.2113037109375:58.778526306152344"

The angles of each are radians in local space, listed in the same order as the edges. This is important: the angles are in radians in local space. If your model has a parent model with a transformation on it, you need to apply a transformation matrix to obtain world space. The model also can't have any flipped faces.

For example, this node connects to edge 0,2,and 4:

Node > "19.09830093383789:190.2113037109375:58.778526306152344"

Node.edges > [0, 2, 4]

Node.angles > [0.31415926112916176, 0.31415926112916176, 0.31415926228226293]

This will work with nodes with N number of edges. However, the model needs to be watertight to work in the real world.

function getEdges(geometry){
    var material = new THREE.LineBasicMaterial({ color: 0xff0000});
    var edges = new THREE.EdgesGeometry( geometry );
    var vertexList = edges.attributes.position.array;
    var nodes = {};
    var edges = [];
    var edgeID = 0;
    for(var i=0; i<vertexList.length;i=i+6){
      var geometry = new THREE.Geometry();
      var node1ID = vertexList[i]+":"+vertexList[i+1] +":"+ vertexList[i+2];
      var node2ID = vertexList[i+3]+":"+vertexList[i+4] +":"+ vertexList[i+5];
      var node1 = nodes[node1ID];
      var node2 = nodes[node2ID];
      if(node1 == undefined){
        node1 = {};
        node1.edges = [];
        node1.angles = [];
        nodes[node1ID] = node1;
      }
        if(node2 == undefined){
        node2 = {};
        node2.edges = [];
        node2.angles = [];
        nodes[node2ID] = node2;
      }
      var vec1 = new THREE.Vector3(vertexList[i], vertexList[i+1], vertexList[i+2]);
      var vec2 = new THREE.Vector3(vertexList[i+3], vertexList[i+4], vertexList[i+5]);
      geometry.vertices.push(vec1);
      geometry.vertices.push(vec2);
      geometry.computeLineDistances();
      var edge = new THREE.Line(geometry, material);

      node1.edges.push(edgeID);
      node1.angles.push(vec1.angleTo(vec2));

      node2.edges.push(edgeID);
      node2.angles.push(vec2.angleTo(vec1));

      edges[edgeID] = geometry.lineDistances[1];

      mesh.add(edge);
      edgeID++;
    }
    return {nodes:nodes, edges:edges};
  }

working fiddle: https://jsfiddle.net/y1hs9x4v/