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