From 3bce2d986263d70548dbf038262a84ad7ee9d22f Mon Sep 17 00:00:00 2001 From: Val Erastov Date: Sun, 27 Nov 2016 23:27:55 -0800 Subject: [PATCH] add terminal support for arcs --- web/app/sketcher/shapes/arc.js | 87 +------------------- web/app/sketcher/sketcher-app.js | 2 +- web/app/sketcher/tools/arc.js | 134 +++++++++++++++++++++++++++++++ web/app/sketcher/tools/tool.js | 38 ++++++++- 4 files changed, 171 insertions(+), 90 deletions(-) create mode 100644 web/app/sketcher/tools/arc.js diff --git a/web/app/sketcher/shapes/arc.js b/web/app/sketcher/shapes/arc.js index a29bc856..44781af2 100644 --- a/web/app/sketcher/shapes/arc.js +++ b/web/app/sketcher/shapes/arc.js @@ -1,11 +1,11 @@ import * as utils from '../../utils/utils'; import * as math from '../../math/math'; import Vector from '../../math/vector' -import {SketchObject, EndPoint, Ref} from '../viewer2d' +import {SketchObject, Ref} from '../viewer2d' import {Constraints} from '../parametric' /** @constructor */ -function Arc(a, b, c) { +export function Arc(a, b, c) { SketchObject.call(this); this.a = a; this.b = b; @@ -130,86 +130,3 @@ Arc.prototype.stabilize = function(viewer) { viewer.parametricManager._add(new Constraints.P2PDistanceV(this.a, this.c, this.r)); }; -/** @constructor */ -function AddArcTool(viewer) { - this.viewer = viewer; - this.arc = null; - this.point = null; - this._v = new Vector(0, 0, 0); -} - -AddArcTool.prototype.keydown = function(e) {}; -AddArcTool.prototype.keypress = function(e) {}; -AddArcTool.prototype.keyup = function(e) {}; -AddArcTool.prototype.cleanup = function(e) {}; - -AddArcTool.prototype.mousemove = function(e) { - var p = this.viewer.screenToModel(e); - if (this.point != null) { - this.point.x = p.x; - this.point.y = p.y; - - var r = math.distance(this.arc.a.x, this.arc.a.y, this.arc.c.x, this.arc.c.y); - if (this.point.id === this.arc.b.id) { - //force placement second point on the arc - var v = this._v; - v.set(this.arc.b.x - this.arc.c.x, this.arc.b.y - this.arc.c.y, 0); - v._normalize()._multiply(r); - this.arc.b.x = v.x + this.arc.c.x; - this.arc.b.y = v.y + this.arc.c.y; - } else { - var ang = Math.atan2(this.point.y - this.arc.c.y, this.point.x - this.arc.c.x) + (2 * Math.PI - 0.3); - - ang %= 2 * Math.PI; - - this.arc.b.x = this.arc.c.x + r * Math.cos(ang); - this.arc.b.y = this.arc.c.y + r * Math.sin(ang); - } - - this.viewer.snap(p.x, p.y, [this.arc.a, this.arc.b, this.arc.c]); - this.viewer.refresh(); - } else { - this.viewer.snap(p.x, p.y, []); - this.viewer.refresh(); - } -}; - -AddArcTool.prototype.mouseup = function(e) { - if (this.arc == null) { - this.viewer.historyManager.checkpoint(); - var p = this.viewer.screenToModel(e); - this.arc = new Arc( - new EndPoint(p.x, p.y), - new EndPoint(p.x, p.y), - new EndPoint(p.x, p.y) - ); - this.point = this.arc.a; - this.viewer.activeLayer.objects.push(this.arc); - this.snapIfNeed(this.arc.c); - this.viewer.refresh(); - } else if (this.point.id === this.arc.a.id) { - this.snapIfNeed(this.arc.a); - this.point = this.arc.b; - } else { - this.snapIfNeed(this.arc.b); - this.arc.stabilize(this.viewer); - this.viewer.toolManager.releaseControl(); - } -}; - -AddArcTool.prototype.snapIfNeed = function(p) { - if (this.viewer.snapped.length != 0) { - var snapWith = this.viewer.snapped.pop(); - this.viewer.cleanSnap(); - this.viewer.parametricManager.linkObjects([p, snapWith]); - this.viewer.parametricManager.refresh(); - } -}; - -AddArcTool.prototype.mousedown = function(e) { -}; - -AddArcTool.prototype.mousewheel = function(e) { -}; - -export {Arc, AddArcTool} \ No newline at end of file diff --git a/web/app/sketcher/sketcher-app.js b/web/app/sketcher/sketcher-app.js index 292d8d7e..5806da56 100644 --- a/web/app/sketcher/sketcher-app.js +++ b/web/app/sketcher/sketcher-app.js @@ -5,7 +5,7 @@ import {IO, BBox} from './io' import {AddDimTool, AddCircleDimTool, HDimension, VDimension, Dimension, DiameterDimension} from './shapes/dim' import {AddPointTool} from './tools/point' import {AddSegmentTool} from './tools/segment' -import {AddArcTool} from './shapes/arc' +import {AddArcTool} from './tools/arc' import {EditCircleTool} from './tools/circle' import {FilletTool} from './helpers' import {ReferencePointTool} from './tools/origin' diff --git a/web/app/sketcher/tools/arc.js b/web/app/sketcher/tools/arc.js new file mode 100644 index 00000000..e7b58897 --- /dev/null +++ b/web/app/sketcher/tools/arc.js @@ -0,0 +1,134 @@ +import {Arc} from '../shapes/arc' +import {EndPoint} from '../viewer2d' +import {Tool} from './tool' +import Vector from '../../math/vector' +import * as math from '../../math/math'; + +export class AddArcTool extends Tool{ + + constructor(viewer) { + super('arc', viewer); + this.arc = null; + this.point = null; + this._v = new Vector(0, 0, 0); + } + + restart() { + this.sendHint('specify center'); + } + + mousemove(e) { + var p = this.viewer.screenToModel(e); + if (this.point != null) { + this.point.x = p.x; + this.point.y = p.y; + + if (this.point.id === this.arc.b.id) { + //force placement second point on the arc + const r = this.radiusOfFirstPoint(); + const v = this._v; + v.set(this.arc.b.x - this.arc.c.x, this.arc.b.y - this.arc.c.y, 0); + v._normalize()._multiply(r); + this.arc.b.x = v.x + this.arc.c.x; + this.arc.b.y = v.y + this.arc.c.y; + } else { + this.demoSecondPoint(); + } + + this.viewer.snap(p.x, p.y, [this.arc.a, this.arc.b, this.arc.c]); + this.viewer.refresh(); + } else { + this.viewer.snap(p.x, p.y, []); + this.viewer.refresh(); + } + } + + mouseup(e) { + if (this.arc == null) { + const center = this.viewer.screenToModel(e); + this.createArcStep(center); + } else if (this.point.id === this.arc.a.id) { + this.snapIfNeed(this.arc.a); + this.startingPointSetStep(); + } else { + this.snapIfNeed(this.arc.b); + this.finishStep(); + } + } + + createArcStep(p) { + this.viewer.historyManager.checkpoint(); + this.arc = new Arc( + new EndPoint(p.x, p.y), + new EndPoint(p.x, p.y), + new EndPoint(p.x, p.y) + ); + this.point = this.arc.a; + this.viewer.activeLayer.objects.push(this.arc); + this.snapIfNeed(this.arc.c); + this.pointPicked(p.x, p.y); + this.sendHint('specify arc starting point'); + this.viewer.refresh(); + } + + startingPointSetStep() { + this.point = this.arc.b; + this.pointPicked(this.arc.a.x, this.arc.a.y); + this.sendHint('specify angle') + } + + finishStep() { + this.arc.stabilize(this.viewer); + this.pointPicked(this.arc.b.x, this.arc.b.y); + this.viewer.refresh(); + this.viewer.toolManager.releaseControl(); + } + + snapIfNeed(p) { + if (this.viewer.snapped.length != 0) { + var snapWith = this.viewer.snapped.pop(); + this.viewer.cleanSnap(); + this.viewer.parametricManager.linkObjects([p, snapWith]); + this.viewer.parametricManager.refresh(); + } + } + + demoSecondPoint() { + const r = this.radiusOfFirstPoint(); + let ang = Math.atan2(this.arc.a.y - this.arc.c.y, this.arc.a.x - this.arc.c.x) + (2 * Math.PI - 0.3); + ang %= 2 * Math.PI; + this.arc.b.x = this.arc.c.x + r * Math.cos(ang); + this.arc.b.y = this.arc.c.y + r * Math.sin(ang); + } + + radiusOfFirstPoint() { + return math.distance(this.arc.a.x, this.arc.a.y, this.arc.c.x, this.arc.c.y); + } + + processCommand(command) { + if (this.arc == null) { + const result = Tool.ParseVector(this.viewer.referencePoint, command); + if(typeof result === 'string') return result; + this.viewer.cleanSnap(); + this.createArcStep(result); + } else if (this.point.id === this.arc.a.id) { + const result = Tool.ParseVector(this.viewer.referencePoint, command); + if(typeof result === 'string') return result; + this.arc.a.x = result.x; + this.arc.a.y = result.y; + this.startingPointSetStep(); + this.demoSecondPoint(); + this.viewer.refresh(); + } else { + const startingAngle = Math.atan2(this.point.y - this.arc.c.y, this.point.x - this.arc.c.x); + const result = Tool.ParseNumberWithRef(command, startingAngle); // treated as radius and angle + const r = this.radiusOfFirstPoint(); + if(typeof result === 'string') return result; + let angle = result / 180 * Math.PI; + angle %= 2 * Math.PI; + this.arc.b.x = this.arc.c.x + r * Math.cos(angle); + this.arc.b.y = this.arc.c.y + r * Math.sin(angle); + this.finishStep(); + } + } +} diff --git a/web/app/sketcher/tools/tool.js b/web/app/sketcher/tools/tool.js index 2565615c..51e988d3 100644 --- a/web/app/sketcher/tools/tool.js +++ b/web/app/sketcher/tools/tool.js @@ -43,11 +43,9 @@ export class Tool { }; } -const VECTOR_PATTERNS = /^(@)?(.+)(,|<)(.+)$/; - Tool.ParseNumber = function(str) { let val; - try { + try { val = eval(str); } catch(e) { return e.toString(); @@ -57,10 +55,26 @@ Tool.ParseNumber = function(str) { return valNumber; }; + +Tool.ParseNumberWithRef = function(str, ref) { + const rel = str.startsWith('@'); + if (rel) { + str = str.substring(1); + } + let val = Tool.ParseNumber(str); + if(typeof val === 'string') return val; + if (rel) { + val += ref; + } + return val; +}; + +const VECTOR_PATTERN = /^(@)?(.+)(,|<)(.+)$/; + Tool.ParseVector = function(referencePoint, command) { command = command.replace(/\s+/g, ''); - const match = command.match(VECTOR_PATTERNS); + const match = command.match(VECTOR_PATTERN); if (match) { const ref = match[1] !== undefined; let x = Tool.ParseNumber(match[2]); @@ -84,4 +98,20 @@ Tool.ParseVector = function(referencePoint, command) { return "wrong input, point is expected: x,y | @x,y | r