awv3
Version:
⚡ AWV3 embedded CAD
128 lines (115 loc) • 4.22 kB
JavaScript
import * as THREE from 'three';
import Object3 from '../../../three/object3';
import DimensionGraphics from '../../dimension/graphics/';
import BaseHandler from './base';
import { intersectLines } from '../../sketcher/geomutils';
export default class AngleHandler extends BaseHandler {
constructor(...args) {
super(...args);
this.preview = new DimensionGraphics('CC_AngularDimension', this.sketcher.dimension);
this.sketcher.pool.add(this.preview);
this.intersectionPoint = new THREE.Vector3();
this.dir0 = new THREE.Vector3();
this.dir1 = new THREE.Vector3();
this.tuv = { type: 0, userValue: 0, value: 0, sector: 0, reflex: false, dimPos: new THREE.Vector3() };
this.resolve = () => {};
}
destroy(options) {
this.preview.destroy();
super.destroy(options);
}
filterObjectsWithInteraction(object) {
return object.id === this.sketch.id;
}
[Object3.Events.Interaction.Clicked](object, hitObject) {
this.resolve(this.tuv);
}
cancel() {
this.resolve(undefined);
}
onMouseMove() {
this.updatePreview();
}
onKeyUp() {
this.updatePreview();
}
onKeyDown() {
this.updatePreview();
}
setLines(lines) {
const [[p0s, p0e], [p1s, p1e]] = lines.map(line => [line.startPoint.pos, line.endPoint.pos]);
this.dir0.copy(p0e).sub(p0s).normalize();
this.dir1.copy(p1e).sub(p1s).normalize();
// ensure that ccw angle from dir0 to dir1 is between 0 and Math.PI
if (ccwAngle(this.dir0, this.dir1) < 0) {
const s = lines[0];
lines[0] = lines[1];
lines[1] = s;
return this.setLines(lines);
}
this.intersectionPoint = intersectLines(p0s, this.dir0, p1s, this.dir1);
this.updatePreview();
this.preview.onRender();
}
updatePreview() {
const point = this.getRecentMousePosition();
const dir = point.clone().sub(this.intersectionPoint).normalize();
const rightOf0 = ccwAngle(this.dir0, dir) < 0, leftOf1 = ccwAngle(this.dir1, dir) >= 0;
this.tuv.sector = rightOf0 << 1 | rightOf0 ^ leftOf1;
this.tuv.reflex = !!this.sketcher.view.input.keys.control;
this.tuv.type = this.tuv.sector ^ this.tuv.reflex << 1;
this.tuv.dimPos.copy(point);
let start = new THREE.Vector3(), end = new THREE.Vector3();
switch (this.tuv.type) {
case 0: {
start.copy(this.dir0);
end.copy(this.dir1);
break;
}
case 1: {
start.copy(this.dir1);
end.copy(this.dir0).negate();
break;
}
case 2: {
start.copy(this.dir0).negate();
end.copy(this.dir1).negate();
break;
}
case 3: {
start.copy(this.dir1).negate();
end.copy(this.dir0);
break;
}
}
this.tuv.userValue = ofSign(ccwAngle(start, end), this.tuv.reflex);
this.tuv.value = ofSign(ccwAngle(this.dir0, this.dir1));
function f(v) {
return { value: v.toArray() };
}
const state = {
id: 0,
class: 'CC_AngularDimension',
coordinateSystem: this.sketch.state.coordinateSystem,
previewValue: THREE.Math.radToDeg(this.tuv.userValue),
members: {
startPt: f(start.add(this.intersectionPoint)),
endPt: f(end.add(this.intersectionPoint)),
dimPt: f(point),
cornerPt: f(this.intersectionPoint),
paramName: { value: '_' },
ccw: { value: !this.tuv.reflex },
extendToCorner: { value: true },
},
};
this.preview.updateFromState(state);
}
}
function ccwAngle(a, b) {
return Math.atan2(a.x * b.y - a.y * b.x, a.x * b.x + a.y * b.y);
}
function ofSign(a, neg = false) {
if (neg && a > 0.0) a -= 2.0 * Math.PI;
if (!neg && a < 0.0) a += 2.0 * Math.PI;
return Math.abs(a);
}