diff --git a/web/app/ctrl.js b/web/app/ctrl.js index 3a4422dc..766018ba 100644 --- a/web/app/ctrl.js +++ b/web/app/ctrl.js @@ -10,9 +10,8 @@ TCAD.UI = function(app) { var actionsF = gui.addFolder('Add Object'); var actions = new TCAD.UI.Actions(this); - actionsF.add(actions.tools, 'polygon'); - actionsF.add(actions.tools, 'line'); - actionsF.add(actions.tools, 'commit'); + actionsF.add(actions.tools, 'extrude'); + actionsF.add(actions.tools, 'cut'); actionsF.add(actions.tools, 'edit'); actionsF.open(); @@ -23,21 +22,18 @@ TCAD.UI = function(app) { TCAD.UI.Actions = function(scope) { this.tools = { - polygon : function() { - scope.viewer.toolMgr.tool = new TCAD.PolygonTool(scope.viewer.selectionMgr.selection[0], scope.viewer); + + extrude : function() { + scope.app.extrude(); }, - line : function() { - scope.viewer.toolMgr.tool = new TCAD.LineTool(scope.viewer.selectionMgr.selection[0]); - }, - - commit : function() { - scope.viewer.toolMgr.commit(); + cut : function() { + }, edit : function() { scope.app.sketchFace(); } - } + }; }; diff --git a/web/app/engine.js b/web/app/engine.js index 626853d7..c0d48dc0 100644 --- a/web/app/engine.js +++ b/web/app/engine.js @@ -77,7 +77,7 @@ TCAD.utils.createLine = function (a, b, color) { return new THREE.Segment(geometry, material); }; -TCAD.utils.createSolid = function(faces) { +TCAD.utils.createSolidMesh = function(faces) { var geometry = new TCAD.Solid(faces); geometry.dynamic = true; //true by default var material = new THREE.MeshPhongMaterial({ @@ -85,7 +85,8 @@ TCAD.utils.createSolid = function(faces) { color: '#B0C4DE', shininess: 0 }); - return new THREE.Mesh( geometry, material ); + geometry.meshObject = new THREE.Mesh(geometry, material); + return geometry.meshObject; }; TCAD.utils.fixCCW = function(path, normal) { @@ -122,6 +123,82 @@ TCAD.utils.equal = function(v1, v2) { return TCAD.utils.areEqual(v1, v2, TCAD.TOLERANCE); }; +TCAD.utils.sketchToPolygons = function(geom) { + + var dict = {}; + var points = {}; + var lines = geom.lines; + + function memDir(a, b) { + var dirs = dict[a]; + if (!dirs) { + dirs = []; + dict[a] = dirs; + } + dirs.push(b); + } + + for (var i = 0; i < lines.length; i++) { + var a = lines[i][0]; + var b = lines[i][1]; + points[a] = true; + points[b] = true; + memDir(a, b); + memDir(b, a); + } + + var visited = {}; + var polygons = []; + + function ar_eq(arr1, arr2) { + return arr1 + "" === arr2 + ""; + } + + function go(p, poly, closePoints) { + var closePoint = null; + for (;;) { + var next = dict[p]; + if (!!visited[p] || next.length == 0) { + break; + } + poly.push(p); + visited[p] = true; + p = next[0]; + + if (!!closePoints[p]) { + closePoint = p; + break; + } + if (next.length > 1) { + //ramification + for (var ni = 1; ni < next.length; ni++) { + var n = next[ni]; + var _v = {}; + _v[p] = true; + go(n, [p], _v); + } + closePoints[p] = true; + } + if (closePoint != null) { + var toCutOff = 0; + for (var i = 0; i < poly.length; i++) { + var p = poly[i]; + if (ar_eq(p, closePoint)) { + toCutOff = i; + break; + } + } + poly.splice(0, toCutOff); + if (poly.length > 2) polygons.push(poly); + } + } + } + + for (var p in points) { + go(p, [], [p]); + } + return polygons; +}; TCAD.geom = {}; @@ -218,7 +295,7 @@ TCAD.Solid = function(polygons) { for ( var h = 0; h < poly.holes; ++ h ) { pushVertices(poly.holes[ h ]); } - var polyFace = new TCAD.SketchFace(poly); + var polyFace = new TCAD.SketchFace(this, poly); this.polyFaces.push(polyFace); for ( var i = 0; i < faces.length; ++ i ) { @@ -252,12 +329,14 @@ TCAD.Solid = function(polygons) { TCAD.Solid.prototype = Object.create( THREE.Geometry.prototype ); -TCAD.SketchFace = function(poly) { +TCAD.SketchFace = function(solid, poly) { this.id = TCAD.geom.FACE_COUNTER++; + this.solid = solid; this.polygon = poly; this.faces = []; this.geom = null; this.sketch3DGroup = null; + this.sketchGeom = null; }; TCAD.SketchFace.prototype.SKETCH_MATERIAL = new THREE.LineBasicMaterial({ @@ -292,6 +371,8 @@ TCAD.SketchFace.prototype.syncSketches = function(geom) { var line = new THREE.Segment(lg, this.SKETCH_MATERIAL); this.sketch3DGroup.add(line); } + this.sketchGeom = geom; + this.sketchGeom.depth = depth; }; /** diff --git a/web/app/main.js b/web/app/main.js index 67f8aca6..0f71ed73 100644 --- a/web/app/main.js +++ b/web/app/main.js @@ -5,9 +5,10 @@ TCAD.App = function() { this.id = "DEFAULT"; this.viewer = new TCAD.Viewer(); this.ui = new TCAD.UI(this); + this.craft = new TCAD.Craft(this); - var box = TCAD.utils.createSolid(TCAD.utils.createBox(500)); + var box = TCAD.utils.createSolidMesh(TCAD.utils.createBox(500)); this.viewer.scene.add( box ); for (var i = 0; i < box.geometry.polyFaces.length; i++) { var sketchFace = box.geometry.polyFaces[i]; @@ -33,7 +34,7 @@ TCAD.App = function() { var prefix = "TCAD.projects."+app.id+".sketch."; if (evt.key.indexOf(prefix) < 0) return; - sketchFaceId = evt.key.substring(prefix.length); + var sketchFaceId = evt.key.substring(prefix.length); for (var oi = 0; oi < viewer.scene.children.length; ++oi) { var obj = viewer.scene.children[oi]; @@ -77,3 +78,21 @@ TCAD.App.prototype.sketchFace = function() { window.open("canvas.html#" + faceStorageKey.substring(14), "Edit Sketch", "height=900,width=1200"); }; + +TCAD.App.prototype.extrude = function() { + + if (this.viewer.selectionMgr.selection.length == 0) { + return; + } + 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); + }); +}; + +TCAD.App.prototype.cut = function(face, depth) { + +}; diff --git a/web/app/viewer.js b/web/app/viewer.js index dae9e04c..936cd081 100644 --- a/web/app/viewer.js +++ b/web/app/viewer.js @@ -229,7 +229,7 @@ TCAD.PolygonTool.prototype.commit = function() { var n = this.workArea.polygon.normal; var _2d = new TCAD.Polygon(this.poly.shell, this.poly.holes, n); - var solid = TCAD.utils.createSolid(TCAD.geom.extrude(_2d, n.multiply(1.1))); + var solid = TCAD.utils.createSolidMesh(TCAD.geom.extrude(_2d, n.multiply(1.1))); this.workArea.sketch.group.parent.add(solid); }; @@ -268,6 +268,6 @@ TCAD.LineTool.prototype.commit = function() { // var n = this.workArea.polygon.normal; // var _2d = new TCAD.Polygon(this.poly.shell, this.poly.holes, n); // -// var solid = TCAD.utils.createSolid(TCAD.geom.extrude(_2d, n.multiply(1.1))); +// var solid = TCAD.utils.createSolidMesh(TCAD.geom.extrude(_2d, n.multiply(1.1))); // this.workArea.sketch.group.parent.add(solid); }; diff --git a/web/app/workbench.js b/web/app/workbench.js index f7879b8e..0ebcd0aa 100644 --- a/web/app/workbench.js +++ b/web/app/workbench.js @@ -7,6 +7,7 @@ TCAD.workbench.readSketchGeom = function(sketch) { for (var i = 0; i < sketch.layers[l].length; ++i) { var obj = sketch.layers[l][i]; if (obj.edge !== undefined) continue; + if (!!obj.aux) continue; if (obj._class === 'TCAD.TWO.Segment') { out.lines.push([ obj.points[0][1][1], obj.points[0][2][1], //x,y @@ -19,4 +20,63 @@ TCAD.workbench.readSketchGeom = function(sketch) { } return out; } -}; \ No newline at end of file +}; + +TCAD.craft = {}; + +TCAD.craft.extrude = function(app, face, height) { + + var savedFace = localStorage.getItem(app.faceStorageKey(face.id)); + if (savedFace == null) return; + + var geom = TCAD.workbench.readSketchGeom(JSON.parse(savedFace)); + var polygons2D = TCAD.utils.sketchToPolygons(geom); + var solid = face.solid; + + var normal = face.polygon.normal; + var depth = null; + var sketchedPolygons = []; + for (var i = 0; i < polygons2D.length; i++) { + var poly2D = polygons2D[i]; + if (poly2D.length < 3) continue; + + if (depth == null) { + 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 + depth = normal.dot(face.polygon.shell[0]); + } + + var shell = []; + for (var m = 0; m < poly2D.length; ++m) { + var a = _3dTransformation.apply(new TCAD.Vector(poly2D[m][0], poly2D[m][1], depth)); + shell.push(a) + } + sketchedPolygons.push(new TCAD.Polygon(shell)); + } + var newSolidFaces = []; + for (var i = 0; i < sketchedPolygons.length; i++) { + var extruded = TCAD.geom.extrude(sketchedPolygons[i], normal.multiply(height)); + newSolidFaces = newSolidFaces.concat(newSolidFaces, extruded); + } + + for (var i = 0; i < solid.polyFaces.length; i++) { + newSolidFaces.push(solid.polyFaces[i].polygon); + } + return newSolidFaces; +}; + +TCAD.Craft = function(app) { + this.app = app; + this.history = []; +}; + +TCAD.Craft.prototype.current = function() { + return this.history[this.history.length - 1]; +}; + +TCAD.Craft.prototype.modify = function(solid, modification) { + var faces = modification(); + this.app.viewer.scene.remove( solid.meshObject ); + this.app.viewer.scene.add( TCAD.utils.createSolidMesh(faces) ); + this.app.viewer.render(); +}; diff --git a/web/canvas.html b/web/canvas.html index 07149274..f0f96509 100644 --- a/web/canvas.html +++ b/web/canvas.html @@ -31,6 +31,7 @@ +