| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- import * as THREE from "../../libs/three.js/build/three.module.js";
- import {Measure} from "./Measure.js";
- import {Utils} from "../utils.js";
- import {CameraMode} from "../defines.js";
- import { EventDispatcher } from "../EventDispatcher.js";
- //old
- function updateAzimuth(viewer, measure){
- const azimuth = measure.azimuth;
- const isOkay = measure.points.length === 2;
- azimuth.node.visible = isOkay && measure.showAzimuth;
- if(!azimuth.node.visible){
- return;
- }
- const camera = viewer.scene.getActiveCamera();
- const renderAreaSize = viewer.renderer.getSize(new THREE.Vector2());
- const width = renderAreaSize.width;
- const height = renderAreaSize.height;
-
- const [p0, p1] = measure.points;
- const r = p0.position.distanceTo(p1.position);
- const northVec = Utils.getNorthVec(p0.position, r, viewer.getProjection());
- const northPos = p0.position.clone().add(northVec);
- azimuth.center.position.copy(p0.position);
- azimuth.center.scale.set(2, 2, 2);
-
- azimuth.center.visible = false;
- // azimuth.target.visible = false;
- { // north
- azimuth.north.position.copy(northPos);
- azimuth.north.scale.set(2, 2, 2);
- let distance = azimuth.north.position.distanceTo(camera.position);
- let pr = Utils.projectedRadius(1, camera, distance, width, height);
- let scale = (5 / pr);
- azimuth.north.scale.set(scale, scale, scale);
- }
- { // target
- azimuth.target.position.copy(p1.position);
- azimuth.target.position.z = azimuth.north.position.z;
- let distance = azimuth.target.position.distanceTo(camera.position);
- let pr = Utils.projectedRadius(1, camera, distance, width, height);
- let scale = (5 / pr);
- azimuth.target.scale.set(scale, scale, scale);
- }
- azimuth.circle.position.copy(p0.position);
- azimuth.circle.scale.set(r, r, r);
- azimuth.circle.material.resolution.set(width, height);
- // to target
- azimuth.centerToTarget.geometry.setPositions([
- 0, 0, 0,
- ...p1.position.clone().sub(p0.position).toArray(),
- ]);
- azimuth.centerToTarget.position.copy(p0.position);
- azimuth.centerToTarget.geometry.verticesNeedUpdate = true;
- azimuth.centerToTarget.geometry.computeBoundingSphere();
- azimuth.centerToTarget.computeLineDistances();
- azimuth.centerToTarget.material.resolution.set(width, height);
- // to target ground
- azimuth.centerToTargetground.geometry.setPositions([
- 0, 0, 0,
- p1.position.x - p0.position.x,
- p1.position.y - p0.position.y,
- 0,
- ]);
- azimuth.centerToTargetground.position.copy(p0.position);
- azimuth.centerToTargetground.geometry.verticesNeedUpdate = true;
- azimuth.centerToTargetground.geometry.computeBoundingSphere();
- azimuth.centerToTargetground.computeLineDistances();
- azimuth.centerToTargetground.material.resolution.set(width, height);
- // to north
- azimuth.centerToNorth.geometry.setPositions([
- 0, 0, 0,
- northPos.x - p0.position.x,
- northPos.y - p0.position.y,
- 0,
- ]);
- azimuth.centerToNorth.position.copy(p0.position);
- azimuth.centerToNorth.geometry.verticesNeedUpdate = true;
- azimuth.centerToNorth.geometry.computeBoundingSphere();
- azimuth.centerToNorth.computeLineDistances();
- azimuth.centerToNorth.material.resolution.set(width, height);
- // label
- const radians = Utils.computeAzimuth(p0.position, p1.position, viewer.getProjection());
- let degrees = THREE.Math.radToDeg(radians);
- if(degrees < 0){
- degrees = 360 + degrees;
- }
- const txtDegrees = `${degrees.toFixed(2)}°`;
- const labelDir = northPos.clone().add(p1.position).multiplyScalar(0.5).sub(p0.position);
- if(labelDir.length() > 0){
- labelDir.z = 0;
- labelDir.normalize();
- const labelVec = labelDir.clone().multiplyScalar(r);
- const labelPos = p0.position.clone().add(labelVec);
- azimuth.label.position.copy(labelPos);
- }
- azimuth.label.setText(txtDegrees);
- let distance = azimuth.label.position.distanceTo(camera.position);
- let pr = Utils.projectedRadius(1, camera, distance, width, height);
- let scale = (70 / pr);
- azimuth.label.scale.set(scale, scale, scale);
- }
- export class MeasuringTool extends EventDispatcher{
- constructor (viewer) {
- super();
- this.viewer = viewer;
- this.renderer = viewer.renderer;
- this.addEventListener('start_inserting_measurement', e => {
- this.viewer.dispatchEvent({
- type: 'cancel_insertions'
- });
- });
- this.showLabels = true;
- this.scene = new THREE.Scene();
- this.scene.name = 'scene_measurement';
- this.light = new THREE.PointLight(0xffffff, 1.0);
- this.scene.add(this.light);
- this.viewer.inputHandler.registerInteractiveScene(this.scene);
- this.onRemove = (e) => { this.scene.remove(e.measurement);};
- this.onAdd = e => {this.scene.add(e.measurement);};
- for(let measurement of viewer.scene.measurements){
- this.onAdd({measurement: measurement});
- }
- 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));
- viewer.scene.addEventListener('measurement_added', this.onAdd);
- viewer.scene.addEventListener('measurement_removed', this.onRemove);
- }
- onSceneChange(e){
- if(e.oldScene){
- e.oldScene.removeEventListener('measurement_added', this.onAdd);
- e.oldScene.removeEventListener('measurement_removed', this.onRemove);
- }
- e.scene.addEventListener('measurement_added', this.onAdd);
- e.scene.addEventListener('measurement_removed', this.onRemove);
- }
- startInsertion (args = {}) {
- let domElement = this.viewer.renderer.domElement;
- let measure = new Measure();
- this.dispatchEvent({
- type: 'start_inserting_measurement',
- measure: measure
- });
- const pick = (defaul, alternative) => {
- if(defaul != null){
- return defaul;
- }else{
- return alternative;
- }
- };
- measure.showDistances = (args.showDistances === null) ? true : args.showDistances;
- measure.showArea = pick(args.showArea, false);
- measure.showAngles = pick(args.showAngles, false);
- measure.showCoordinates = pick(args.showCoordinates, false);
- measure.showHeight = pick(args.showHeight, false);
- measure.showCircle = pick(args.showCircle, false);
- measure.showAzimuth = pick(args.showAzimuth, false);
- measure.showEdges = pick(args.showEdges, true);
- measure.closed = pick(args.closed, false);
- measure.maxMarkers = pick(args.maxMarkers, Infinity);
- measure.name = args.name || 'Measurement';
- this.scene.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, false);
- this.viewer.removeEventListener('cancel_insertions', cancel.callback);
- };
- if (measure.maxMarkers > 1) {
- this.viewer.addEventListener('cancel_insertions', cancel.callback);
- domElement.addEventListener('mouseup', insertionCallback, false);
- }
- measure.addMarker(new THREE.Vector3(0, 0, 0));
- this.viewer.inputHandler.startDragging(
- measure.spheres[measure.spheres.length - 1]);
- this.viewer.scene.addMeasurement(measure);
- return measure;
- }
-
- update(){
- let camera = this.viewer.scene.getActiveCamera();
- let domElement = this.renderer.domElement;
- let measurements = this.viewer.scene.measurements;
- const renderAreaSize = this.renderer.getSize(new THREE.Vector2());
- let clientWidth = renderAreaSize.width;
- let clientHeight = renderAreaSize.height;
- this.light.position.copy(camera.position);
- // make size independant of distance
- for (let measure of measurements) {
- measure.lengthUnit = this.viewer.lengthUnit;
- measure.lengthUnitDisplay = this.viewer.lengthUnitDisplay;
- measure.update();
- updateAzimuth(this.viewer, measure);
- // spheres
- for(let sphere of measure.spheres){
- let distance = camera.position.distanceTo(sphere.getWorldPosition(new THREE.Vector3()));
- let pr = Utils.projectedRadius(1, camera, distance, clientWidth, 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(new THREE.Vector3()));
- let pr = Utils.projectedRadius(1, camera, distance, clientWidth, clientHeight);
- let scale = (70 / pr);
- if(Potree.debug.scale){
- scale = (Potree.debug.scale / 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];
- let distance = camera.position.distanceTo(sphere.getWorldPosition(new THREE.Vector3()));
- let screenPos = sphere.getWorldPosition(new THREE.Vector3()).clone().project(camera);
- screenPos.x = Math.round((screenPos.x + 1) * clientWidth / 2);
- screenPos.y = Math.round((-screenPos.y + 1) * clientHeight / 2);
- screenPos.z = 0;
- screenPos.y -= 30;
- let labelPos = new THREE.Vector3(
- (screenPos.x / clientWidth) * 2 - 1,
- -(screenPos.y / clientHeight) * 2 + 1,
- 0.5 );
- labelPos.unproject(camera);
- if(this.viewer.scene.cameraMode == CameraMode.PERSPECTIVE) {
- let direction = labelPos.sub(camera.position).normalize();
- labelPos = new THREE.Vector3().addVectors(
- camera.position, direction.multiplyScalar(distance));
- }
- label.position.copy(labelPos);
- let pr = Utils.projectedRadius(1, camera, distance, clientWidth, 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 = Utils.projectedRadius(1, camera, distance, clientWidth, clientHeight);
- let scale = (70 / pr);
- label.scale.set(scale, scale, scale);
- }
- { // height edge
- let edge = measure.heightEdge;
- let sorted = measure.points.slice().sort((a, b) => a.position.z - b.position.z);
- let lowPoint = sorted[0].position.clone();
- let highPoint = sorted[sorted.length - 1].position.clone();
- let min = lowPoint.z;
- let max = highPoint.z;
- let start = new THREE.Vector3(highPoint.x, highPoint.y, min);
- let end = new THREE.Vector3(highPoint.x, highPoint.y, max);
- 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 * clientWidth;
- r.y = r.y * 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 = Utils.projectedRadius(1, camera, distance, clientWidth, clientHeight);
- let scale = (70 / pr);
- label.scale.set(scale, scale, scale);
- }
- { // radius label
- let label = measure.circleRadiusLabel;
- let distance = label.position.distanceTo(camera.position);
- let pr = Utils.projectedRadius(1, camera, distance, clientWidth, clientHeight);
- let scale = (70 / pr);
- label.scale.set(scale, scale, scale);
- }
- { // edges
- const materials = [
- measure.circleRadiusLine.material,
- ...measure.edges.map( (e) => e.material),
- measure.heightEdge.material,
- measure.circleLine.material,
- ];
- for(const material of materials){
- material.resolution.set(clientWidth, clientHeight);
- }
- }
- if(!this.showLabels){
- const labels = [
- ...measure.sphereLabels,
- ...measure.edgeLabels,
- ...measure.angleLabels,
- ...measure.coordinateLabels,
- measure.heightLabel,
- measure.areaLabel,
- measure.circleRadiusLabel,
- ];
- for(const label of labels){
- label.visible = false;
- }
- }
- }
- }
- render(){
- this.viewer.renderer.render(this.scene, this.viewer.scene.getActiveCamera());
- }
- };
|