From c18798e07993b7ebde1e096f4e4560a1045e89e8 Mon Sep 17 00:00:00 2001 From: Val Erastov Date: Mon, 13 Oct 2014 21:46:18 -0700 Subject: [PATCH] tangent constraint --- web/app/constr/constraints.js | 83 +++++++++++++++++++++++++++++++++++ web/app/fetchers.js | 19 ++++++++ web/app/main2d.js | 7 ++- web/app/parametric.js | 25 ++++++++++- 4 files changed, 132 insertions(+), 2 deletions(-) diff --git a/web/app/constr/constraints.js b/web/app/constr/constraints.js index 74e3928d..a61ce4cc 100644 --- a/web/app/constr/constraints.js +++ b/web/app/constr/constraints.js @@ -12,6 +12,8 @@ TCAD.constraints.create = function(name, params, values) { return new TCAD.constraints.Parallel(params); case "P2LDistance": return new TCAD.constraints.P2LDistance(params, values[0]); + case "P2LDistanceV": + return new TCAD.constraints.P2LDistanceV(params); case "P2PDistance": return new TCAD.constraints.P2PDistance(params, values[0]); case "P2PDistanceV": @@ -157,6 +159,87 @@ TCAD.constraints.P2LDistance = function(params, distance) { }; + +TCAD.constraints.P2LDistanceV = function(params) { + + this.params = params;//.slice(0, params.length -1); + + var TX = 0; + var TY = 1; + var LP1X = 2; + var LP1Y = 3; + var LP2X = 4; + var LP2Y = 5; + var D = 6; + + this.error = function() { + var x0 = this.p0x(), x1 = this.p1x(), x2 = this.p2x(); + var y0 = this.p0y(), y1 = this.p1y(), y2 = this.p2y(); + var dist = this.params[D].get(); + var dx = x2 - x1; + var dy = y2 - y1; + var d = Math.sqrt(dx * dx + dy * dy); + var area = Math.abs + (-x0 * dy + y0 * dx + x1 * y2 - x2 * y1); // = x1y2 - x2y1 - x0y2 + x2y0 + x0y1 - x1y0 = 2*(triangle area) + if (d == 0) { + return 0; + } + return (area / d - dist); + + }; + + this.p1x = function() { + return params[LP1X].get(); + }; + + this.p1y = function() { + return params[LP1Y].get(); + }; + + this.p2x = function() { + return params[LP2X].get(); + }; + + this.p2y = function() { + return params[LP2Y].get(); + }; + + this.p0x = function() { + return params[TX].get(); + }; + + this.p0y = function() { + return params[TY].get(); + }; + + this.gradient = function(out) { + var x0 = this.p0x(), x1 = this.p1x(), x2 = this.p2x(); + var y0 = this.p0y(), y1 = this.p1y(), y2 = this.p2y(); + var dx = x2 - x1; + var dy = y2 - y1; + var d2 = dx * dx + dy * dy; + var d = Math.sqrt(d2); + var area = -x0 * dy + y0 * dx + x1 * y2 - x2 * y1; + out[TX] = ((y1 - y2) / d); + out[TY] = ((x2 - x1) / d); + out[LP1X] = (((y2 - y0) * d + (dx / d) * area) / d2); + out[LP1Y] = (((x0 - x2) * d + (dy / d) * area) / d2); + out[LP2X] = (((y0 - y1) * d - (dx / d) * area) / d2); + out[LP2Y] = (((x1 - x0) * d - (dy / d) * area) / d2); + out[D] = -1; + + for (var i = 0; i < 6; i++) { + if (Number.isNaN(out[i])) { + out[i] = 0; + } + if (area < 0) { + out[i] *= -1; + } + } + } + +}; + TCAD.constraints.P2PDistance = function(params, distance) { this.params = params; diff --git a/web/app/fetchers.js b/web/app/fetchers.js index 87f8b917..3564631f 100644 --- a/web/app/fetchers.js +++ b/web/app/fetchers.js @@ -46,6 +46,25 @@ TCAD.TWO.ParametricManager.prototype._fetchPointAndLine = function(objs) { return [point, line]; }; +TCAD.TWO.ParametricManager.prototype._fetchArcAndLine = function(objs) { + + var arc = null; + var line = null; + + for (var i = 0; i < objs.length; ++i) { + if (objs[i]._class == 'TCAD.TWO.Arc') { + arc = objs[i]; + } else if (objs[i]._class == 'TCAD.TWO.Segment') { + line = objs[i]; + } + } + if (arc == null || line == null) { + throw "Illegal Argument. Constraint requires arc and line." + } + + return [arc, line]; +}; + TCAD.TWO.ParametricManager.prototype._fetchTwoLines = function(objs) { var lines = []; for (var i = 0; i < objs.length; ++i) { diff --git a/web/app/main2d.js b/web/app/main2d.js index b3c51fa8..197d95f6 100644 --- a/web/app/main2d.js +++ b/web/app/main2d.js @@ -99,9 +99,13 @@ TCAD.App2D = function() { "R = R" : function() { app.viewer.parametricManager.rr(app.viewer.selected); - } + }, + tangent : function() { + app.viewer.parametricManager.tangent(app.viewer.selected); + } }; + actionsF.add(actions, 'addSegment'); actionsF.add(actions, 'addArc'); actionsF.add(actions, 'pan'); @@ -115,6 +119,7 @@ TCAD.App2D = function() { actionsF.add(actions, 'P2PDistance'); actionsF.add(actions, 'Radius'); actionsF.add(actions, 'R = R'); + actionsF.add(actions, 'tangent'); actionsF.open(); }; diff --git a/web/app/parametric.js b/web/app/parametric.js index 2d2df2ec..afebe8f7 100644 --- a/web/app/parametric.js +++ b/web/app/parametric.js @@ -32,6 +32,13 @@ TCAD.TWO.ParametricManager.prototype.perpendicular = function(objs) { this.add(new TCAD.TWO.Constraints.Perpendicular(lines[0], lines[1])); }; +TCAD.TWO.ParametricManager.prototype.tangent = function(objs) { + var al = this._fetchArcAndLine(objs); + var arc = al[0]; + var line = al[1]; + this.add(new TCAD.TWO.Constraints.P2LDistanceV( arc.c, line, arc.r )); +}; + TCAD.TWO.ParametricManager.prototype.rr = function(objs) { var arcs = this._fetchArcs(objs, 2); var prev = arcs[0].r; @@ -72,7 +79,7 @@ TCAD.TWO.ParametricManager.prototype.p2pDistance = function(objs, promptCallback var p = this._fetchTwoPoints(objs); var distance = new TCAD.Vector(p[1].x - p[0].x, p[1].y - p[0].y).length(); var promptDistance = promptCallback("Enter the distance", distance.toFixed(2)); - + if (promptDistance != null) { promptDistance = Number(promptDistance); if (promptDistance == promptDistance) { // check for NaN @@ -296,6 +303,22 @@ TCAD.TWO.Constraints.P2LDistance.prototype.getSolveData = function() { return ['P2LDistance', params, [this.d]]; }; + +TCAD.TWO.Constraints.P2LDistanceV = function(p, l, d) { + this.p = p; + this.l = l; + this.d = d; +}; + +TCAD.TWO.Constraints.P2LDistanceV.prototype.getSolveData = function() { + var params = []; + this.p.collectParams(params); + this.l.collectParams(params); + params.push(this.d); + return ['P2LDistanceV', params]; +}; + + TCAD.TWO.Constraints.P2PDistance = function(p1, p2, d) { this.p1 = p1; this.p2 = p2;