From 17b7c8bade0604a9aafac97e92b247e48e3bef1a Mon Sep 17 00:00:00 2001 From: Val Erastov Date: Fri, 27 May 2016 20:36:44 -0700 Subject: [PATCH] convex constraint --- web/app/sketcher/constr/constraints.js | 43 ++++++++ web/app/sketcher/main2d.js | 3 + web/app/sketcher/parametric.js | 131 +++++++++++++++++++++---- web/img/vec/convex.svg | 99 +++++++++++++++++++ web/sketcher.html | 1 + 5 files changed, 257 insertions(+), 20 deletions(-) create mode 100644 web/img/vec/convex.svg diff --git a/web/app/sketcher/constr/constraints.js b/web/app/sketcher/constr/constraints.js index f3ff76b6..25f03f69 100644 --- a/web/app/sketcher/constr/constraints.js +++ b/web/app/sketcher/constr/constraints.js @@ -26,6 +26,8 @@ TCAD.constraints.create = function(name, params, values) { var _ = true, x = false; // Exclude angle value from parameters return new TCAD.constraints.ConstantWrapper(new TCAD.constraints.Angle(params), [x,x,x,x,x,x,x,x,_]); + case 'LockConvex': + return new TCAD.constraints.LockConvex(params); } }; @@ -82,6 +84,47 @@ TCAD.constraints.MinLength = function(params, distance) { } }; +TCAD.constraints.LockConvex = function(params) { + this.params = params; + + var _pcx = 0; + var _pcy = 1; + var _pax = 2; + var _pay = 3; + var _ptx = 4; + var _pty = 5; + + this.error = function() { + var cx = params[_pcx].get(); + var cy = params[_pcy].get(); + var ax = params[_pax].get(); + var ay = params[_pay].get(); + var tx = params[_ptx].get(); + var ty = params[_pty].get(); + + var crossProductNorm = (cx - ax) * (ty - ay) - (cy - ay) * (tx - ax); + + var violate = crossProductNorm < 0; + return violate ? crossProductNorm : 0; + }; + + this.gradient = function(out) { + var cx = params[_pcx].get(); + var cy = params[_pcy].get(); + var ax = params[_pax].get(); + var ay = params[_pay].get(); + var tx = params[_ptx].get(); + var ty = params[_pty].get(); + + out[_pcx] = ty-ay; + out[_pcy] = ax-tx; + out[_pax] = cy-ty; + out[_pay] = tx-cx; + out[_ptx] = ay-cy; + out[_pty] = cx-ax; + } +}; + /** @constructor */ TCAD.constraints.ConstantWrapper = function(constr, mask) { diff --git a/web/app/sketcher/main2d.js b/web/app/sketcher/main2d.js index da113840..799d73fa 100644 --- a/web/app/sketcher/main2d.js +++ b/web/app/sketcher/main2d.js @@ -193,6 +193,9 @@ TCAD.App2D = function() { this.registerAction('symmetry', "Symmetry", function () { app.viewer.parametricManager.symmetry(app.viewer.selected, prompt); }); + this.registerAction('lockConvex', "Lock Convexity", function () { + app.viewer.parametricManager.lockConvex(app.viewer.selected, alert); + }); this.registerAction('analyzeConstraint', "Analyze Constraint", function () { app.viewer.parametricManager.analyze(alert); diff --git a/web/app/sketcher/parametric.js b/web/app/sketcher/parametric.js index f6d1ca7f..52ad60b6 100644 --- a/web/app/sketcher/parametric.js +++ b/web/app/sketcher/parametric.js @@ -167,6 +167,56 @@ TCAD.TWO.ParametricManager.prototype.perpendicular = function(objs) { this.add(new TCAD.TWO.Constraints.Perpendicular(lines[0], lines[1])); }; +TCAD.TWO.ParametricManager.prototype.lockConvex = function(objs, warnCallback) { + var lines = this._fetchTwoLines(objs); + var l1 = lines[0]; + var l2 = lines[1]; + var pts =[l1.a, l1.b, l2.a, l2.b]; + function isLinked(p1, p2) { + for (var i = 0; i < p1.linked.length; ++i) { + if (p1.linked[i].id === p2.id) { + return true; + } + } + return false; + } + + function swap(arr, i1, i2) { + var _ = arr[i1]; + arr[i1] = arr[i2]; + arr[i2] = _; + } + + if (isLinked(pts[0], pts[2])) { + swap(pts, 0, 1); + } else if (isLinked(pts[0], pts[3])) { + swap(pts, 0, 1); + swap(pts, 2, 3); + } else if (isLinked(pts[1], pts[3])) { + swap(pts, 2, 3); + } else if (isLinked(pts[1], pts[2])) { + //we are good + } else { + warnCallback("Lines must be connected"); + return; + } + + var c = pts[0]; + var a = pts[1]; + var t = pts[3]; + + // ||ac x at|| > 0 + var crossNorma = (c.x - a.x) * (t.y - a.y) - (c.y - a.y) * (t.x - a.x); + + if (crossNorma < 0) { + var _ = c; + c = t; + t = _; + } + + this.add(new TCAD.TWO.Constraints.LockConvex(c, a, t)); +}; + TCAD.TWO.ParametricManager.prototype.tangent = function(objs) { var al = this._fetchArcCircAndLine(objs); var arc = al[0]; @@ -721,6 +771,25 @@ TCAD.TWO.ParametricManager.prototype.prepareForSubSystem = function(locked, subS return solver; }; +TCAD.TWO.Constraints.ParentsCollector = function() { + this.parents = []; + var parents = this.parents; + var index = {}; + function add(obj) { + if (index[obj.id] === undefined) { + index[obj.id] = obj; + parents.push(obj); + } + } + this.check = function(obj) { + if (obj.parent !== null) { + add(obj.parent); + } else { + add(obj); + } + }; +}; + TCAD.TWO.Constraints.Factory = {}; // ------------------------------------------------------------------------------------------------------------------ // @@ -1348,28 +1417,50 @@ TCAD.TWO.Constraints.Factory[TCAD.TWO.Constraints.Angle.prototype.NAME] = functi }; TCAD.TWO.Constraints.Angle.prototype.getObjects = function() { - var out = []; - var index = {}; - function add(obj) { - if (index[obj.id] === undefined) { - index[obj.id] = obj; - out.push(obj); - } - } - function check(obj) { - if (obj.parent !== null) { - add(obj.parent); - } else { - add(obj); - } - } - check(this.p1); - check(this.p2); - check(this.p3); - check(this.p4); - return out; + var collector = new TCAD.TWO.Constraints.ParentsCollector(); + collector.check(this.p1); + collector.check(this.p2); + collector.check(this.p3); + collector.check(this.p4); + return collector.parents; }; TCAD.TWO.Constraints.Angle.prototype.SettableFields = {'angle' : "Enter the angle value"}; // ------------------------------------------------------------------------------------------------------------------ // + +/** @constructor */ +TCAD.TWO.Constraints.LockConvex = function(c, a, t) { + this.c = c; + this.a = a; + this.t = t; +}; + +TCAD.TWO.Constraints.LockConvex.prototype.NAME = 'LockConvex'; +TCAD.TWO.Constraints.LockConvex.prototype.UI_NAME = 'Lock Convexity'; + +TCAD.TWO.Constraints.LockConvex.prototype.getSolveData = function() { + var params = []; + this.c.collectParams(params); + this.a.collectParams(params); + this.t.collectParams(params); + return [['LockConvex', params, []]]; +}; + +TCAD.TWO.Constraints.LockConvex.prototype.serialize = function() { + return [this.NAME, [this.c.id, this.a.id, this.t.id]]; +}; + +TCAD.TWO.Constraints.Factory[TCAD.TWO.Constraints.LockConvex.prototype.NAME] = function(refs, data) { + return new TCAD.TWO.Constraints.LockConvex(refs(data[0]), refs(data[1]), refs(data[2])); +}; + +TCAD.TWO.Constraints.LockConvex.prototype.getObjects = function() { + var collector = new TCAD.TWO.Constraints.ParentsCollector(); + collector.check(this.c); + collector.check(this.a); + collector.check(this.t); + return collector.parents; +}; + +// ------------------------------------------------------------------------------------------------------------------ // \ No newline at end of file diff --git a/web/img/vec/convex.svg b/web/img/vec/convex.svg new file mode 100644 index 00000000..1c638a83 --- /dev/null +++ b/web/img/vec/convex.svg @@ -0,0 +1,99 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/web/sketcher.html b/web/sketcher.html index 9c66071a..5e5f9a77 100644 --- a/web/sketcher.html +++ b/web/sketcher.html @@ -88,6 +88,7 @@ +