jsketcher/web/app/sketcher/tools/ellipse.js
2020-05-14 03:49:53 -07:00

117 lines
No EOL
3.4 KiB
JavaScript

import {Tool} from './tool'
import {EndPoint} from '../shapes/point'
import {Ellipse} from '../shapes/ellipse'
import {EllipticalArc} from '../shapes/elliptical-arc'
import Vector from 'math/vector';
export const STATE_POINT1 = 0;
export const STATE_POINT2 = 1;
export const STATE_RADIUS = 2;
export class EllipseTool extends Tool {
constructor(viewer, arc) {
super(arc ? 'ellipse' : 'elliptical arc', viewer);
this.arc = arc;
this.ellipse = null;
this.state = STATE_POINT1;
}
restart() {
this.ellipse = null;
this.state = STATE_POINT1;
this.sendHint('specify first major axis point')
}
cleanup(e) {
this.viewer.cleanSnap();
}
point(e) {
return this.viewer.snapped ? this.viewer.snapped : this.viewer.screenToModel(e);
}
newEllipse(p) {
return this.arc ? new EllipticalArc(p.x, p.y, p.x, p.y, p.x, p.y, p.x, p.y) : new Ellipse(p.x, p.y, p.x, p.y);
}
demoBPoint() {
const arc = this.ellipse;
let ang = Math.atan2(arc.a.y - arc.centerY, arc.a.x - arc.centerX) + (2 * Math.PI - 0.3);
ang %= 2 * Math.PI;
const r = arc.radiusAtAngle(ang - arc.rotation);
arc.b.x = arc.centerX + r * Math.cos(ang);
arc.b.y = arc.centerY + r * Math.sin(ang);
}
mouseup(e) {
switch (this.state) {
case STATE_POINT1: {
const p = this.point(e);
this.ellipse = this.newEllipse(p);
this.snapIfNeed(this.ellipse.ep1);
this.viewer.activeLayer.add(this.ellipse);
this.viewer.refresh();
this.state = STATE_POINT2;
this.sendHint('specify second major axis point');
break;
}
case STATE_POINT2: {
const p = this.point(e);
this.ellipse.ep2.setFromPoint(p);
this.snapIfNeed(this.ellipse.ep2);
this.viewer.refresh();
this.state = STATE_RADIUS;
this.sendHint('specify minor axis radius');
break;
}
case STATE_RADIUS:
if (this.arc) {
this.ellipse.stabilize(this.viewer);
}
this.viewer.toolManager.releaseControl();
}
}
mousemove(e) {
const p = this.viewer.screenToModel(e);
switch (this.state) {
case STATE_POINT1:
this.viewer.snap(p.x, p.y, []);
break;
case STATE_POINT2:
this.ellipse.ep2.setFromPoint(this.viewer.screenToModel(e));
this.ellipse.r.value = this.ellipse.radiusX * 0.5;
this.viewer.snap(p.x, p.y, this.ellipse.children);
if (this.arc) {
this.ellipse.a.setFromPoint(this.ellipse.ep2);
this.demoBPoint();
}
break;
case STATE_RADIUS:
const polarPoint = this.ellipse.toEllipseCoordinateSystem(p);
let minorRadius = Ellipse.findMinorRadius(this.ellipse.radiusX, polarPoint.radius, polarPoint.angle);
if (isNaN(minorRadius)) {
const projAxis = new Vector(-(this.ellipse.ep2.y - this.ellipse.ep1.y), this.ellipse.ep2.x - this.ellipse.ep1.x);
projAxis._normalize();
const v = new Vector(this.ellipse.ep2.x - p.x, this.ellipse.ep2.y - p.y);
minorRadius = Math.abs(projAxis.dot(v));
}
this.ellipse.r.set(minorRadius);
if (!Tool.dumbMode(e)) {
this.solveRequest(true);
}
if (this.arc) {
this.demoBPoint();
}
break;
}
this.viewer.refresh();
}
solveRequest(rough) {
this.viewer.parametricManager.prepare([this.ellipse.r]);
this.viewer.parametricManager.solve(rough);
}
}