UNPKG

web-ifc-viewer

Version:
174 lines 6.82 kB
import { BoxGeometry, BufferGeometry, Group, Line, Mesh, Vector3 } from 'three'; import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'; import { disposeMeshRecursively } from '../../../utils/ThreeUtils'; import { CameraProjections } from '../../../base-types'; export class IfcDimensionLine { constructor(context, start, end, lineMaterial, endpointMaterial, endpointGeometry, className, endpointScale) { // Elements this.root = new Group(); this.endpointMeshes = []; this.scale = new Vector3(1, 1, 1); this.boundingSize = 0.05; this.context = context; this.labelClassName = className; this.start = start; this.end = end; this.scale = endpointScale; this.lineMaterial = lineMaterial; this.endpointMaterial = endpointMaterial; this.length = this.getLength(); this.center = this.getCenter(); this.axis = new BufferGeometry().setFromPoints([start, end]); this.line = new Line(this.axis, this.lineMaterial); this.root.add(this.line); this.endpoint = endpointGeometry; this.addEndpointMeshes(); this.textLabel = this.newText(); this.root.renderOrder = 2; this.context.getScene().add(this.root); this.context.ifcCamera.onChange.on(() => this.rescaleObjectsToCameraPosition()); this.rescaleObjectsToCameraPosition(); } dispose() { this.removeFromScene(); this.context = null; disposeMeshRecursively(this.root); this.root = null; disposeMeshRecursively(this.line); this.line = null; this.endpointMeshes.forEach((mesh) => disposeMeshRecursively(mesh)); this.endpointMeshes.length = 0; this.axis.dispose(); this.axis = null; this.endpoint.dispose(); this.endpoint = null; this.textLabel.removeFromParent(); this.textLabel.element.remove(); this.textLabel = null; this.lineMaterial.dispose(); this.lineMaterial = null; this.endpointMaterial.dispose(); this.endpointMaterial = null; if (this.boundingMesh) { disposeMeshRecursively(this.boundingMesh); this.boundingMesh = null; } } get boundingBox() { return this.boundingMesh; } get text() { return this.textLabel; } set dimensionColor(dimensionColor) { this.endpointMaterial.color = dimensionColor; this.lineMaterial.color = dimensionColor; } set visibility(visible) { this.root.visible = visible; this.textLabel.visible = visible; } set endpointGeometry(geometry) { this.endpointMeshes.forEach((mesh) => this.root.remove(mesh)); this.endpointMeshes = []; this.endpoint = geometry; this.addEndpointMeshes(); } set endpointScale(scale) { this.scale = scale; this.endpointMeshes.forEach((mesh) => mesh.scale.set(scale.x, scale.y, scale.z)); } set endPoint(point) { this.end = point; if (!this.axis) return; const position = this.axis.attributes.position; if (!position) return; position.setXYZ(1, point.x, point.y, point.z); position.needsUpdate = true; this.endpointMeshes[1].position.set(point.x, point.y, point.z); this.endpointMeshes[1].lookAt(this.start); this.endpointMeshes[0].lookAt(this.end); this.length = this.getLength(); this.textLabel.element.textContent = this.getTextContent(); this.center = this.getCenter(); this.textLabel.position.set(this.center.x, this.center.y, this.center.z); this.line.computeLineDistances(); } removeFromScene() { this.context.getScene().remove(this.root); this.root.remove(this.textLabel); } createBoundingBox() { this.boundingMesh = this.newBoundingBox(); this.setupBoundingBox(this.end); } rescaleObjectsToCameraPosition() { this.endpointMeshes.forEach((mesh) => this.rescaleMesh(mesh, IfcDimensionLine.scaleFactor)); if (this.boundingMesh) { this.rescaleMesh(this.boundingMesh, this.boundingSize, true, true, false); } } rescaleMesh(mesh, scalefactor = 1, x = true, y = true, z = true) { const camera = this.context.ifcCamera.activeCamera; let scale = new Vector3().subVectors(mesh.position, camera.position).length(); if (this.context.ifcCamera.projection === CameraProjections.Orthographic) { scale *= 0.1; } scale *= scalefactor; const scaleX = x ? scale : 1; const scaleY = y ? scale : 1; const scaleZ = z ? scale : 1; mesh.scale.set(scaleX, scaleY, scaleZ); } addEndpointMeshes() { this.newEndpointMesh(this.start, this.end); this.newEndpointMesh(this.end, this.start); } newEndpointMesh(position, direction) { const mesh = new Mesh(this.endpoint, this.endpointMaterial); mesh.position.set(position.x, position.y, position.z); mesh.scale.set(this.scale.x, this.scale.y, this.scale.z); mesh.lookAt(direction); this.endpointMeshes.push(mesh); this.root.add(mesh); } newText() { const htmlText = document.createElement('div'); htmlText.className = this.labelClassName; htmlText.textContent = this.getTextContent(); const label = new CSS2DObject(htmlText); label.position.set(this.center.x, this.center.y, this.center.z); this.root.add(label); return label; } getTextContent() { return `${this.length / IfcDimensionLine.scale} ${IfcDimensionLine.units}`; } newBoundingBox() { const box = new BoxGeometry(1, 1, this.length); return new Mesh(box); } setupBoundingBox(end) { if (!this.boundingMesh) return; this.boundingMesh.position.set(this.center.x, this.center.y, this.center.z); this.boundingMesh.lookAt(end); this.boundingMesh.visible = false; this.root.add(this.boundingMesh); } getLength() { return parseFloat(this.start.distanceTo(this.end).toFixed(2)); } getCenter() { let dir = this.end.clone().sub(this.start); const len = dir.length() * 0.5; dir = dir.normalize().multiplyScalar(len); return this.start.clone().add(dir); } } IfcDimensionLine.scaleFactor = 0.1; IfcDimensionLine.scale = 1; IfcDimensionLine.units = 'm'; //# sourceMappingURL=dimension-line.js.map