diff --git a/web/app/ctrl.js b/web/app/ctrl.js
index 766018ba..9cb581f1 100644
--- a/web/app/ctrl.js
+++ b/web/app/ctrl.js
@@ -28,7 +28,7 @@ TCAD.UI.Actions = function(scope) {
},
cut : function() {
-
+ scope.app.cut();
},
edit : function() {
diff --git a/web/app/engine.js b/web/app/engine.js
index fd89883d..52c6b1eb 100644
--- a/web/app/engine.js
+++ b/web/app/engine.js
@@ -263,7 +263,7 @@ TCAD.Solid = function(polygons, material) {
this.dynamic = true; //true by default
this.meshObject = new THREE.Mesh(this, material);
-
+
this.polyFaces = [];
var scope = this;
function pushVertices(vertices) {
@@ -328,7 +328,6 @@ TCAD.SketchFace = function(solid, poly) {
this.solid = solid;
this.polygon = poly;
this.faces = [];
- this.geom = null;
this.sketch3DGroup = null;
if (this.sketchGeom != null) {
@@ -353,7 +352,6 @@ TCAD.SketchFace.prototype.syncSketches = function(geom) {
this.solid.meshObject.add(this.sketch3DGroup);
}
- this.geom = [];
var _3dTransformation = new TCAD.Matrix().setBasis(TCAD.geom.someBasis(this.polygon.shell, normal));
//we lost depth or z off in 2d sketch, calculate it again
var depth = normal.dot(this.polygon.shell[0]);
diff --git a/web/app/main.js b/web/app/main.js
index bd3afb13..be5c3aeb 100644
--- a/web/app/main.js
+++ b/web/app/main.js
@@ -92,7 +92,18 @@ TCAD.App.prototype.extrude = function() {
});
};
-TCAD.App.prototype.cut = function(face, depth) {
+TCAD.App.prototype.cut = function() {
+
+ if (this.viewer.selectionMgr.selection.length == 0) {
+ return;
+ }
+ var polyFace = this.viewer.selectionMgr.selection[0];
+ var depth = prompt("Depth", "50");
+
+ var app = this;
+ this.craft.modify(polyFace.solid, function() {
+ return TCAD.craft.cut(app, polyFace, polyFace.solid.polyFaces, depth);
+ });
};
@@ -102,9 +113,4 @@ TCAD.App.prototype.save = function() {
var polyFace = this.viewer.selectionMgr.selection[0];
var height = prompt("Height", "50");
-
- var app = this;
- this.craft.modify(polyFace.solid, function() {
- return TCAD.craft.extrude(app, polyFace, height);
- });
};
\ No newline at end of file
diff --git a/web/app/workbench.js b/web/app/workbench.js
index d769a495..d259dae4 100644
--- a/web/app/workbench.js
+++ b/web/app/workbench.js
@@ -18,8 +18,8 @@ TCAD.workbench.readSketchGeom = function(sketch) {
}
}
}
- return out;
}
+ return out;
};
TCAD.workbench.serializeSolid = function(solid) {
@@ -31,7 +31,7 @@ TCAD.workbench.serializeSolid = function(solid) {
faceData.id = face.id;
}
return data;
-}
+};
TCAD.workbench.applyHistory = function(history) {
@@ -90,7 +90,7 @@ TCAD.craft.extrude = function(app, face, faces, height) {
var normal = face.polygon.normal;
for (var i = 0; i < sketchedPolygons.length; i++) {
var extruded = TCAD.geom.extrude(sketchedPolygons[i], normal.multiply(height));
- newSolidFaces = newSolidFaces.concat(newSolidFaces, extruded);
+ newSolidFaces = newSolidFaces.concat(extruded);
}
face.polygon.__face = undefined;
@@ -102,6 +102,154 @@ TCAD.craft.extrude = function(app, face, faces, height) {
};
+TCAD.craft._mergeCSGPolygons = function(cgsPolygons) {
+ var pointToPoly = {};
+ var points = [];
+ function pkey(point) {
+ return point.x + ":" + point.y + ":" + point.z;
+ }
+ function pnkey(point, normal) {
+ return pkey(point) + ":" + pkey(normal);
+ }
+ var pi, vi, poly, key, vert;
+ var pid = 0;
+ for (pi = 0; pi < cgsPolygons.length; pi++) {
+ poly = cgsPolygons[pi];
+ poly.__tcad_id = pi;
+ for (vi = 0; vi < poly.vertices.length; vi++) {
+ vert = poly.vertices[vi];
+ key = pkey(vert.pos);
+ points.push(vert.pos);
+ var pList = pointToPoly[key];
+ if (pList === undefined) {
+ pointToPoly[key] = [poly];
+ } else {
+ pList.push(poly);
+ }
+ }
+ }
+
+ function sharesEdge(key1, key2, normalKey) {
+ var pp1 = pointToPoly[key1];
+ for (var ii = 0; ii < pp1.length; ii++) {
+ var poly = pp1[ii];
+ if (pkey(poly.plane.normal) === normalKey) {
+ continue;
+ }
+ for (var vi = 0; vi < poly.vertices.length; vi++) {
+ if (pkey(poly.vertices[vi].pos) === key2 && ii === 1) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ function vec(p) {
+ var v = new TCAD.Vector();
+ v.setV(p);
+ return v;
+ }
+
+ var paths = [];
+ var path;
+ var visited = {};
+ function nextUnvisitedNormal(p, key) {
+ var polygons = pointToPoly[key];
+ for (var pi = 0; pi < polygons.length; pi++) {
+ var poly = polygons[pi];
+ var nkey = pnkey(p, poly.plane.normal);
+ if (visited[nkey] === undefined) return poly.plane.normal;
+ }
+ return null;
+ }
+ var p, pCurr, keyCurr, keyPrev, keyStart, pStart;
+ for (var i = 0; i < points.length; i++) {
+ var point = points[i];
+ key = pkey(point);
+ var normal = nextUnvisitedNormal(point, key);
+ if (normal == null) {
+ continue;
+ }
+ var normalKey = pkey(normal);
+
+ pCurr = point;
+ pStart = point;
+ keyCurr = key;
+ keyStart = key;
+
+ path = [];
+ keyPrev = null;
+
+ visited[pnkey(pCurr, normal)] = true;
+ while (pCurr != null) {
+ path.push(vec(pCurr));
+ pCurr = null;
+ var polygons = pointToPoly[keyCurr];
+ POLY:
+ for (pi = 0; pi < polygons.length; pi++) {
+ poly = polygons[pi];
+ for (vi = 0; vi < poly.vertices.length; vi++) {
+ p = poly.vertices[vi].pos;
+ key = pkey(p);
+
+ if (keyStart === key) continue;
+ if (keyCurr === key) continue;
+ if (keyPrev != null && keyPrev === key) continue;
+ var nkey = pnkey(p, poly.plane.normal);
+ console.log(nkey);
+ if (visited[nkey] !== undefined) continue;
+ visited[nkey] = true;
+
+ if (sharesEdge(keyCurr, key, normalKey)) continue;
+ pCurr = p;
+ keyPrev = keyCurr;
+ keyCurr = key;
+ break POLY;
+ }
+ }
+ }
+ if (path.length > 3) {
+ paths.push(path);
+ }
+ }
+
+ function sortPaths() {
+
+ }
+
+ return paths;
+
+};
+
+TCAD.craft._makeFromPolygons = function(polygons) {
+ var points = [];
+ var csgPolygons = [];
+ var off = 0;
+ for (var ei = 0; ei < polygons.length; ++ei) {
+ var poly = polygons[ei];
+ Array.prototype.push.apply( points, poly.shell );
+ for ( var h = 0; h < poly.holes.length; h ++ ) {
+ Array.prototype.push.apply( points, poly.holes[h] );
+ }
+ var shared = {group : poly};
+ var refs = poly.triangulate();
+ for ( var i = 0; i < refs.length; ++ i ) {
+ var a = refs[i][0] + off;
+ var b = refs[i][1] + off;
+ var c = refs[i][2] + off;
+ var csgPoly = new CSG.Polygon([
+ new CSG.Vertex(points[a], poly.normal),
+ new CSG.Vertex(points[b], poly.normal),
+ new CSG.Vertex(points[c], poly.normal)
+ ], shared);
+ csgPolygons.push(csgPoly);
+ }
+ off = points.length;
+ }
+ return csgPolygons;
+};
+
TCAD.craft.cut = function(app, face, faces, height) {
var sketchedPolygons = TCAD.craft.getSketchedPolygons3D(app, face);
@@ -109,17 +257,28 @@ TCAD.craft.cut = function(app, face, faces, height) {
var newSolidFaces = [];
var normal = face.polygon.normal;
+
+ var cutter = [];
for (var i = 0; i < sketchedPolygons.length; i++) {
- var extruded = TCAD.geom.extrude(sketchedPolygons[i], normal.multiply(height));
- newSolidFaces = newSolidFaces.concat(newSolidFaces, extruded);
+ var extruded = TCAD.geom.extrude(sketchedPolygons[i], normal.multiply( - height));
+ cutter = cutter.concat(TCAD.craft._makeFromPolygons(extruded));
}
+ var work = TCAD.craft._makeFromPolygons(faces.map(function(f){ return f.polygon }));
+
+ var cut = CSG.fromPolygons(work).subtract(CSG.fromPolygons(cutter));
face.polygon.__face = undefined;
+// return TCAD.craft._mergeCSGPolygons(cut.polygons).map(function(path) {
+// return new TCAD.Polygon(path, []);
+// });
+
+ return cut.polygons.map(function(e) {
+ return new TCAD.Polygon(e.vertices.map(
+ function(v) {
+ return new TCAD.Vector(v.pos.x, v.pos.y, v.pos.z)
+ }), [])
+ });
- for (var i = 0; i < faces.length; i++) {
- newSolidFaces.push(faces[i].polygon);
- }
- return newSolidFaces;
};
TCAD.Craft = function(app) {
@@ -135,6 +294,6 @@ TCAD.Craft.prototype.modify = function(solid, modification) {
var faces = modification();
if (faces == null) return;
this.app.viewer.scene.remove( solid.meshObject );
- this.app.viewer.scene.add( TCAD.utils.createSolidMesh(faces) );
+ this.app.viewer.scene.add(TCAD.utils.createSolidMesh(faces));
this.app.viewer.render();
};
diff --git a/web/index.html b/web/index.html
index e042ff9f..128a5a9e 100644
--- a/web/index.html
+++ b/web/index.html
@@ -13,6 +13,7 @@
+