UNPKG

potree

Version:

WebGL point cloud viewer - WORK IN PROGRESS

219 lines (171 loc) 6.82 kB
Potree.MeasuringTool = class MeasuringTool extends THREE.EventDispatcher { constructor (viewer) { super(); this.viewer = viewer; this.renderer = viewer.renderer; this.addEventListener('start_inserting_measurement', e => { this.viewer.dispatchEvent({ type: 'cancel_insertions' }); }); this.sceneMeasurement = new THREE.Scene(); this.sceneMeasurement.name = 'scene_measurement'; this.light = new THREE.PointLight(0xffffff, 1.0); this.sceneMeasurement.add(this.light); this.viewer.inputHandler.registerInteractiveScene(this.sceneMeasurement); this.onRemove = (e) => { this.sceneMeasurement.remove(e.measurement); }; this.onAdd = e => { this.sceneMeasurement.add(e.measurement); }; } setScene (scene) { if (this.scene === scene) { return; } if (this.scene) { this.scene.removeEventListener('measurement_added', this.onAdd); this.scene.removeEventListener('measurement_removed', this.onRemove); } this.scene = scene; this.scene.addEventListener('measurement_added', this.onAdd); this.scene.addEventListener('measurement_removed', this.onRemove); } startInsertion (args = {}) { let domElement = this.viewer.renderer.domElement; let measure = new Potree.Measure(); this.dispatchEvent({ type: 'start_inserting_measurement', measure: measure }); measure.showDistances = (args.showDistances == null) ? true : args.showDistances; measure.showArea = args.showArea || false; measure.showAngles = args.showAngles || false; measure.showCoordinates = args.showCoordinates || false; measure.showHeight = args.showHeight || false; measure.closed = args.closed || false; measure.maxMarkers = args.maxMarkers || Infinity; measure.name = args.name || 'Measurement'; this.sceneMeasurement.add(measure); let cancel = { removeLastMarker: measure.maxMarkers > 3, callback: null }; let insertionCallback = (e) => { if (e.button === THREE.MOUSE.LEFT) { measure.addMarker(measure.points[measure.points.length - 1].position.clone()); if (measure.points.length >= measure.maxMarkers) { cancel.callback(); } this.viewer.inputHandler.startDragging( measure.spheres[measure.spheres.length - 1]); } else if (e.button === THREE.MOUSE.RIGHT) { cancel.callback(); } }; cancel.callback = e => { if (cancel.removeLastMarker) { measure.removeMarker(measure.points.length - 1); } domElement.removeEventListener('mouseup', insertionCallback, true); this.viewer.removeEventListener('cancel_insertions', cancel.callback); }; if (measure.maxMarkers > 1) { this.viewer.addEventListener('cancel_insertions', cancel.callback); domElement.addEventListener('mouseup', insertionCallback, true); } measure.addMarker(new THREE.Vector3(0, 0, 0)); this.viewer.inputHandler.startDragging( measure.spheres[measure.spheres.length - 1]); this.viewer.scene.addMeasurement(measure); } update () { let camera = this.viewer.scene.camera; let domElement = this.renderer.domElement; let measurements = this.viewer.scene.measurements; this.light.position.copy(camera.position); // make size independant of distance for (let measure of measurements) { measure.lengthUnit = this.viewer.lengthUnit; measure.update(); // spheres for (let sphere of measure.spheres) { let distance = camera.position.distanceTo(sphere.getWorldPosition()); let pr = Potree.utils.projectedRadius(1, camera.fov * Math.PI / 180, distance, domElement.clientHeight); let scale = (15 / pr); sphere.scale.set(scale, scale, scale); } // labels let labels = measure.edgeLabels.concat(measure.angleLabels); for (let label of labels) { let distance = camera.position.distanceTo(label.getWorldPosition()); let pr = Potree.utils.projectedRadius(1, camera.fov * Math.PI / 180, distance, domElement.clientHeight); let scale = (70 / pr); label.scale.set(scale, scale, scale); } // coordinate labels for (let j = 0; j < measure.coordinateLabels.length; j++) { let label = measure.coordinateLabels[j]; let sphere = measure.spheres[j]; // measure.points[j] let distance = camera.position.distanceTo(sphere.getWorldPosition()); let screenPos = sphere.getWorldPosition().clone().project(camera); screenPos.x = Math.round((screenPos.x + 1) * domElement.clientWidth / 2); screenPos.y = Math.round((-screenPos.y + 1) * domElement.clientHeight / 2); screenPos.z = 0; screenPos.y -= 30; let labelPos = new THREE.Vector3( (screenPos.x / domElement.clientWidth) * 2 - 1, -(screenPos.y / domElement.clientHeight) * 2 + 1, 0.5); labelPos.unproject(camera); let direction = labelPos.sub(camera.position).normalize(); labelPos = new THREE.Vector3().addVectors( camera.position, direction.multiplyScalar(distance)); label.position.copy(labelPos); let pr = Potree.utils.projectedRadius(1, camera.fov * Math.PI / 180, distance, domElement.clientHeight); let scale = (70 / pr); label.scale.set(scale, scale, scale); } // height label if (measure.showHeight) { let label = measure.heightLabel; { let distance = label.position.distanceTo(camera.position); let pr = Potree.utils.projectedRadius(1, camera.fov * Math.PI / 180, distance, domElement.clientHeight); let scale = (70 / pr); label.scale.set(scale, scale, scale); } { // height edge let edge = measure.heightEdge; let lowpoint = edge.geometry.vertices[0].clone().add(edge.position); let start = edge.geometry.vertices[2].clone().add(edge.position); let end = edge.geometry.vertices[3].clone().add(edge.position); let lowScreen = lowpoint.clone().project(camera); let startScreen = start.clone().project(camera); let endScreen = end.clone().project(camera); let toPixelCoordinates = v => { let r = v.clone().addScalar(1).divideScalar(2); r.x = r.x * domElement.clientWidth; r.y = r.y * domElement.clientHeight; r.z = 0; return r; }; let lowEL = toPixelCoordinates(lowScreen); let startEL = toPixelCoordinates(startScreen); let endEL = toPixelCoordinates(endScreen); let lToS = lowEL.distanceTo(startEL); let sToE = startEL.distanceTo(endEL); edge.geometry.lineDistances = [0, lToS, lToS, lToS + sToE]; edge.geometry.lineDistancesNeedUpdate = true; edge.material.dashSize = 10; edge.material.gapSize = 10; } } { // area label let label = measure.areaLabel; let distance = label.position.distanceTo(camera.position); let pr = Potree.utils.projectedRadius(1, camera.fov * Math.PI / 180, distance, domElement.clientHeight); let scale = (70 / pr); label.scale.set(scale, scale, scale); } } } };