awv3
Version:
⚡ AWV3 embedded CAD
124 lines (115 loc) • 4.72 kB
JavaScript
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
}
}