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 @@ +