diff --git a/web/app/math/qr.js b/web/app/math/qr.js index cd940f29..458f7edd 100644 --- a/web/app/math/qr.js +++ b/web/app/math/qr.js @@ -18,7 +18,7 @@ TCAD.math.QR = function(matrix) { var vec = TCAD.math.vec; this.matrix = matrix; var nR = this.matrix.length; - var nC = this.matrix[0].length; + var nC = nR == 0 ? 0 : this.matrix[0].length; this.qrRankingThreshold = 1e-30; //?? this.solvedCols = Math.min(nR, nC); diff --git a/web/app/math/vector.js b/web/app/math/vector.js index 951bf317..5c98dda9 100644 --- a/web/app/math/vector.js +++ b/web/app/math/vector.js @@ -50,10 +50,31 @@ TCAD.Vector.prototype.minus = function(vector) { return new TCAD.Vector(this.x - vector.x, this.y - vector.y, this.z - vector.z); }; +TCAD.Vector.prototype._minus = function(vector) { + this.x -= vector.x; + this.y -= vector.y; + this.z -= vector.z; + return this; +}; + +TCAD.Vector.prototype._minusXYZ = function(x, y, z) { + this.x -= x; + this.y -= y; + this.z -= z; + return this; +}; + TCAD.Vector.prototype.plus = function(vector) { return new TCAD.Vector(this.x + vector.x, this.y + vector.y, this.z + vector.z); }; +TCAD.Vector.prototype._plus = function(vector) { + this.x += vector.x; + this.y += vector.y; + this.z += vector.z; + return this; +}; + TCAD.Vector.prototype.normalize = function() { var mag = this.length(); if (mag == 0.0) { diff --git a/web/app/sketcher/constr/solver.js b/web/app/sketcher/constr/solver.js index e974deff..2f22a7ad 100644 --- a/web/app/sketcher/constr/solver.js +++ b/web/app/sketcher/constr/solver.js @@ -206,6 +206,12 @@ TCAD.parametric.lock2Equals2 = function(constrs, locked) { }; TCAD.parametric.diagnose = function(sys) { + if (sys.constraints.length == 0 || sys.params.length == 0) { + return { + conflict : false, + dof : 0 + } + } var jacobian = sys.makeJacobian(); var qr = new TCAD.math.QR(jacobian); return { @@ -231,13 +237,18 @@ TCAD.parametric.prepare = function(constrs, locked, aux, alg) { sys.setParams(point); return sys.makeJacobian(); }; + var nullResult = { + evalCount : 0, + error : 0, + returnCode : 1 + }; function solve(rough, alg) { - if (constrs.length == 0) return; - if (sys.params.length == 0) return; + if (constrs.length == 0) return nullResult; + if (sys.params.length == 0) return nullResult; if (TCAD.parametric.diagnose(sys).conflict) { console.log("Conflicting or redundant constraints. Please fix your system."); - return; + return nullResult; } switch (alg) { diff --git a/web/app/sketcher/fetchers.js b/web/app/sketcher/fetchers.js index ae60da45..969ada54 100644 --- a/web/app/sketcher/fetchers.js +++ b/web/app/sketcher/fetchers.js @@ -102,3 +102,24 @@ TCAD.TWO.ParametricManager.prototype._fetchTwoLines = function(objs) { } return lines; }; + +TCAD.TWO.utils._fetchSketchObjects = function(objs, silent, matching) { + var fetched = []; + for (var i = 0; i < objs.length; ++i) { + for (var j = 0; j < matching.length; j++) { + if (objs[i]._class == matching[j]) { + fetched[j] = objs[i]; + matching[j] = null; + } + } + } + if (fetched.length != matching.length) { + if (silent) { + return null; + } else { + throw "Illegal Argument. " + matching + " required"; + } + } + return fetched; +}; + diff --git a/web/app/sketcher/helpers.js b/web/app/sketcher/helpers.js new file mode 100644 index 00000000..255d0bb6 --- /dev/null +++ b/web/app/sketcher/helpers.js @@ -0,0 +1,123 @@ + + +TCAD.TWO.FilletTool = function(viewer) { + this.viewer = viewer; +}; + +TCAD.TWO.FilletTool.prototype.makeFillet = function(point1, point2) { + function shrink(point1) { + point1.parent.a; + if (point1.id === point1.parent.a.id) { + var a = point1.parent.b; + var b = point1.parent.a; + } else { + var a = point1.parent.a; + var b = point1.parent.b; + } + var d = TCAD.math.distanceAB(a, b); + k = 4 / 5; + b.x = a.x + (b.x - a.x) * k; + b.y = a.y + (b.y - a.y) * k; + return new TCAD.Vector(a.x - b.x, a.y - b.y, 0); + } + + var v1 = shrink(point1); + var v2 = shrink(point2); + + if (v1.cross(v2).z > 0) { + var _ = point1; + point1 = point2; + point2 = _; + } + + var vec = new TCAD.Vector(); + vec.setV(point2); + vec._minus(point1); + vec._multiply(0.5); + vec._plus(point1); + + var arc = new TCAD.TWO.Arc( + new TCAD.TWO.EndPoint(point1.x, point1.y), + new TCAD.TWO.EndPoint(point2.x, point2.y), + new TCAD.TWO.EndPoint(vec.x, vec.y)) + point1.parent.layer.objects.push(arc); + var pm = this.viewer.parametricManager; + arc.stabilize(this.viewer); + pm._add(new TCAD.TWO.Constraints.Tangent( arc, point1.parent)); + pm._add(new TCAD.TWO.Constraints.Tangent( arc, point2.parent)); + pm._add(new TCAD.TWO.Constraints.Coincident( arc.a, point1)); + pm._add(new TCAD.TWO.Constraints.Coincident( arc.b, point2)); + + var solver = pm.solveWithLock([]); +// var solver = pm.solveWithLock([point1._x, point1._y, point2._x, point2._y]); + pm.notify(); + this.viewer.refresh(); +}; + +TCAD.TWO.FilletTool.prototype.mouseup = function(e) { + var candi = this.getCandidate(e); + if (candi == null) return; + var point1 = candi[0]; + var point2 = candi[1]; + + var pm = this.viewer.parametricManager; + for (var i = 0; i < pm.subSystems.length; i++) { + var subSys = pm.subSystems[i]; + for (var j = 0; j < subSys.constraints.length; j++) { + var c = subSys.constraints[j]; + if (c.NAME === 'coi' && + ((c.a.id === point1.id && c.b.id === point2.id) || + (c.b.id === point1.id && c.a.id === point2.id))) { + pm.remove(c); + this.makeFillet(point1, point2); + this.viewer.deselectAll(); + return; + } + } + } +}; + +TCAD.TWO.FilletTool.prototype.getCandidate = function(e) { + var picked = this.viewer.pick(e); + if (picked.length > 0) { + function isLine(line) { + return line != null && line._class === 'TCAD.TWO.Segment'; + } + var res = TCAD.TWO.utils._fetchSketchObjects(picked, true, ['TCAD.TWO.EndPoint']); + if (res == null) return null; + var point1 = res[0]; + if (!isLine(point1.parent)) return; + var line2 = null; + for (var i = 0; i < point1.linked.length; i++) { + var point2 = point1.linked[i]; + if (isLine(point2.parent)) { + return [point1, point2]; + } + } + } + return null; +}; + +TCAD.TWO.FilletTool.prototype.keydown = function(e) {}; +TCAD.TWO.FilletTool.prototype.keypress = function(e) {}; +TCAD.TWO.FilletTool.prototype.keyup = function(e) {}; +TCAD.TWO.FilletTool.prototype.cleanup = function(e) {}; + +TCAD.TWO.FilletTool.prototype.mousemove = function(e) { + var needRefresh = false; + if (this.viewer.selected.length != 0) { + this.viewer.deselectAll(); + needRefresh = true; + } + var candi = this.getCandidate(e); + if (candi != null) { + this.viewer.mark(candi[0], TCAD.TWO.Styles.SNAP); + needRefresh = true; + } + if (needRefresh) { + this.viewer.refresh(); + } +}; +TCAD.TWO.FilletTool.prototype.mousedown = function(e) {}; +TCAD.TWO.FilletTool.prototype.mousewheel = function(e) {}; + diff --git a/web/app/sketcher/main2d.js b/web/app/sketcher/main2d.js index 6b37d97f..7155f805 100644 --- a/web/app/sketcher/main2d.js +++ b/web/app/sketcher/main2d.js @@ -41,6 +41,10 @@ TCAD.App2D = function() { this.registerAction('pan', "Pan", function () { app.viewer.toolManager.releaseControl(); }); + + this.registerAction('addFillet', "Add Fillet", function () { + app.viewer.toolManager.takeControl(new TCAD.TWO.FilletTool(app.viewer)); + }); this.registerAction('addDim', "Add Dimension", function () { app.viewer.toolManager.takeControl(new TCAD.TWO.AddDimTool(app.viewer, app.viewer.dimLayer, function(a,b) {return new TCAD.TWO.Dimension(a,b)} )); diff --git a/web/app/sketcher/parametric.js b/web/app/sketcher/parametric.js index 805e6073..a57269e9 100644 --- a/web/app/sketcher/parametric.js +++ b/web/app/sketcher/parametric.js @@ -298,6 +298,12 @@ TCAD.TWO.ParametricManager.prototype.solve = function() { solver.sync(); }; +TCAD.TWO.ParametricManager.prototype.solveWithLock = function(lock) { + var solver = this.prepare(lock); + solver.solve(false); + solver.sync(); +}; + TCAD.TWO.ParametricManager.prototype.prepare = function(locked) { return this._prepare(locked, this.subSystems); }; @@ -313,11 +319,12 @@ TCAD.TWO.ParametricManager.prototype._prepare = function(locked, subSystems) { solve : function(rough) { for (var i = 0; i < solvers.length; i++) { var alg = subSystems[i].alg; - if (solvers[i].solve(rough, alg) !== 1) { - //alg = alg == 1 ? 2 : 1; - //if (solvers[i].solve(rough, alg) == 1) { - // subSystems[i].alg = alg; - //} + var res = solvers[i].solve(rough, alg); + if (res.returnCode !== 1) { + alg = alg == 1 ? 2 : 1; + if (solvers[i].solve(rough, alg).returnCode == 1) { + subSystems[i].alg = alg; + } } } }, @@ -351,6 +358,11 @@ TCAD.TWO.ParametricManager.prototype.prepareForSubSystem = function(locked, subS return Math.abs(p1.get() - p2.get()) <= 0.000001 } var system = this.__getSolveData(subSystem, []); + system.sort(function(a, b){ + a = a[0] === 'equal' ? 1 : 2; + b = b[0] === 'equal' ? 1 : 2; + return a - b; + }); var tuples = []; for (i = 0; i < system.length; ++i) { var c = system[i]; diff --git a/web/sketcher.html b/web/sketcher.html index 8ad07b43..e348a889 100644 --- a/web/sketcher.html +++ b/web/sketcher.html @@ -189,6 +189,7 @@ + @@ -274,6 +275,7 @@ -->