mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-10 02:13:58 +01:00
add terminal support for arcs
This commit is contained in:
parent
85bc6cd711
commit
3bce2d9862
4 changed files with 171 additions and 90 deletions
|
|
@ -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}
|
||||
|
|
@ -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'
|
||||
|
|
|
|||
134
web/app/sketcher/tools/arc.js
Normal file
134
web/app/sketcher/tools/arc.js
Normal file
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<polar | @r<polar ";
|
||||
};
|
||||
|
||||
Tool.ParseNumberSequence = function(command, refs, length) {
|
||||
command = command.replace(/\s+/g, '');
|
||||
const parts = command.split(',');
|
||||
const result = [];
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
const part = parts[i];
|
||||
let val = refs && refs[i] ? Tool.ParseNumberWithRef(part, refs[i]) : Tool.ParseNumberWithRef(part);
|
||||
result.push(val);
|
||||
}
|
||||
if (length !== undefined && result.length != length) {
|
||||
return "wrong input, sequence of length " + length + " is expected: x1,x2...";
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue