EdgesGeometry constructor

EdgesGeometry(
  1. BufferGeometry geometry,
  2. dynamic thresholdAngle
)

Implementation

EdgesGeometry(BufferGeometry geometry, thresholdAngle) : super() {
  parameters = {"thresholdAngle": thresholdAngle};

  thresholdAngle = (thresholdAngle != null) ? thresholdAngle : 1;

  var precisionPoints = 4;
  var precision = Math.pow(10, precisionPoints);
  var thresholdDot = Math.cos(MathUtils.DEG2RAD * thresholdAngle);

  var indexAttr = geometry.getIndex();
  var positionAttr = geometry.getAttribute('position');
  var indexCount = indexAttr != null ? indexAttr.count : positionAttr.count;

  var indexArr = [0, 0, 0];
  var vertKeys = ['a', 'b', 'c'];
  Map hashes = {};

  var edgeData = {};
  List<double> vertices = [];
  for (var i = 0; i < indexCount; i += 3) {
    if (indexAttr != null) {
      indexArr[0] = indexAttr.getX(i)!.toInt();
      indexArr[1] = indexAttr.getX(i + 1)!.toInt();
      indexArr[2] = indexAttr.getX(i + 2)!.toInt();
    } else {
      indexArr[0] = i;
      indexArr[1] = i + 1;
      indexArr[2] = i + 2;
    }

    var a = _triangle.a;
    var b = _triangle.b;
    var c = _triangle.c;

    a.fromBufferAttribute(positionAttr, indexArr[0]);
    b.fromBufferAttribute(positionAttr, indexArr[1]);
    c.fromBufferAttribute(positionAttr, indexArr[2]);
    _triangle.getNormal(_normal);

    // create hashes for the edge from the vertices
    hashes[0] = "${a.x},${a.y},${a.z}";
    hashes[1] = "${b.x},${b.y},${b.z}";
    hashes[2] = "${c.x},${c.y},${c.z}";

    // skip degenerate triangles
    if (hashes[0] == hashes[1] ||
        hashes[1] == hashes[2] ||
        hashes[2] == hashes[0]) {
      continue;
    }

    // iterate over every edge
    for (var j = 0; j < 3; j++) {
      // get the first and next vertex making up the edge
      var jNext = (j + 1) % 3;
      var vecHash0 = hashes[j];
      var vecHash1 = hashes[jNext];
      var v0 = _triangle[vertKeys[j]];
      var v1 = _triangle[vertKeys[jNext]];

      var hash = "${vecHash0}_$vecHash1";
      var reverseHash = "${vecHash1}_$vecHash0";

      if (edgeData.containsKey(reverseHash) &&
          edgeData[reverseHash] != null) {
        // if we found a sibling edge add it into the vertex array if
        // it meets the angle threshold and delete the edge from the map.
        if (_normal.dot(edgeData[reverseHash]["normal"]) <= thresholdDot) {
          vertices
              .addAll([v0.x.toDouble(), v0.y.toDouble(), v0.z.toDouble()]);
          vertices
              .addAll([v1.x.toDouble(), v1.y.toDouble(), v1.z.toDouble()]);
        }

        edgeData[reverseHash] = null;
      } else if (!(edgeData.containsKey(hash))) {
        // if we've already got an edge here then skip adding a new one
        edgeData[hash] = {
          "index0": indexArr[j],
          "index1": indexArr[jNext],
          "normal": _normal.clone(),
        };
      }
    }
  }

  // iterate over all remaining, unmatched edges and add them to the vertex array
  for (var key in edgeData.keys) {
    if (edgeData[key] != null) {
      var _ed = edgeData[key];
      var index0 = _ed["index0"];
      var index1 = _ed["index1"];
      _v0.fromBufferAttribute(positionAttr, index0);
      _v1.fromBufferAttribute(positionAttr, index1);

      vertices.addAll([_v0.x.toDouble(), _v0.y.toDouble(), _v0.z.toDouble()]);
      vertices.addAll([_v1.x.toDouble(), _v1.y.toDouble(), _v1.z.toDouble()]);
    }
  }

  setAttribute('position',
      Float32BufferAttribute(Float32Array.from(vertices), 3, false));
}