UNPKG

awv3

Version:
128 lines (115 loc) 4.22 kB
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); }