From 69da5dcd16903683532c923c403c5fdfe99c0c8e Mon Sep 17 00:00:00 2001 From: Val Erastov Date: Tue, 6 Dec 2016 23:42:38 -0800 Subject: [PATCH] ellipse tangent constraint math / 'Grater Than' constraint math --- web/app/sketcher/constr/constraints.js | 92 ++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/web/app/sketcher/constr/constraints.js b/web/app/sketcher/constr/constraints.js index edfda92b..6b75b473 100644 --- a/web/app/sketcher/constr/constraints.js +++ b/web/app/sketcher/constr/constraints.js @@ -25,6 +25,8 @@ function createByConstraintName(name, params, values) { return new P2PDistanceV(params); case "PointOnEllipse": return new PointOnEllipse(params); + case "EllipseTangent": + return new EllipseTangent(params); case "angle": return new Angle(params); case "angleConst": @@ -33,6 +35,9 @@ function createByConstraintName(name, params, values) { return new ConstantWrapper(new Angle(params), [x,x,x,x,x,x,x,x,_]); case 'LockConvex': return new LockConvex(params); + case 'GreaterThan': + return new GreaterThan(params, values[0]); + } } @@ -540,6 +545,93 @@ function PointOnEllipse(params) { this.gradient = NumericGradient; } +/** @constructor */ +function EllipseTangent(params) { + + this.params = params; + + const P1X = 0; + const P1Y = 1; + const P2X = 2; + const P2Y = 3; + const EP1X = 4; + const EP1Y = 5; + const EP2X = 6; + const EP2Y = 7; + const R = 8; + + this.error = function(gr) { + let p1x = params[P1X].get(); + let p1y = params[P1Y].get(); + let p2x = params[P2X].get(); + let p2y = params[P2Y].get(); + + let ep1x = params[EP1X].get(); + let ep1y = params[EP1Y].get(); + let ep2x = params[EP2X].get(); + let ep2y = params[EP2Y].get(); + + const radiusY = params[R].get(); + + let axisX = ep2x - ep1x; + let axisY = ep2y - ep1y; + const radiusX = Math.sqrt(sq(axisX) + sq(axisY)) * 0.5; + const scaleToCircleSpace = radiusY / radiusX; + const rotation = - Math.atan2(axisY, axisX); + function tr(x, y) { + let xx = x * Math.cos(rotation) - y * Math.sin(rotation) + let yy = x * Math.sin(rotation) + y * Math.cos(rotation); + xx *= scaleToCircleSpace; + return {x: xx, y: yy}; + } + + const axis = tr(axisX, axisY); + const p1 = tr(p1x, p1y); + const p2 = tr(p2x, p2y); + const ep1 = tr(ep1x, ep1y); + + const centerX = ep1.x + axis.x * 0.5; + const centerY = ep1.y + axis.y * 0.5; + + + let normalX = -(p2.y - p1.y); + let normalY = p2.x - p1.x; + + const normalD = Math.sqrt(sq(normalX) + sq(normalY)); + normalX /= normalD; + normalY /= normalD; + + //this length of normal of line to center + let perpendicularLength = (centerX - p1.x) * normalX + (centerY - p1.y) * normalY; + + if (perpendicularLength < 0) { + perpendicularLength *= -1; + } else { + } + + return (radiusY - perpendicularLength); //*1000; + }; + + this.gradient = NumericGradient; +} + +function GreaterThan(params, limit) { + + this.params = params; + + this.error = function() { + let value = this.params[0].get(); + var error = value <= limit ? limit - value : 0; + console.log("GreaterThan: " + error + ", value: " +value); + return error; + }; + + this.gradient = function(out) { + out[0] = -1; + } +} + + function NumericGradient(out) { const h = 1; const approx = (param) => {