+ point_equal: function(a, b, epsilon) {
+ return Math.abs(a[0] - b[0]) < epsilon &&
+ Math.abs(a[1] - b[1]) < epsilon &&
+ Math.abs(a[2] - b[2]) < epsilon;
+ },
+ degenerate_face_epsilon: 1e-10,
+ is_degenerate: function(a, b, c) {
+ return this.point_equal(a, b, this.degenerate_face_epsilon) ||
+ this.point_equal(b, c, this.degenerate_face_epsilon) ||
+ this.point_equal(c, a, this.degenerate_face_epsilon);
+ },
+ validate: function(points) {
+ // Do a little validation
+ if (points.length % 3 != 0) {
+ alert("Points list length not divisble by 3!");
+ }
+ var nan_count = 0;
+ var nan_point_count = 0;
+ var nan_face_count = 0;
+ for (var i = 0; i < points.length/3; i++) {
+ var nan_in_face = false;
+ for (var j = 0; j < 3; j++) {
+ var nan_in_point = false;
+ for (var k = 0; k < 3; k++) {
+ if (isNaN(points[i*3+j][k])) {
+ nan_count++;
+ nan_in_point = true;
+ nan_in_face = true;
+ }
+ }
+ if (nan_in_point) nan_point_count ++;
+ }
+ if (nan_in_face) nan_face_count ++;
+ }
+ if (nan_count != 0) {
+ alert(nan_count + " NaNs in " + nan_point_count + " points in " + nan_face_count + " faces (" + (100 * nan_face_count / (points.length/3)) + "% of faces).");
+ }
+ },
+ remove_degenerate_faces: function(points) {
+ // Note: This modifies points
+ var degenerate_face_count = 0;
+ for (var i = 0; i < points.length/3; i++) {
+ if (this.is_degenerate(points[i*3+0],
+ points[i*3+1],
+ points[i*3+2])) {
+ points.splice(i*3, 3);
+ i--;
+ degenerate_face_count ++;
+ }
+ }
+ if (degenerate_face_count != 0) {
+ console.log("Removed " + degenerate_face_count + " degenerate faces");
+ }
+ return points;
+ },
+ to_stl: function(points, name) {
+ var stl = "solid " + name + "\n";
+ for (var i = 0; i < points.length/3; i++) {
+ var a = points[i*3+0];
+ var b = points[i*3+1];
+ var c = points[i*3+2];
+ var normal = this.normal(a, b, c);
+ stl += "facet normal " + normal[0] + " " + normal[1] + " " + normal[2] + "\n" +
+ "outer loop\n" +
+ "vertex " + a[0] + " " + a[1] + " " + a[2] + "\n"+
+ "vertex " + b[0] + " " + b[1] + " " + b[2] + "\n"+
+ "vertex " + c[0] + " " + c[1] + " " + c[2] + "\n"+
+ "endloop\n" +
+ "endfacet\n";
+ }
+ stl += "endsolid " + name + "\n";
+ return stl;
+ },