From e01b450ad293912fb4bd0eaeeeaedd6f3cf51ce7 Mon Sep 17 00:00:00 2001 From: Val Erastov Date: Tue, 6 Dec 2016 23:45:54 -0800 Subject: [PATCH] ellipse tangent UI support --- web/app/sketcher/io.js | 2 +- web/app/sketcher/parametric.js | 61 ++++++++++++++++++++++-- web/app/sketcher/shapes/ellipse.js | 31 ++++++++++-- web/app/sketcher/shapes/segment.js | 18 +++---- web/app/sketcher/shapes/sketch-object.js | 10 ++-- web/app/sketcher/tools/drag.js | 7 +-- 6 files changed, 105 insertions(+), 24 deletions(-) diff --git a/web/app/sketcher/io.js b/web/app/sketcher/io.js index ee7b0473..cc4c88d8 100644 --- a/web/app/sketcher/io.js +++ b/web/app/sketcher/io.js @@ -111,7 +111,6 @@ IO.prototype._loadSketch = function(sketch) { const b = endPoint(points[1]); const c = endPoint(points[2]); skobj = new Arc(a, b, c); - if (!aux) skobj.stabilize(this.viewer); } else if (_class === T.CIRCLE) { const c = endPoint(obj['c']); skobj = new Circle(c); @@ -134,6 +133,7 @@ IO.prototype._loadSketch = function(sketch) { skobj = new DiameterDimension(obj['obj']); } if (skobj != null) { + if (!aux) skobj.stabilize(this.viewer); if (aux) skobj.accept(function(o){o.aux = true; return true;}); if (obj['edge'] !== undefined) { skobj.edge = obj['edge']; diff --git a/web/app/sketcher/parametric.js b/web/app/sketcher/parametric.js index 8cb35e50..be1d500e 100644 --- a/web/app/sketcher/parametric.js +++ b/web/app/sketcher/parametric.js @@ -267,10 +267,14 @@ ParametricManager.prototype.lockConvex = function(objs, warnCallback) { }; ParametricManager.prototype.tangent = function(objs) { - var al = fetch.arcCircAndLine(objs); - var arc = al[0]; - var line = al[1]; - this.add(new Constraints.Tangent( arc, line)); + const ellipses = fetch.generic(objs, ['TCAD.TWO.Ellipse'], 0); + const lines = fetch.generic(objs, ['TCAD.TWO.Segment'], 1); + if (ellipses.length > 0) { + this.add(new Constraints.EllipseTangent(lines[0], ellipses[0])); + } else { + const arcs = fetch.generic(objs, ['TCAD.TWO.Arc', 'TCAD.TWO.Circle'], 1); + this.add(new Constraints.Tangent(arcs[0], lines[0])); + } }; ParametricManager.prototype.rr = function(arcs) { @@ -1104,6 +1108,22 @@ Constraints.P2PDistanceV.prototype.getSolveData = function() { // ------------------------------------------------------------------------------------------------------------------ // +/** @constructor */ +Constraints.GreaterThan = function(p, limit) { + this.p = p; + this.limit = limit; +}; + +Constraints.GreaterThan.prototype.aux = true; +Constraints.GreaterThan.prototype.NAME = 'GreaterThan'; +Constraints.GreaterThan.prototype.UI_NAME = 'Greater Than'; + +Constraints.GreaterThan.prototype.getSolveData = function() { + return [[this.NAME, [this.p], [this.limit]]]; +}; + +// ------------------------------------------------------------------------------------------------------------------ // + /** @constructor */ Constraints.Radius = function(arc, d) { this.arc = arc; @@ -1392,6 +1412,39 @@ Constraints.PointOnEllipse.prototype.getObjects = function() { // ------------------------------------------------------------------------------------------------------------------ // +/** @constructor */ +Constraints.EllipseTangent = function(line, ellipse) { + this.line = line; + this.ellipse = ellipse; +}; + +Constraints.EllipseTangent.prototype.NAME = 'EllipseTangent'; +Constraints.EllipseTangent.prototype.UI_NAME = 'Tangent Ellipse'; + +Constraints.EllipseTangent.prototype.getSolveData = function() { + const params = []; + this.line.collectParams(params); + this.ellipse.ep1.collectParams(params); + this.ellipse.ep2.collectParams(params); + params.push(this.ellipse.r); + return [['EllipseTangent', params, []]]; + +}; + +Constraints.EllipseTangent.prototype.serialize = function() { + return [this.NAME, [this.line.id, this.ellipse.id]]; +}; + +Constraints.Factory[Constraints.EllipseTangent.prototype.NAME] = function(refs, data) { + return new Constraints.EllipseTangent(refs(data[0]), refs(data[1])); +}; + +Constraints.EllipseTangent.prototype.getObjects = function() { + return [this.line, this.ellipse]; +}; + +// ------------------------------------------------------------------------------------------------------------------ // + /** @constructor */ Constraints.PointInMiddle = function(point, line) { this.point = point; diff --git a/web/app/sketcher/shapes/ellipse.js b/web/app/sketcher/shapes/ellipse.js index 48122d51..0619fb38 100644 --- a/web/app/sketcher/shapes/ellipse.js +++ b/web/app/sketcher/shapes/ellipse.js @@ -1,6 +1,7 @@ import {Ref} from './ref' import {SketchObject} from './sketch-object' import {EllipseTool, STATE_RADIUS} from '../tools/ellipse' +import {Constraints} from '../parametric' import * as math from '../../math/math'; @@ -13,10 +14,31 @@ export class Ellipse extends SketchObject { this.addChild(this.ep1); this.addChild(this.ep2); this.r = new Ref(0); - this.r.value = this.radiusX * 0.5; + this.r.set(this.radiusX * 0.5); this.r.obj = this; } + recoverIfNecessary() { + let recovered = false; + if (math.distanceAB(this.ep1, this.ep2) <= math.TOLERANCE) { + this.ep1.translate(-RECOVER_LENGTH, -RECOVER_LENGTH); + this.ep2.translate(RECOVER_LENGTH, RECOVER_LENGTH); + recovered = true; + } + if (this.radiusY <= 0.1) { + this.r.set(RECOVER_LENGTH); + recovered = true; + } + return recovered; + } + + collectParams(params) { + this.ep1.collectParams(params); + this.ep2.collectParams(params); + params.push(this.r); + } + + get rotation() { return Math.atan2(this.ep2.y - this.ep1.y, this.ep2.x - this.ep1.x); } @@ -39,7 +61,9 @@ export class Ellipse extends SketchObject { drawImpl(ctx, scale) { ctx.beginPath(); - ctx.ellipse(this.centerX, this.centerY, this.radiusX, this.radiusY, this.rotation, 0, 2 * Math.PI); + const radiusX = Math.max(this.radiusX, 1e-8); + const radiusY = Math.max(this.radiusY, 1e-8); + ctx.ellipse(this.centerX, this.centerY, radiusX, radiusY, this.rotation, 0, 2 * Math.PI); ctx.stroke(); } @@ -80,4 +104,5 @@ export class Ellipse extends SketchObject { } Ellipse.prototype._class = 'TCAD.TWO.Ellipse'; -const sq = (a) => a * a; \ No newline at end of file +const sq = (a) => a * a; +const RECOVER_LENGTH = 100; \ No newline at end of file diff --git a/web/app/sketcher/shapes/segment.js b/web/app/sketcher/shapes/segment.js index ee5445f5..93db4272 100644 --- a/web/app/sketcher/shapes/segment.js +++ b/web/app/sketcher/shapes/segment.js @@ -1,5 +1,6 @@ import {SketchObject} from './sketch-object' import Vector from '../../math/vector' +import {Constraints} from '../parametric' import * as math from '../../math/math' export class Segment extends SketchObject { @@ -13,14 +14,15 @@ export class Segment extends SketchObject { this.children.push(a, b); } - validate() { - return math.distanceAB(this.a, this.b) > math.TOLERANCE; - } - - recover() { - var recoverLength = 100; - this.a.translate(-recoverLength, -recoverLength); - this.b.translate( recoverLength, recoverLength); + recoverIfNecessary() { + if (math.distanceAB(this.a, this.b) > math.TOLERANCE) { + return false; + } else { + const recoverLength = 100; + this.a.translate(-recoverLength, -recoverLength); + this.b.translate( recoverLength, recoverLength); + return true; + } } collectParams(params) { diff --git a/web/app/sketcher/shapes/sketch-object.js b/web/app/sketcher/shapes/sketch-object.js index 361ce03f..2b0643dc 100644 --- a/web/app/sketcher/shapes/sketch-object.js +++ b/web/app/sketcher/shapes/sketch-object.js @@ -31,12 +31,12 @@ export class SketchObject { } return visitor(this); } - - validate() { - return true; + + stabilize(viewer) { } - - recover() { + + recoverIfNecessary() { + return false; } getDefaultTool(viewer) { diff --git a/web/app/sketcher/tools/drag.js b/web/app/sketcher/tools/drag.js index e081dc6e..1bc2defb 100644 --- a/web/app/sketcher/tools/drag.js +++ b/web/app/sketcher/tools/drag.js @@ -59,9 +59,10 @@ export class DragTool extends Tool { var paramsToUpdate = []; this.viewer.accept(function (obj) { - if (!obj.validate() && obj.aux !== true) { - obj.recover(); - obj.collectParams(paramsToUpdate); + if (obj.aux !== true) { + if (obj.recoverIfNecessary()){ + obj.collectParams(paramsToUpdate); + } } return true; });