UNPKG

@sauskylark/potree

Version:

WebGL point cloud viewer

182 lines (135 loc) 5.81 kB
import * as THREE from "../../libs/three.js/build/three.module.js"; import {BoxVolume} from "./Volume.js"; import {Utils} from "../utils.js"; import {PointSizeType} from "../defines.js"; import { EventDispatcher } from "../EventDispatcher.js"; export class ScreenBoxSelectTool extends EventDispatcher{ constructor(viewer){ super(); this.viewer = viewer; this.scene = new THREE.Scene(); viewer.addEventListener("update", this.update.bind(this)); viewer.addEventListener("render.pass.perspective_overlay", this.render.bind(this)); viewer.addEventListener("scene_changed", this.onSceneChange.bind(this)); } onSceneChange(scene){ console.log("scene changed"); } startInsertion(){ let domElement = this.viewer.renderer.domElement; let volume = new BoxVolume(); volume.position.set(12345, 12345, 12345); volume.showVolumeLabel = false; volume.visible = false; volume.update(); this.viewer.scene.addVolume(volume); this.importance = 10; let selectionBox = $(`<div style="position: absolute; border: 2px solid white; pointer-events: none; border-style:dashed"></div>`); $(domElement.parentElement).append(selectionBox); selectionBox.css("right", "10px"); selectionBox.css("bottom", "10px"); let drag = e =>{ volume.visible = true; let mStart = e.drag.start; let mEnd = e.drag.end; let box2D = new THREE.Box2(); box2D.expandByPoint(mStart); box2D.expandByPoint(mEnd); selectionBox.css("left", `${box2D.min.x}px`); selectionBox.css("top", `${box2D.min.y}px`); selectionBox.css("width", `${box2D.max.x - box2D.min.x}px`); selectionBox.css("height", `${box2D.max.y - box2D.min.y}px`); let camera = e.viewer.scene.getActiveCamera(); let size = e.viewer.renderer.getSize(new THREE.Vector2()); let frustumSize = new THREE.Vector2( camera.right - camera.left, camera.top - camera.bottom); let screenCentroid = new THREE.Vector2().addVectors(e.drag.end, e.drag.start).multiplyScalar(0.5); let ray = Utils.mouseToRay(screenCentroid, camera, size.width, size.height); let diff = new THREE.Vector2().subVectors(e.drag.end, e.drag.start); diff.divide(size).multiply(frustumSize); volume.position.copy(ray.origin); volume.up.copy(camera.up); volume.rotation.copy(camera.rotation); volume.scale.set(diff.x, diff.y, 1000 * 100); e.consume(); }; let drop = e => { this.importance = 0; $(selectionBox).remove(); this.viewer.inputHandler.deselectAll(); this.viewer.inputHandler.toggleSelection(volume); let camera = e.viewer.scene.getActiveCamera(); let size = e.viewer.renderer.getSize(new THREE.Vector2()); let screenCentroid = new THREE.Vector2().addVectors(e.drag.end, e.drag.start).multiplyScalar(0.5); let ray = Utils.mouseToRay(screenCentroid, camera, size.width, size.height); let line = new THREE.Line3(ray.origin, new THREE.Vector3().addVectors(ray.origin, ray.direction)); this.removeEventListener("drag", drag); this.removeEventListener("drop", drop); let allPointsNear = []; let allPointsFar = []; // TODO support more than one point cloud for(let pointcloud of this.viewer.scene.pointclouds){ if(!pointcloud.visible){ continue; } let volCam = camera.clone(); volCam.left = -volume.scale.x / 2; volCam.right = +volume.scale.x / 2; volCam.top = +volume.scale.y / 2; volCam.bottom = -volume.scale.y / 2; volCam.near = -volume.scale.z / 2; volCam.far = +volume.scale.z / 2; volCam.rotation.copy(volume.rotation); volCam.position.copy(volume.position); volCam.updateMatrix(); volCam.updateMatrixWorld(); volCam.updateProjectionMatrix(); volCam.matrixWorldInverse.copy(volCam.matrixWorld).invert(); let ray = new THREE.Ray(volCam.getWorldPosition(new THREE.Vector3()), volCam.getWorldDirection(new THREE.Vector3())); let rayInverse = new THREE.Ray( ray.origin.clone().add(ray.direction.clone().multiplyScalar(volume.scale.z)), ray.direction.clone().multiplyScalar(-1)); let pickerSettings = { width: 8, height: 8, pickWindowSize: 8, all: true, pickClipped: true, pointSizeType: PointSizeType.FIXED, pointSize: 1}; let pointsNear = pointcloud.pick(viewer, volCam, ray, pickerSettings); volCam.rotateX(Math.PI); volCam.updateMatrix(); volCam.updateMatrixWorld(); volCam.updateProjectionMatrix(); volCam.matrixWorldInverse.copy(volCam.matrixWorld).invert(); let pointsFar = pointcloud.pick(viewer, volCam, rayInverse, pickerSettings); allPointsNear.push(...pointsNear); allPointsFar.push(...pointsFar); } if(allPointsNear.length > 0 && allPointsFar.length > 0){ let viewLine = new THREE.Line3(ray.origin, new THREE.Vector3().addVectors(ray.origin, ray.direction)); let closestOnLine = allPointsNear.map(p => viewLine.closestPointToPoint(p.position, false, new THREE.Vector3())); let closest = closestOnLine.sort( (a, b) => ray.origin.distanceTo(a) - ray.origin.distanceTo(b))[0]; let farthestOnLine = allPointsFar.map(p => viewLine.closestPointToPoint(p.position, false, new THREE.Vector3())); let farthest = farthestOnLine.sort( (a, b) => ray.origin.distanceTo(b) - ray.origin.distanceTo(a))[0]; let distance = closest.distanceTo(farthest); let centroid = new THREE.Vector3().addVectors(closest, farthest).multiplyScalar(0.5); volume.scale.z = distance * 1.1; volume.position.copy(centroid); } volume.clip = true; }; this.addEventListener("drag", drag); this.addEventListener("drop", drop); viewer.inputHandler.addInputListener(this); return volume; } update(e){ //console.log(e.delta) } render(){ this.viewer.renderer.render(this.scene, this.viewer.scene.getActiveCamera()); } }