mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-09 01:44:19 +01:00
94 lines
No EOL
3.2 KiB
JavaScript
94 lines
No EOL
3.2 KiB
JavaScript
import {Tool} from './tool'
|
|
import {BezierCurve} from '../shapes/bezier-curve'
|
|
import Vector from 'math/vector';
|
|
import {AlgNumConstraint, ConstraintDefinitions} from "../constr/ANConstraints";
|
|
import {rotate} from "geom/euclidean";
|
|
|
|
export class BezierCurveTool extends Tool {
|
|
|
|
constructor(viewer) {
|
|
super('bezier curve', viewer);
|
|
this.init();
|
|
this._v = new Vector();
|
|
}
|
|
|
|
init() {
|
|
this.curve = null;
|
|
this.otherCurveEndPoint = null;
|
|
}
|
|
|
|
restart() {
|
|
this.init();
|
|
this.sendHint('specify first point')
|
|
}
|
|
|
|
cleanup(e) {
|
|
this.viewer.cleanSnap();
|
|
}
|
|
|
|
mouseup(e) {
|
|
if (this.curve == null) {
|
|
this.checkIfConnectedToOtherCurve();
|
|
|
|
const p = this.viewer.screenToModel(e);
|
|
|
|
this.curve = new BezierCurve(p.x, p.y, p.x, p.y, p.x, p.y, p.x, p.y);
|
|
if (this.viewer.snapped != null) {
|
|
this.snapIfNeed(this.curve.a);
|
|
}
|
|
|
|
this.viewer.activeLayer.add(this.curve);
|
|
this.viewer.refresh();
|
|
} else {
|
|
this.viewer.parametricManager.startTransaction();
|
|
this.snapIfNeed(this.curve.b);
|
|
if (this.otherCurveEndPoint != null) {
|
|
const smoothingConstr = new AlgNumConstraint(ConstraintDefinitions.Parallel, [this.otherCurveEndPoint.parent, this.curve.a.parent]);
|
|
smoothingConstr.initConstants();
|
|
this.viewer.parametricManager.add(smoothingConstr);
|
|
}
|
|
this.curve.stabilize(this.viewer);
|
|
this.viewer.parametricManager.finishTransaction();
|
|
this.viewer.toolManager.releaseControl();
|
|
}
|
|
}
|
|
|
|
mousemove(e) {
|
|
const p = this.viewer.screenToModel(e);
|
|
if (this.curve != null) {
|
|
this.curve.b.setFromPoint(p);
|
|
const axis = this._v.set(this.curve.b.x - this.curve.a.x, this.curve.b.y - this.curve.a.y)._multiply(0.7);
|
|
//controlSegment = {x: -controlSegment.y, y: controlSegment.x};
|
|
const controlSegment = rotate(- axis.y, axis.x, - Math.PI * 0.25);
|
|
if (this.otherCurveEndPoint != null) {
|
|
const ctrlLength = axis.length();
|
|
this.curve.cp1.x = this.curve.a.x + this.snappedControl.x * ctrlLength;
|
|
this.curve.cp1.y = this.curve.a.y + this.snappedControl.y * ctrlLength;
|
|
if (this.snappedControl.x * controlSegment.x + this.snappedControl.y * controlSegment.y < 0) {
|
|
controlSegment.x *= -1;
|
|
controlSegment.y *= -1;
|
|
}
|
|
} else {
|
|
this.curve.cp1.x = this.curve.a.x + controlSegment.x;
|
|
this.curve.cp1.y = this.curve.a.y + controlSegment.y;
|
|
}
|
|
this.curve.cp2.x = this.curve.b.x - controlSegment.x;
|
|
this.curve.cp2.y = this.curve.b.y - controlSegment.y;
|
|
this.viewer.snap(p.x, p.y, [this.curve.a, this.curve.b, this.curve.cp1, this.curve.cp2]);
|
|
} else {
|
|
this.viewer.snap(p.x, p.y, []);
|
|
}
|
|
this.viewer.refresh();
|
|
}
|
|
|
|
checkIfConnectedToOtherCurve() {
|
|
const snapped = this.viewer.snapped;
|
|
if (snapped != null && snapped.parent && snapped.parent.parent &&
|
|
snapped.parent.parent instanceof BezierCurve &&
|
|
snapped.parent.a === snapped) { //only a of Segment is a curve endpoint(other end is a control point)
|
|
const seg = snapped.parent;
|
|
this.otherCurveEndPoint = snapped;
|
|
this.snappedControl = new Vector(seg.b.x - seg.a.x, seg.b.y - seg.a.y)._normalize()._multiply(-1);
|
|
}
|
|
}
|
|
} |