UNPKG

awv3

Version:
124 lines (115 loc) 4.72 kB
import * as THREE from 'three'; import Object3 from '../../../three/object3'; import Ccref from '../ccref'; import { getArcAngles, getClass, intersectLines } from '../geomutils'; import HoverHandler from './hover'; export default class TrimHandler extends HoverHandler { constructor(...args) { super(...args); this.pool = this.sketcher.pool; this.trimObjects = new Map(); } filterObjectsWithInteraction(object) { return object.id !== this.sketch.id && object.graphics !== undefined && !object.isConstraint(); } addInteraction(object) { if (!this.filterObjectsWithInteraction(object)) return; const id = object.id; const trimObjects = []; const ats = [0, 1]; for (let otherObject of this.sketch.children) if (object.id !== otherObject.id) ats.push(...intersections(object.geomParams, otherObject.geomParams)); ats.sort(); for (let i = 1; i < ats.length; ++i) { const graphics = trimGraphics(object, ats[i - 1], ats[i]); this.pool.add(graphics); const trimObject = { id: `${id}-trim-${i}`, graphics, isPoint() { return object.isPoint(); }, isConstraint() { return object.isConstraint(); }, }; trimObjects.push(trimObjects); super.addInteraction(trimObject); } object.graphics.visible = false; this.trimObjects.set(id, trimObjects); } removeInteraction(object) { const id = object.id; if (!this.trimObjects.has(id)) return; for (let trimObject of this.trimObjects.get(id)) { super.removeInteraction(trimObject); this.pool.remove(trimObject.graphics); } if (object.graphics) object.graphics.visible = true; this.trimObjects.delete(id); } // override because base method calls removeInteraction based on interactions.keys instead of trimObjects.keys removeInteractions() { for (let id of this.trimObjects.keys()) this.removeInteraction(new Ccref(this.sketcher, id)); super.removeInteractions(); } [Object3.Events.Interaction.Clicked](object, hitObject) { // TODO object.graphics.visible = false; object.graphics.removeInteraction(); } } function trimGraphics(object, at0, at1) { const graphics = object.graphics; const geomParams = object.geomParams; let constructor = graphics.constructor; if (object.class === 'CC_Circle') constructor = Object.getPrototypeOf(constructor); // Arc const result = new constructor(); switch (object.class) { case 'CC_Circle': geomParams.start = 0; geomParams.end = 2 * Math.PI; geomParams.clockwise = false; // fallthrough case 'CC_Arc': const angleParams = getArcAngles(geomParams); const startA = THREE.Math.lerp(angleParams.start, angleParams.end, at0); const endA = THREE.Math.lerp(angleParams.start, angleParams.end, at1); result.updateCoordinateSystem(geomParams.coordinateSystem); result.updateWithAngles(geomParams.center, geomParams.radius, startA, endA, geomParams.scale); break; case 'CC_Line': const start = geomParams.start.clone(); geomParams.start.lerp(geomParams.end, at0); geomParams.end.lerpVectors(start, geomParams.end, at1); // fallthrough default: result.updateFromGeomParams(geomParams); break; } return result; } function intersections(geomA, geomB) { switch (getClass(geomA)) { case 'CC_Line': switch (getClass(geomB)) { case 'CC_Point': geomB = { ...geomB, end: geomB.start.clone().addScalar(1) }; // fallthrough case 'CC_Line': const params = {}; const dirA = geomA.end.clone().sub(geomA.start), dirB = geomB.end.clone().sub(geomB.start); const lenA = dirA.length(), lenB = dirB.length(); dirA.divideScalar(lenA), dirB.divideScalar(lenB); const point = intersectLines(geomA.start, dirA, geomB.start, dirB, undefined, params); if (!point || params.A <= 0 || params.A >= lenA || params.B < 0 || params.B > lenB) return []; return [params.A / lenA]; default: return []; } default: return []; // TODO } }