Browse Source

fix: 1213

xzw 3 years ago
parent
commit
8968883558

+ 106 - 20
src/modules/Images360/Images360.js

@@ -102,7 +102,7 @@ export class Images360 extends EventDispatcher{
             e.intersectPoint && this.updateClosestPano(e.intersectPoint)
             e.intersectPoint && this.updateClosestPano(e.intersectPoint)
 		});
 		});
 
 
-        if(Potree.settings.isTest){
+        if(!Potree.settings.isOfficial){
             this.domRoot = viewer.renderer.domElement.parentElement;
             this.domRoot = viewer.renderer.domElement.parentElement;
             let elUnfocus = $("<input type='button' value='unfocus'></input>");
             let elUnfocus = $("<input type='button' value='unfocus'></input>");
             elUnfocus.css({
             elUnfocus.css({
@@ -236,14 +236,17 @@ export class Images360 extends EventDispatcher{
                         this.cube.visible = config.atPano.showSkybox 
                         this.cube.visible = config.atPano.showSkybox 
                         this.cube.visible && this.cube.material.setProjectedPanos(this.currentPano, this.currentPano, 1)
                         this.cube.visible && this.cube.material.setProjectedPanos(this.currentPano, this.currentPano, 1)
             
             
+                         
                         
                         
-                        
-                        viewer.dispatchEvent({
+                        /* viewer.dispatchEvent({
                             type: "enableChangePos",
                             type: "enableChangePos",
-                            canLeavePano :  config.canLeavePano 
-                        })
+                            canLeavePano :  config.canLeavePano ,
+                            viewport: 
+                        }) */
+                        viewer.mainViewport.unableChangePos = !config.canLeavePano
+                        
                         displayMode = mode
                         displayMode = mode
-                        if(Potree.settings.isTest){
+                        if(this.elDisplayModel){
                             this.elDisplayModel.value = mode == 'showPointCloud' ? ">>全景" : '>>点云'
                             this.elDisplayModel.value = mode == 'showPointCloud' ? ">>全景" : '>>点云'
                         }
                         }
                     }                        
                     }                        
@@ -270,7 +273,33 @@ export class Images360 extends EventDispatcher{
             })  
             })  
         }            
         }            
                 
                 
+        {//是否显示marker
+            let ifShowMarker = true;  
+            Object.defineProperty(Potree.settings, "ifShowMarker",{  
+                get: function() {
+                    return ifShowMarker 
+                },
+                set:  (show)=>{
+                    show = !!show
+                    if(show != ifShowMarker){
+                        this.panos.forEach(pano=>{
+                            pano.marker.visible = show
+                            pano.mesh.visible = show
+                            //pano.mesh.label && (pano.mesh.label
+                        })
+                        this.emit('markersDisplayChange', show) 
+                        ifShowMarker = show
+                    }
+                     
+                } 
+            })  
+        }            
+                
                 
                 
+        
+
+
+        
         viewer.addEventListener("update", () => {
         viewer.addEventListener("update", () => {
 			this.update(viewer);
 			this.update(viewer);
 		});
 		});
@@ -402,16 +431,19 @@ export class Images360 extends EventDispatcher{
             return this.focusPano(toPano) 
             return this.focusPano(toPano) 
         }
         }
         
         
-        if(this.currentPano == pano && this.isAtPano() ){
-            toPano.callback && toPano.callback()
-            return;
+        let done = (makeIt)=>{
+            toPano.deferred && toPano.deferred.resolve(makeIt)
+            makeIt && toPano.callback && toPano.callback()
+        }
+        if(this.currentPano == pano && this.isAtPano() && !toPano.target ){
+            return done(true);
         }
         }
         if(this.flying){
         if(this.flying){
-            return
+            return done(false)
         }
         }
         
         
         let target = toPano.target 
         let target = toPano.target 
-        
+        let easeName = toPano.easeName || 'easeInOutQuad'
         
         
         let config = Potree.config.displayMode[Potree.settings.displayMode]
         let config = Potree.config.displayMode[Potree.settings.displayMode]
         var pointcloudVisi = config.atPano.showPoint  //viewer.scene.pointclouds[0].visible
         var pointcloudVisi = config.atPano.showPoint  //viewer.scene.pointclouds[0].visible
@@ -419,12 +451,12 @@ export class Images360 extends EventDispatcher{
         
         
         var pano = toPano.pano 
         var pano = toPano.pano 
         
         
-        var duration = Potree.config.transitionsTime.panoToPano
+        var duration = toPano.duration || Potree.config.transitionsTime.panoToPano 
         
         
         //console.log("flyto "+pano.file.split('/').pop()  )     
         //console.log("flyto "+pano.file.split('/').pop()  )     
         
         
         this.nextPano = pano
         this.nextPano = pano
-        
+        //不飞的话是否不要执行这段?
         if(config.atPano.showSkybox || config.atPano.pointUsePanoTex){
         if(config.atPano.showSkybox || config.atPano.pointUsePanoTex){
             if(this.checkAndWaitForPanoLoad(pano, "high", "low", this.basePanoSize, ()=> {
             if(this.checkAndWaitForPanoLoad(pano, "high", "low", this.basePanoSize, ()=> {
                     setTimeout( ()=>{
                     setTimeout( ()=>{
@@ -472,16 +504,20 @@ export class Images360 extends EventDispatcher{
                 viewer.scene.pointclouds.forEach(e=>{
                 viewer.scene.pointclouds.forEach(e=>{
                     e.visible = pointcloudVisi
                     e.visible = pointcloudVisi
                 })
                 })
-                toPano.callback && toPano.callback()
+                done(true);
             },(progress)=>{//onUpdate
             },(progress)=>{//onUpdate
                 this.cube.material.uniforms.progress.value = progress 
                 this.cube.material.uniforms.progress.value = progress 
                 
                 
                 viewer.scene.pointclouds.forEach(e=>{
                 viewer.scene.pointclouds.forEach(e=>{
                     e.material.uniforms.progress.value = progress 
                     e.material.uniforms.progress.value = progress 
                 })
                 })
-            } )
-            
+            }, easeName )
             
             
+            {
+                toPano.duration = duration
+                toPano.easeName = easeName
+                this.emit('flyToPano', toPano)
+            }
         //})
         //})
     }
     }
 
 
@@ -495,6 +531,10 @@ export class Images360 extends EventDispatcher{
         if(toPano instanceof Panorama){
         if(toPano instanceof Panorama){
             toPano = {pano: toPano}
             toPano = {pano: toPano}
         }
         }
+        let done = (makeIt)=>{
+            toPano.deferred && toPano.deferred.resolve(makeIt)
+            makeIt && toPano.callback && toPano.callback()
+        }
         
         
         var pano = toPano.pano 
         var pano = toPano.pano 
         let config = Potree.config.displayMode[Potree.settings.displayMode]
         let config = Potree.config.displayMode[Potree.settings.displayMode]
@@ -523,7 +563,7 @@ export class Images360 extends EventDispatcher{
                     },1)
                     },1)
                 })  
                 })  
             ) {
             ) {
-                return //deferred.promise();
+                return ;
             }
             }
         }
         }
 		//this.load(pano).then( () => {
 		//this.load(pano).then( () => {
@@ -555,7 +595,7 @@ export class Images360 extends EventDispatcher{
                 e.visible = pointcloudVisi
                 e.visible = pointcloudVisi
             }) */
             }) */
             this.currentPano = pano;
             this.currentPano = pano;
-            toPano.callback && toPano.callback()
+            done(true)
         },(progress)=>{//onUpdate
         },(progress)=>{//onUpdate
             /* this.cube.material.uniforms.progress.value = progress 
             /* this.cube.material.uniforms.progress.value = progress 
             
             
@@ -567,7 +607,7 @@ export class Images360 extends EventDispatcher{
 
 
 		
 		
 
 
-		this.elUnfocus[0].style.display = "";
+		this.elUnfocus && (this.elUnfocus[0].style.display = "");
 	}
 	}
 
 
 
 
@@ -605,7 +645,7 @@ export class Images360 extends EventDispatcher{
         //this.currentPano.exit()
         //this.currentPano.exit()
 		this.currentPano = null;
 		this.currentPano = null;
 
 
-		this.elUnfocus[0].style.display = "none";
+		this.elUnfocus && (this.elUnfocus[0].style.display = "none");
 	}
 	}
 
 
 	load(pano, ){ 
 	load(pano, ){ 
@@ -723,6 +763,7 @@ export class Images360 extends EventDispatcher{
 
 
 
 
     closestPanoChanging(oldPano, newPano){
     closestPanoChanging(oldPano, newPano){
+        if(!Potree.setting.ifShowMarker)return
         
         
         oldPano && oldPano.hoverOff()
         oldPano && oldPano.hoverOff()
         newPano && newPano.hoverOn()
         newPano && newPano.hoverOn()
@@ -864,6 +905,51 @@ export class Images360 extends EventDispatcher{
     } 
     } 
 
 
 
 
+
+
+    fitPanoTowardPoint(o){  //寻找最适合的点位
+		var point = o.point, 
+			require = o.require || [],
+			rank = o.rank || [],
+			force = o.force,
+			getAll = o.getAll,  
+            bestDistance = o.bestDistance || 0
+        let camera = viewer.scene.getActiveCamera()
+        
+        
+        //if(o.floor)require.push(Panorama.filters.atFloor(o.floor))
+            
+        
+        if(o.boundSphere){//只接受boundSphere
+            let aspect = 1//size.x / size.y
+            let dis
+            if(camera.aspect > aspect){//视野更宽则用bound的纵向来决定
+                dis = /* size.y */o.boundSphere.radius/* / 2  *// THREE.Math.degToRad(camera.fov / 2)
+            }else{
+                let hfov = cameraLight.getHFOVForCamera(camera, camera.aspect, 1 );
+                dis = /* size.x */ o.boundSphere.radius /* / 2 */ / THREE.Math.degToRad(hfov / 2)
+            }
+                
+            bestDistance = dis*0.8 
+            
+        } 
+        
+        
+        let bestDisSquared = bestDistance * bestDistance
+        rank.push((pano)=>{
+            return -Math.abs(pano.position.distanceToSquared(point) - bestDisSquared)
+        }) 
+     
+		/* var temp = {position:point}
+ 		rank.push(Panorama.scoreFunctions.distanceSquared(temp, -2)); */
+		 
+		var g = Common.sortByScore(this.panos,  require, rank);
+		
+		if(getAll)return g;
+		return g && g.length > 0 && g[0].item
+		
+	}
+
 };
 };
 
 
 
 

+ 9 - 5
src/modules/Images360/Panorama.js

@@ -14,9 +14,13 @@ const labelProp = {
     borderRadius: 15,
     borderRadius: 15,
 }
 }
 
 
-  
-
-let standardMarkerMat = new THREE.MeshBasicMaterial({opacity:0.5, side: THREE.DoubleSide , map:texLoader.load('../resources/textures/marker.png') ,transparent:true})
+let standardMarkerMat 
+let getMarerMat = function(){
+    if(!standardMarkerMat) {
+        standardMarkerMat = new THREE.MeshBasicMaterial({opacity:0.5, side: THREE.DoubleSide , map:texLoader.load( Potree.resourcePath+'/textures/marker.png' ) ,transparent:true})
+    }
+    return standardMarkerMat.clone()
+}
 //显示全景图时marker没有被遮挡,如果需要,要换成depthBasicMaterial  或者直接把skybox的深度修改(拿到深度贴图后更如此)
 //显示全景图时marker没有被遮挡,如果需要,要换成depthBasicMaterial  或者直接把skybox的深度修改(拿到深度贴图后更如此)
 let planeGeo = new THREE.PlaneBufferGeometry(0.1,0.1);
 let planeGeo = new THREE.PlaneBufferGeometry(0.1,0.1);
 
 
@@ -171,7 +175,7 @@ class Panorama extends EventDispatcher{
         this.mesh = mesh;
         this.mesh = mesh;
          
          
          
          
-        let marker = new THREE.Mesh(planeGeo, standardMarkerMat.clone()) 
+        let marker = new THREE.Mesh(planeGeo, getMarerMat() ) 
             marker.up.set(0,0,1)
             marker.up.set(0,0,1)
             marker.lookAt(marker.up) 
             marker.lookAt(marker.up) 
             marker.scale.set(2,2,2) 
             marker.scale.set(2,2,2) 
@@ -181,7 +185,7 @@ class Panorama extends EventDispatcher{
         
         
         this.images360.node.add(mesh)
         this.images360.node.add(mesh)
         this.images360.node.add(marker)
         this.images360.node.add(marker)
-        //this.createTextLabel()
+        Potree.settings.isTest && this.createTextLabel()
         
         
     }
     }
     
     

+ 106 - 72
src/navigation/FirstPersonControls.js

@@ -21,7 +21,7 @@ import cameraLight from "../utils/cameraLight.js";
 
 
 
 
 export class FirstPersonControls extends EventDispatcher {
 export class FirstPersonControls extends EventDispatcher {
-	constructor (viewer, view) {
+	constructor (viewer, viewport) {
 		super();
 		super();
         
         
 		this.viewer = viewer;
 		this.viewer = viewer;
@@ -32,16 +32,19 @@ export class FirstPersonControls extends EventDispatcher {
 
 
 		this.rotationSpeed = 200;
 		this.rotationSpeed = 200;
 		this.moveSpeed = 10;
 		this.moveSpeed = 10;
-		this.lockElevation = false;
-        this.currentView = view
+		 
+       
+        this.setCurrentViewport({hoverViewport:viewport, force:true}) //this.currentViewport = viewport
+        
+        
         
         
 		this.keys = {
 		this.keys = {
-			FORWARD: ['W'.charCodeAt(0), 38],
-			BACKWARD: ['S'.charCodeAt(0), 40],
-			LEFT: ['A'.charCodeAt(0), 37],
-			RIGHT: ['D'.charCodeAt(0), 39],
-			UP: ['Q'.charCodeAt(0)],
-			DOWN: ['E'.charCodeAt(0)],
+            FORWARD: ['W'.charCodeAt(0), 38],
+            BACKWARD: ['S'.charCodeAt(0), 40],
+            LEFT: ['A'.charCodeAt(0), 37],
+            RIGHT: ['D'.charCodeAt(0), 39],
+            UP: ['Q'.charCodeAt(0)],
+            DOWN: ['E'.charCodeAt(0)],
             
             
             //SHIFT : [16],
             //SHIFT : [16],
             ALT : [18],
             ALT : [18],
@@ -52,7 +55,7 @@ export class FirstPersonControls extends EventDispatcher {
             Rotate_UP : ['K'.charCodeAt(0)],
             Rotate_UP : ['K'.charCodeAt(0)],
             Rotate_DOWN   : ['I'.charCodeAt(0)], 
             Rotate_DOWN   : ['I'.charCodeAt(0)], 
 
 
-		};
+        };
 
 
 		this.fadeFactor = 50;
 		this.fadeFactor = 50;
 		this.yawDelta = 0;
 		this.yawDelta = 0;
@@ -62,9 +65,11 @@ export class FirstPersonControls extends EventDispatcher {
 
 
 		this.tweens = [];
 		this.tweens = [];
 
 
-        this.enableChangePos = true
-        
+        //this.enableChangePos = true
         
         
+        this.viewer.addEventListener('camera_changed',(e)=>{
+            this.setFPCMoveSpeed(e.viewport)
+        })
         
         
 
 
 		let drag = (e) => {
 		let drag = (e) => {
@@ -79,7 +84,7 @@ export class FirstPersonControls extends EventDispatcher {
 				this.dispatchEvent({type: 'start'});
 				this.dispatchEvent({type: 'start'});
 			}
 			}
 
 
-			let moveSpeed = this.viewer.getMoveSpeed();
+			let moveSpeed = this.currentViewport.getMoveSpeed();
  
  
             
             
             let camera = e.drag.dragViewport.camera 
             let camera = e.drag.dragViewport.camera 
@@ -117,7 +122,7 @@ export class FirstPersonControls extends EventDispatcher {
                 camera.matrixWorld = _matrixWorld ;
                 camera.matrixWorld = _matrixWorld ;
               
               
 			} else if (mode == 'pan') {//平移 
 			} else if (mode == 'pan') {//平移 
-                if(!this.enableChangePos)return
+                if(viewport.unableChangePos)return
                 if(camera.type == "OrthographicCamera"){
                 if(camera.type == "OrthographicCamera"){
                    
                    
                     
                     
@@ -178,9 +183,9 @@ export class FirstPersonControls extends EventDispatcher {
                         let ratio = radius * Math.tan(THREE.Math.degToRad(camera.fov)/2) / 1000 */
                         let ratio = radius * Math.tan(THREE.Math.degToRad(camera.fov)/2) / 1000 */
                         
                         
                         
                         
-                        /* let speed = this.viewer.getMoveSpeed()
+                        /* let speed = this.currentViewport.getMoveSpeed()
                         if(FirstPersonControls.boundPlane){
                         if(FirstPersonControls.boundPlane){
-                            speed = FirstPersonControls.boundPlane.distanceToPoint(this.currentView.position)   
+                            speed = FirstPersonControls.boundPlane.distanceToPoint(this.currentViewport.position)   
                             speed = Math.max(1 , speed) 
                             speed = Math.max(1 , speed) 
                         }  */
                         }  */
                         let speed = camera.position.distanceTo(window.viewer.reticule.position)   
                         let speed = camera.position.distanceTo(window.viewer.reticule.position)   
@@ -204,26 +209,28 @@ export class FirstPersonControls extends EventDispatcher {
 		};
 		};
 
 
 		let scroll = (e) => {
 		let scroll = (e) => {
-            if(!this.enabled)return          
-            if(!this.enableChangePos)return
-            this.setCurrentView(e)
+            if(!this.enabled)return   
+            this.setCurrentViewport(e)            
+            if(this.currentViewport.unableChangePos)return 
             let camera = e.hoverViewport.camera
             let camera = e.hoverViewport.camera
-            let speed = this.viewer.getMoveSpeed() || 1 
+            let speed = this.currentViewport.getMoveSpeed() || 1 
             if(camera.type == "OrthographicCamera"){
             if(camera.type == "OrthographicCamera"){
                 let ratio
                 let ratio
                 if (e.delta < 0) {
                 if (e.delta < 0) {
-                    ratio = 1.1
+                    ratio = 0.9 
                 } else if (e.delta > 0) {
                 } else if (e.delta > 0) {
-                    ratio = 0.9
-                }
-                camera.left *= ratio;
+                    ratio = 1.1
+                } 
+                /* camera.left *= ratio;
                 camera.right *= ratio
                 camera.right *= ratio
                 camera.top *= ratio
                 camera.top *= ratio
-                camera.bottom *= ratio
+                camera.bottom *= ratio */
+                camera.zoom *= ratio
+                
                 camera.updateProjectionMatrix()
                 camera.updateProjectionMatrix()
                 
                 
             }else{
             }else{
-                var direction = this.currentView.direction.clone();
+                var direction = this.currentViewport.view.direction.clone();
             
             
                 var vec = direction.multiplyScalar(speed * 7)
                 var vec = direction.multiplyScalar(speed * 7)
                 if (e.delta < 0) {
                 if (e.delta < 0) {
@@ -246,37 +253,63 @@ export class FirstPersonControls extends EventDispatcher {
 		this.viewer.addEventListener('global_mousewheel', scroll);
 		this.viewer.addEventListener('global_mousewheel', scroll);
 		this.viewer.addEventListener('global_dblclick', dblclick);
 		this.viewer.addEventListener('global_dblclick', dblclick);
         
         
-        this.viewer.addEventListener('startDragging', this.setCurrentView.bind(this))
-        this.viewer.addEventListener('enableChangePos', (e)=>{
+        this.viewer.addEventListener('startDragging', this.setCurrentViewport.bind(this))
+        /* this.viewer.addEventListener('enableChangePos', (e)=>{
             if(!this.enabled)return
             if(!this.enabled)return
             this.enableChangePos = e.canLeavePano 
             this.enableChangePos = e.canLeavePano 
-        })
+        }) */
 
 
 
 
        
        
 	}
 	}
+    
+    setEnable(enabled){
+        this.enabled = enabled;
+         
+    }
 
 
-
-    setCurrentView(o={}){//add
-        if(!this.enabled)return
-        if(o.hoverViewport && this.currentView != o.hoverViewport.view ){
-            this.currentView = o.hoverViewport.view 
-     
-			//this.viewer.setMoveSpeed(this.currentView.radius/100);
-            this.setMoveSpeed()
+    setFPCMoveSpeed(viewport){
+        if(viewport.camera.type == 'OrthographicCamera'){
+            let s = 1 / viewport.camera.zoom
+            viewport.setMoveSpeed(s)   
+            
+        }else{
+            if(viewport == viewer.mainViewport && FirstPersonControls.boundPlane){
+                let s = FirstPersonControls.boundPlane.distanceToPoint(viewer.mainViewport.view.position)
+                s = Math.sqrt(s) / 10;
+                s = Math.max(FirstPersonControls.standardSpeed , s)
+                viewer.setMoveSpeed(s)
+            }
+            
         }
         }
+        
     }
     }
 
 
-    setMoveSpeed(){
-        if(FirstPersonControls.boundPlane){
-            let s = FirstPersonControls.boundPlane.distanceToPoint(this.currentView.position)
-            s = Math.sqrt(s) / 10;
-            s = Math.max(FirstPersonControls.standardSpeed , s)
-            this.viewer.setMoveSpeed(s)
+
+
+
+    setCurrentViewport(o={}){//add
+        if(!this.enabled && !o.force)return
+        if(o.hoverViewport && this.currentViewport != o.hoverViewport ){
+            this.currentViewport = o.hoverViewport 
+            
+            if(this.currentViewport.camera.type == 'OrthographicCamera'){
+                this.lockElevationOri = true
+                this.lockRotation = true
+            }else{
+                this.lockElevationOri = false
+                this.lockRotation = false
+            }
+     
+     
+     
+			//this.viewer.setMoveSpeed(this.currentViewport.radius/100);
+            this.setFPCMoveSpeed(this.currentViewport)
         }
         }
-        
     }
     }
 
 
+     
+
 
 
 	setScene (scene) {
 	setScene (scene) {
 		this.scene = scene;
 		this.scene = scene;
@@ -290,9 +323,7 @@ export class FirstPersonControls extends EventDispatcher {
 	}
 	}
     
     
     
     
-	setEnable(enabled){
-        this.enabled = enabled
-    }
+	
 	zoomToLocation(mouse){
 	zoomToLocation(mouse){
         if(!this.enabled)return
         if(!this.enabled)return
 		let camera = this.scene.getActiveCamera();
 		let camera = this.scene.getActiveCamera();
@@ -369,7 +400,7 @@ export class FirstPersonControls extends EventDispatcher {
         if(!this.enabled)return
         if(!this.enabled)return
  
  
         
         
-		let view = this.currentView  //this.scene.view;
+		let view = this.currentViewport.view  
 
 
 		{ // cancel move animations on user input
 		{ // cancel move animations on user input
 			let changes = [ this.yawDelta,
 			let changes = [ this.yawDelta,
@@ -398,22 +429,25 @@ export class FirstPersonControls extends EventDispatcher {
 			let rotateUp = this.keys.Rotate_UP.some(e => ih.pressedKeys[e]);
 			let rotateUp = this.keys.Rotate_UP.some(e => ih.pressedKeys[e]);
 			let rotateDown = this.keys.Rotate_DOWN.some(e => ih.pressedKeys[e]);
 			let rotateDown = this.keys.Rotate_DOWN.some(e => ih.pressedKeys[e]);
 
 
-
-            this.lockElevation = this.keys.ALT.some(e => ih.pressedKeys[e]);
-
-            if(rotateLeft){
-                this.yawDelta -= 0.01
-            }else if(rotateRight){
-                this.yawDelta += 0.01
-            } 
-            if(rotateUp){
-                this.pitchDelta -= 0.01
-            }else if(rotateDown){
-                this.pitchDelta += 0.01
-            }
             
             
+            this.lockElevation = this.lockElevationOri || this.keys.ALT.some(e => ih.pressedKeys[e]);
+            
+            
+            
+            if(!this.lockRotation){
+                if(rotateLeft){
+                    this.yawDelta -= 0.01
+                }else if(rotateRight){
+                    this.yawDelta += 0.01
+                } 
+                if(rotateUp){
+                    this.pitchDelta -= 0.01
+                }else if(rotateDown){
+                    this.pitchDelta += 0.01
+                }
+            }
         
         
-            if(this.enableChangePos){
+            if(!this.currentViewport.unableChangePos){
                 if(this.lockElevation){
                 if(this.lockElevation){
                     let dir = view.direction;
                     let dir = view.direction;
                     dir.z = 0;
                     dir.z = 0;
@@ -422,34 +456,34 @@ export class FirstPersonControls extends EventDispatcher {
                     if (moveForward && moveBackward) {
                     if (moveForward && moveBackward) {
                         this.translationWorldDelta.set(0, 0, 0);
                         this.translationWorldDelta.set(0, 0, 0);
                     } else if (moveForward) {
                     } else if (moveForward) {
-                        this.translationWorldDelta.copy(dir.multiplyScalar(this.viewer.getMoveSpeed()));
+                        this.translationWorldDelta.copy(dir.multiplyScalar(this.currentViewport.getMoveSpeed()));
                     } else if (moveBackward) {
                     } else if (moveBackward) {
-                        this.translationWorldDelta.copy(dir.multiplyScalar(-this.viewer.getMoveSpeed()));
+                        this.translationWorldDelta.copy(dir.multiplyScalar(-this.currentViewport.getMoveSpeed()));
                     }
                     }
                 }else{
                 }else{
                     if (moveForward && moveBackward) {
                     if (moveForward && moveBackward) {
                         this.translationDelta.y = 0;
                         this.translationDelta.y = 0;
                     } else if (moveForward) {
                     } else if (moveForward) {
-                        this.translationDelta.y = this.viewer.getMoveSpeed();
+                        this.translationDelta.y = this.currentViewport.getMoveSpeed();
                     } else if (moveBackward) {
                     } else if (moveBackward) {
-                        this.translationDelta.y = -this.viewer.getMoveSpeed();
+                        this.translationDelta.y = -this.currentViewport.getMoveSpeed();
                     }
                     }
                 }
                 }
 
 
                 if (moveLeft && moveRight) {
                 if (moveLeft && moveRight) {
                     this.translationDelta.x = 0;
                     this.translationDelta.x = 0;
                 } else if (moveLeft) {
                 } else if (moveLeft) {
-                    this.translationDelta.x = -this.viewer.getMoveSpeed();
+                    this.translationDelta.x = -this.currentViewport.getMoveSpeed();
                 } else if (moveRight) {
                 } else if (moveRight) {
-                    this.translationDelta.x = this.viewer.getMoveSpeed();
+                    this.translationDelta.x = this.currentViewport.getMoveSpeed();
                 }
                 }
 
 
                 if (moveUp && moveDown) {
                 if (moveUp && moveDown) {
                     this.translationWorldDelta.z = 0;
                     this.translationWorldDelta.z = 0;
                 } else if (moveUp) {
                 } else if (moveUp) {
-                    this.translationWorldDelta.z = this.viewer.getMoveSpeed();
+                    this.translationWorldDelta.z = this.currentViewport.getMoveSpeed();
                 } else if (moveDown) {
                 } else if (moveDown) {
-                    this.translationWorldDelta.z = -this.viewer.getMoveSpeed();
+                    this.translationWorldDelta.z = -this.currentViewport.getMoveSpeed();
                 }
                 }
             } 
             } 
 		}
 		}
@@ -492,12 +526,12 @@ export class FirstPersonControls extends EventDispatcher {
 		}
 		}
 
 
 		{ // set view target according to speed
 		{ // set view target according to speed
-			//view.radius = 1 * this.viewer.getMoveSpeed();
+			//view.radius = 1 * this.currentViewport.getMoveSpeed();
             
             
             /* if(viewer.bound)  view.radius = view.position.distanceTo(viewer.bound.center)
             /* if(viewer.bound)  view.radius = view.position.distanceTo(viewer.bound.center)
             let speed = view.radius/100;
             let speed = view.radius/100;
 			this.viewer.setMoveSpeed(speed); */
 			this.viewer.setMoveSpeed(speed); */
-            this.setMoveSpeed()
+            //this.setMoveSpeed()
             
             
             
             
 		}
 		}

+ 6 - 3
src/navigation/InputHandler.js

@@ -367,6 +367,7 @@ export class InputHandler extends EventDispatcher {
 		}
 		}
 
 
 		if (this.drag) { 
 		if (this.drag) { 
+            //拖拽结束
 			if (this.drag.object/*  && e.button == THREE.MOUSE.LEFT */) {//add LEFT
 			if (this.drag.object/*  && e.button == THREE.MOUSE.LEFT */) {//add LEFT
 				if (this.logMessages) console.log(`${this.constructor.name}: drop ${this.drag.object.name}`);
 				if (this.logMessages) console.log(`${this.constructor.name}: drop ${this.drag.object.name}`);
 				this.drag.object.dispatchEvent({
 				this.drag.object.dispatchEvent({
@@ -374,8 +375,9 @@ export class InputHandler extends EventDispatcher {
 					drag: this.drag, 
 					drag: this.drag, 
 					viewer: this.viewer,
 					viewer: this.viewer,
                     pressDistance,
                     pressDistance,
-                    button : e.button//add 放开的鼠标按键
-
+                    button : e.button,//add 放开的鼠标按键
+                    isAtDomElement: e.target == this.domElement
+                    
 				});
 				});
 			} else {
 			} else {
 				/* for (let inputListener of this.getSortedListeners()) {
 				/* for (let inputListener of this.getSortedListeners()) {
@@ -673,7 +675,8 @@ export class InputHandler extends EventDispatcher {
                 type: 'global_mousemove',
                 type: 'global_mousemove',
                 intersectPoint,
                 intersectPoint,
                 hoverViewport:this.hoverViewport,
                 hoverViewport:this.hoverViewport,
-                object: null
+                buttons: e.buttons,
+                drag:this.drag,
             });
             });
         //}
         //}
 		
 		

+ 12 - 7
src/navigation/Reticule.js

@@ -1,5 +1,5 @@
 import * as THREE from "../../libs/three.js/build/three.module.js";
 import * as THREE from "../../libs/three.js/build/three.module.js";
-
+import {MOUSE} from '../defines.js'
 import {transitions, easing, lerp} from '../utils/transitions.js'
 import {transitions, easing, lerp} from '../utils/transitions.js'
 
 
 
 
@@ -36,19 +36,24 @@ export default class Reticule extends THREE.Mesh{
         
         
         viewer.addEventListener('measureMovePoint',()=>{
         viewer.addEventListener('measureMovePoint',()=>{
             this.material.map = crosshairTex
             this.material.map = crosshairTex
+            this.state = 'crosshair' 
         }) 
         }) 
         viewer.addEventListener('endMeasureMove',()=>{
         viewer.addEventListener('endMeasureMove',()=>{
             this.material.map = defaultTex 
             this.material.map = defaultTex 
+            this.state = 'default' 
         }) 
         }) 
-         
-    
+        this.state = 'default'
+        
+        viewer.setObjectLayers(this, 'reticule' )
     }
     }
 
 
     move(e){
     move(e){
-        this.hidden = false,
-        this.mouseLastMoveTime = Date.now()
-        
-        this.updatePosition(e.intersectPoint, viewer.scene.getActiveCamera().position)
+        if(e.buttons == MOUSE.NONE || this.state == 'crosshair' ){//按下时不更新,除非拖拽测量
+            this.hidden = false,
+            this.mouseLastMoveTime = Date.now()
+            
+            this.updatePosition(e.intersectPoint, viewer.scene.getActiveCamera().position)
+        }
     }
     }
 
 
     hide(){
     hide(){

+ 24 - 13
src/settings.js

@@ -71,7 +71,7 @@ const config = {//配置参数   不可修改
     },
     },
      
      
     transitionsTime:{
     transitionsTime:{
-        panoToPano: 1000,
+        panoToPano: 1500,
         flyIn:1000,
         flyIn:1000,
         flyOut:1000,
         flyOut:1000,
     }
     }
@@ -80,11 +80,11 @@ const config = {//配置参数   不可修改
         fov:50,  //navvis:50
         fov:50,  //navvis:50
     },
     },
     
     
-    pointQuality:{
+    pointDensity:{
         low:{//highPerformance
         low:{//highPerformance
             maxLevel: 4, //最小为0
             maxLevel: 4, //最小为0
             pointBudget :1*1000*1000,
             pointBudget :1*1000*1000,
-        },
+        }, 
         middle:{//balanced
         middle:{//balanced
             maxLevel: 5,
             maxLevel: 5,
             pointBudget:4*1000*1000,
             pointBudget:4*1000*1000,
@@ -117,12 +117,16 @@ const config = {//配置参数   不可修改
      
      
     
     
     renderLayers:{//渲染层,方便分批渲染管理,替代scene的创建。数字不代表顺序。
     renderLayers:{//渲染层,方便分批渲染管理,替代scene的创建。数字不代表顺序。
-        bg: 1,
-        skybox: 2,
+        
+        skybox: 1,
         pointcloud: 0,
         pointcloud: 0,
-        marker: 0,
-        measure:0, //其实本来顺序是3,但是用depthTexture单独渲染了,无所谓layer,就用默认的0
-        magnifier:0//其实本来顺序是4,但是clearDepth了无所谓了
+        marker: 2,
+        reticule: 3,
+        measure:4,  
+        magnifier:5, 
+        
+        map:6,
+        mapObjects:7,
     },
     },
     
     
     tiling: {
     tiling: {
@@ -185,15 +189,22 @@ const config = {//配置参数   不可修改
 2只显示全景: 不能任意行走。 过渡时显示贴图材质非edl的点云(否则有折痕不贴合)。
 2只显示全景: 不能任意行走。 过渡时显示贴图材质非edl的点云(否则有折痕不贴合)。
 3混合:都显示。 不能任意行走。过渡时显示贴图材质非edl的点云(因为只显示点云的话不太美,点云很碎,不细腻)
 3混合:都显示。 不能任意行走。过渡时显示贴图材质非edl的点云(因为只显示点云的话不太美,点云很碎,不细腻)
  */
  */
+ 
+function getPrefix(){  
+    let u = window.location.href.split('//')
+    let v = u[1].split('/');
+    return v[0]
+}
 
 
-
-var settings = {//设置   可修改
+let settings = {//设置   可修改
     number: '', //场景序号
     number: '', //场景序号
     displayMode:'',
     displayMode:'',
-    isTest :browser.urlHasValue('test')
-    
+    isTest :browser.urlHasValue('test'),
+    prefix:getPrefix(),
+    pointDensity: '',
+    ifShowMarker:true,//显示漫游点
 }
 }
-
+settings.isLocalhost = settings.prefix.includes('localhost')
 
 
 
 
 export {config, settings}
 export {config, settings}

+ 2 - 2
src/utils.js

@@ -1175,8 +1175,8 @@ Utils.convertScreenPositionToNDC = function(pointer, mouse, width, height) {
 
 
 Utils.getOrthoCameraMoveVec = function(pointerDelta, camera ){//获取当camera为Ortho型时 屏幕点1 到 屏幕点2 的三维距离
 Utils.getOrthoCameraMoveVec = function(pointerDelta, camera ){//获取当camera为Ortho型时 屏幕点1 到 屏幕点2 的三维距离
      
      
-    let cameraViewWidth = camera.right  
-    let cameraViewHeight = camera.top ; 
+    let cameraViewWidth = camera.right / camera.zoom  
+    let cameraViewHeight = camera.top / camera.zoom
     let moveVec = new THREE.Vector3; 
     let moveVec = new THREE.Vector3; 
     moveVec.set( pointerDelta.x * cameraViewWidth  , pointerDelta.y * cameraViewHeight  , 0).applyQuaternion(camera.quaternion)  
     moveVec.set( pointerDelta.x * cameraViewWidth  , pointerDelta.y * cameraViewHeight  , 0).applyQuaternion(camera.quaternion)  
     return moveVec              
     return moveVec              

+ 22 - 12
src/utils/Magnifier.js

@@ -62,7 +62,7 @@ export default class Magnifier extends THREE.Object3D {//放大镜or望远镜
         this.mesh.renderOrder = 10;
         this.mesh.renderOrder = 10;
         this.overlayMesh.renderOrder = 11;
         this.overlayMesh.renderOrder = 11;
         this.aimPos
         this.aimPos
-
+        viewer.setObjectLayers(this, 'magnifier' )
         //viewer.inputHandler.addInputListener(this)
         //viewer.inputHandler.addInputListener(this)
         
         
         viewer.addEventListener('camera_changed',(e)=>{ // 平移、滚轮时更新
         viewer.addEventListener('camera_changed',(e)=>{ // 平移、滚轮时更新
@@ -89,32 +89,42 @@ export default class Magnifier extends THREE.Object3D {//放大镜or望远镜
                 this.updateVisible("atViewport", true)
                 this.updateVisible("atViewport", true)
                 this.update(e.intersectPoint && e.intersectPoint.location)
                 this.update(e.intersectPoint && e.intersectPoint.location)
             }else{
             }else{
-                this.updateVisible("atViewport", false)
+                this.updateVisible("atViewport", false) //小地图不显示
             }
             }
         })
         })
         
         
         
         
         
         
         
         
+        
         /* viewer.addEventListener("beginSplitView",()=>{
         /* viewer.addEventListener("beginSplitView",()=>{
             this.updateVisible("splitView", false) 
             this.updateVisible("splitView", false) 
         })
         })
         viewer.addEventListener("finishSplitView",()=>{
         viewer.addEventListener("finishSplitView",()=>{
             this.updateVisible("splitView", true) 
             this.updateVisible("splitView", true) 
         })  */
         })  */
-        
-        viewer.addEventListener("measureMovePoint",()=>{
-            this.updateVisible("measure", true) 
+         
+         
+        this.addEventListener("setEnable",(e)=>{
+            this.updateVisible("enable", e.value) //界面开关
         })
         })
-        viewer.addEventListener("endMeasureMove",()=>{
+         
+         
+        if(Potree.settings.isOfficial){
+            this.updateVisible("enable", false) 
+        }else{
             this.updateVisible("measure", false) 
             this.updateVisible("measure", false) 
-        })
-        
-        this.updateVisible("measure", false) 
+            viewer.addEventListener("measureMovePoint",()=>{//测量开始
+                this.updateVisible("measure", true) 
+            })
+            viewer.addEventListener("endMeasureMove",()=>{
+                this.updateVisible("measure", false) 
+            })
+        }
     }
     }
     
     
     
     
-    updateVisible(reason, ifShow){
+    updateVisible(reason, ifShow){//当所有加入的条件都不为false时才显示
         if(ifShow){
         if(ifShow){
             var index = this.unvisibleReasons.indexOf(reason)
             var index = this.unvisibleReasons.indexOf(reason)
             index > -1 && this.unvisibleReasons.splice(index, 1)
             index > -1 && this.unvisibleReasons.splice(index, 1)
@@ -171,7 +181,7 @@ export default class Magnifier extends THREE.Object3D {//放大镜or望远镜
         var scale = math.getScaleForConstantSize({// 
         var scale = math.getScaleForConstantSize({// 
             width2d : width2dPX,
             width2d : width2dPX,
             camera:viewer.scene.getActiveCamera(),  position: this.getWorldPosition(new THREE.Vector3()),
             camera:viewer.scene.getActiveCamera(),  position: this.getWorldPosition(new THREE.Vector3()),
-            resulution: viewer.mainViewport.resolution
+            resolution: viewer.mainViewport.resolution2
         })
         })
         this.scale.set(scale, scale, scale); 
         this.scale.set(scale, scale, scale); 
  
  
@@ -189,7 +199,7 @@ export default class Magnifier extends THREE.Object3D {//放大镜or望远镜
         //this.visible = false;//防止放大镜里有自己
         //this.visible = false;//防止放大镜里有自己
         viewer.render({
         viewer.render({
             target : this.renderTarget,
             target : this.renderTarget,
-            viewport : viewer.mainViewport,
+            viewports : [viewer.mainViewport],
             camera : this.camera,
             camera : this.camera,
             magnifier : true,
             magnifier : true,
             rtEDL: this.rtEDL,
             rtEDL: this.rtEDL,

+ 123 - 107
src/utils/Measure.js

@@ -20,7 +20,7 @@ var lineMats;
 var planeMats 
 var planeMats 
 
 
 const sphereSizeInfo = {
 const sphereSizeInfo = {
-    minSize : 15 ,  maxSize : 55,   nearBound : 0.2, farBound : 8,
+    minSize : 25 ,  maxSize : 65,   nearBound : 0.2, farBound : 8,
 }
 }
 const labelSizeInfo = {width2d:200}
 const labelSizeInfo = {width2d:200}
 const mainLabelProp = { 
 const mainLabelProp = { 
@@ -114,11 +114,12 @@ export class Measure extends THREE.Object3D {
         
         
         this.selectStates = {}
         this.selectStates = {}
         
         
-        
+        this.setUnitSystem(viewer.unitConvert.UnitService.defaultSystem)
+         
 	}
 	}
  
  
  
  
- 
+    
  
  
  
  
  
  
@@ -129,7 +130,7 @@ export class Measure extends THREE.Object3D {
 		}else{ 
 		}else{ 
             if(this.showCoordinates){
             if(this.showCoordinates){
                 let point = this.points[0];
                 let point = this.points[0];
-                let position = point.position;
+                let position = point 
                 this.spheres[0].position.copy(position);
                 this.spheres[0].position.copy(position);
 
 
                 { // coordinate labels
                 { // coordinate labels
@@ -171,7 +172,7 @@ export class Measure extends THREE.Object3D {
                 if(this.showEdges){ // edges
                 if(this.showEdges){ // edges
                     let edge = this.edges[index];
                     let edge = this.edges[index];
   
   
-                    this.updateLine(edge,point.position, nextPoint.position)
+                    this.updateLine(edge, point, nextPoint)
                       
                       
                     edge.visible = index < lastIndex || this.closed;
                     edge.visible = index < lastIndex || this.closed;
                     
                     
@@ -180,22 +181,23 @@ export class Measure extends THREE.Object3D {
                 if(this.showDistances){ // edge labels
                 if(this.showDistances){ // edge labels
                     let edgeLabel = this.edgeLabels[i];
                     let edgeLabel = this.edgeLabels[i];
 
 
-                    let center = new THREE.Vector3().add(point.position);
-                    center.add(nextPoint.position);
-                    center = center.multiplyScalar(0.5);
-                    let distance = point.position.distanceTo(nextPoint.position);
-
+                    let center = new THREE.Vector3().add(point);
+                    center.add(nextPoint);
+                    center = center.multiplyScalar(0.5); 
                     edgeLabel.setPos(center) 
                     edgeLabel.setPos(center) 
+                    let distance = point.distanceTo(nextPoint);
+                    
+                    var text = viewer.unitConvert.convert(distance, 'distance', void 0, this.unitSystem, 0.1 , true)//distance要传0.1 这个factor
 
 
-                    /* let suffix = "";
-                    if(this.lengthUnit != null && this.lengthUnitDisplay != null){
-                        distance = distance / this.lengthUnit.unitspermeter * this.lengthUnitDisplay.unitspermeter;  //convert to meters then to the display unit
-                        suffix = this.lengthUnitDisplay.code;
-                    } */
-                    let suffix = "m";
+                    /* let suffix = "m";
                     let txtLength = Utils.addCommas(distance.toFixed(2));
                     let txtLength = Utils.addCommas(distance.toFixed(2));
-                    edgeLabel.setText(`${txtLength} ${suffix}`);
+                    edgeLabel.setText(`${txtLength} ${suffix}`); */
+                    edgeLabel.setText(text)
+                    
+                    
                     edgeLabel.shouldVisi = (index < lastIndex || this.closed && this.points.length > 2) && distance>0 
                     edgeLabel.shouldVisi = (index < lastIndex || this.closed && this.points.length > 2) && distance>0 
+                    
+                    
                     /* this.closed || */ edgeLabel.setVisible(edgeLabel.shouldVisi)  
                     /* this.closed || */ edgeLabel.setVisible(edgeLabel.shouldVisi)  
                      
                      
                 }
                 }
@@ -229,25 +231,30 @@ export class Measure extends THREE.Object3D {
                 this.areaPlane.geometry = MeshDraw.getShapeGeo(this.point2dInfo.points2d)
                 this.areaPlane.geometry = MeshDraw.getShapeGeo(this.point2dInfo.points2d)
                 var center = math.getCenterOfGravityPoint(this.point2dInfo.points2d) //重心 
                 var center = math.getCenterOfGravityPoint(this.point2dInfo.points2d) //重心 
                   
                   
-                var fistPos =  this.point2dInfo.points2d[0].clone()
-                fistPos.z = 0                  //因为shape只读取了xy,所以位移下, 再算出最终位置,得到差距
-                fistPos.applyQuaternion(this.point2dInfo.quaInverse)
-                var vec = this.point2dInfo.originPoint0.clone().sub(fistPos)
+                var firstPos =  this.point2dInfo.points2d[0].clone()
+                firstPos.z = 0                  //因为shape只读取了xy,所以位移下, 再算出最终位置,得到差距
+                firstPos.applyQuaternion(this.point2dInfo.quaInverse)
+                var vec = this.point2dInfo.originPoint0.clone().sub(firstPos)
                 center = new THREE.Vector3(center.x, center.y, 0)
                 center = new THREE.Vector3(center.x, center.y, 0)
                 center.applyQuaternion(this.point2dInfo.quaInverse)
                 center.applyQuaternion(this.point2dInfo.quaInverse)
                 this.areaPlane.quaternion.copy(this.point2dInfo.quaInverse) 
                 this.areaPlane.quaternion.copy(this.point2dInfo.quaInverse) 
                 this.areaPlane.position.copy(vec)       
                 this.areaPlane.position.copy(vec)       
                 center.add(vec)
                 center.add(vec)
                 this.center = center
                 this.center = center
-                
+                let area = Math.abs(math.getArea(this.point2dInfo.points2d))//this.getArea();
                 //label
                 //label
                 this.areaLabel.setPos(center); 
                 this.areaLabel.setPos(center); 
-                let area = Math.abs(math.getArea(this.point2dInfo.points2d))//this.getArea();
+                /* 
 
 
                 let suffix = "m";
                 let suffix = "m";
                 this.area = area
                 this.area = area
                 let txtArea = Utils.addCommas(area.toFixed(2));
                 let txtArea = Utils.addCommas(area.toFixed(2));
-                let msg =  `${this.measureType} ${txtArea} ${suffix}\u00B2`;
+                let msg =  `${this.measureType} ${txtArea} ${suffix}\u00B2`; */
+                
+                
+                let msg = viewer.unitConvert.convert(area, 'area', void 0, this.unitSystem/* , 0.1 */ )
+                this.area = {value:area, string:msg}
+                
                 this.areaLabel.setText(msg);
                 this.areaLabel.setText(msg);
                 this.areaLabel.setVisible(true)
                 this.areaLabel.setVisible(true)
             }
             }
@@ -267,9 +274,9 @@ export class Measure extends THREE.Object3D {
 
 
                 if(circleOkay){
                 if(circleOkay){
 
 
-                    const A = this.points[0].position;
-                    const B = this.points[1].position;
-                    const C = this.points[2].position;
+                    const A = this.points[0];
+                    const B = this.points[1];
+                    const C = this.points[2];
                     const AB = B.clone().sub(A);
                     const AB = B.clone().sub(A);
                     const AC = C.clone().sub(A);
                     const AC = C.clone().sub(A);
                     const N = AC.clone().cross(AB).normalize();
                     const N = AC.clone().cross(AB).normalize();
@@ -313,17 +320,15 @@ export class Measure extends THREE.Object3D {
 	};
 	};
 
 
  
  
- 
+    
  
  
  
  
 
 
 
 
 	addMarker (point) {
 	addMarker (point) {
-		if (point.x != null) {
-			point = {position: point};
-		}else if(point instanceof Array){
-			point = {position: new THREE.Vector3(...point)};
-		}
+        if(point instanceof Array){
+            point = new THREE.Vector3(...point) 
+        } 
 		this.points.push(point);
 		this.points.push(point);
          
          
         
         
@@ -331,11 +336,12 @@ export class Measure extends THREE.Object3D {
         //let sphere = new THREE.Sprite(this.getSphereMaterial('default')  );
         //let sphere = new THREE.Sprite(this.getSphereMaterial('default')  );
        
        
         let sphere = new Sprite({mat:this.getSphereMaterial('default'), sizeInfo: sphereSizeInfo, name:"measure_point"} )
         let sphere = new Sprite({mat:this.getSphereMaterial('default'), sizeInfo: sphereSizeInfo, name:"measure_point"} )
+        viewer.setObjectLayers(sphere, 'measure' )
         sphere.renderOrder = 3
         sphere.renderOrder = 3
         sphere.sphereSelectStates = {}
         sphere.sphereSelectStates = {}
 		this.add(sphere);
 		this.add(sphere);
 		this.spheres.push(sphere);
 		this.spheres.push(sphere);
-        this.updateSphere(sphere, point.position)
+        this.updateSphere(sphere, point)
         
         
         
         
 		{ // edges 
 		{ // edges 
@@ -345,7 +351,7 @@ export class Measure extends THREE.Object3D {
 			],{material:this.getLineMat('edgeDefault')} )
 			],{material:this.getLineMat('edgeDefault')} )
             
             
             
             
-            
+            viewer.setObjectLayers(edge, 'measure' )
 			this.add(edge);
 			this.add(edge);
 			this.edges.push(edge);
 			this.edges.push(edge);
             
             
@@ -395,7 +401,7 @@ export class Measure extends THREE.Object3D {
                 })  
                 })  
             }
             }
              
              
-            
+            viewer.setObjectLayers(edgeLabel, 'measure' )
 			this.edgeLabels.push(edgeLabel);
 			this.edgeLabels.push(edgeLabel);
 			this.add(edgeLabel);
 			this.add(edgeLabel);
 		}
 		}
@@ -431,23 +437,8 @@ export class Measure extends THREE.Object3D {
                 
                 
 				if (I) {
 				if (I) {
 					let i = this.spheres.indexOf(e.drag.object);
 					let i = this.spheres.indexOf(e.drag.object);
-					if (i !== -1) {
-						/* let point = this.points[i];
-						let oldPos = point.position.clone();
-                        
-						// loop through current keys and cleanup ones that will be orphaned
-						for (let key of Object.keys(point)) {
-							if (!I.point[key]) {
-								delete point[key];
-							}
-						}
-
-						for (let key of Object.keys(I.point).filter(e => e !== 'position')) {
-							point[key] = I.point[key];
-						} */
-                        
-                        this.dragChange(I, i, atMap)
-						
+					if (i !== -1) { 
+                        this.dragChange(I, i, atMap) 
 					}
 					}
 				}
 				}
                 
                 
@@ -457,7 +448,16 @@ export class Measure extends THREE.Object3D {
 			};
 			};
 
 
 			let drop = e => {
 			let drop = e => {
-                
+                if(!e.isAtDomElement && this.isNew){//如果是刚添加时在其他dom点击, 不要响应
+                    setTimeout(()=>{//等 drag=null之后 //右键拖拽结束后需要重新得到drag
+                        if(viewer.scene.measurements.includes(this)){
+                            viewer.inputHandler.startDragging(e.drag.object,
+                                {endDragFun: e.drag.endDragFun} 
+                            )
+                        } 
+                    },1) 
+                    return
+                }
 				let i = this.spheres.indexOf(e.drag.object); 
 				let i = this.spheres.indexOf(e.drag.object); 
 				if (i !== -1) {
 				if (i !== -1) {
 					this.dispatchEvent({
 					this.dispatchEvent({
@@ -477,7 +477,8 @@ export class Measure extends THREE.Object3D {
                 
                 
                 this.editStateChange(false)
                 this.editStateChange(false)
                 e.drag.endDragFun && e.drag.endDragFun(e)//  addmarker
                 e.drag.endDragFun && e.drag.endDragFun(e)//  addmarker
-			};
+                if(this.changeCallBack)this.changeCallBack()
+            };
 
 
             
             
 			let mouseover = (e) => {this.setSphereSelected(e.object, true, 'single');/* console.log('hover')  */};
 			let mouseover = (e) => {this.setSphereSelected(e.object, true, 'single');/* console.log('hover')  */};
@@ -525,32 +526,34 @@ export class Measure extends THREE.Object3D {
             this.guideLine.visible = true
             this.guideLine.visible = true
         }else if( len > 1){ 
         }else if( len > 1){ 
              
              
-            var points = this.points.map(e=>e.position.clone())
+            var points = this.points//.map(e=>e.position.clone())
             points[i].copy(location) //算normal需要提前确认point
             points[i].copy(location) //算normal需要提前确认point
             
             
             //若为定义了面朝向的矩形
             //若为定义了面朝向的矩形
             if(this.faceDirection == 'horizontal'){
             if(this.faceDirection == 'horizontal'){
                 if(len == 2){
                 if(len == 2){
-                    location.setZ(this.points[0].position.z) 
+                    location.setZ(this.points[0].z) 
                 }
                 }
                 if(!this.facePlane){//一个点就能确定面
                 if(!this.facePlane){//一个点就能确定面
-                    this.facePlane = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3(0,0,1), this.points[0].position  )
+                    this.facePlane = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3(0,0,1), this.points[0]  )
                 }
                 }
             }else if(this.faceDirection == 'vertical'){//当有两个点时, 有两个方向的可能
             }else if(this.faceDirection == 'vertical'){//当有两个点时, 有两个方向的可能
                 if(len == 2){
                 if(len == 2){
-                    let vec = points[0].clone().sub(location) 
-                    if(Math.sqrt(vec.x*vec.x+vec.y*vec.y) > Math.abs(vec.z) ){//水平(高度差小于水平距离时)
-                        location.setZ(this.points[0].position.z) 
-                        //this.cannotConfirmNormal = false;//能确定面为水平方向
-                    }else{//垂直 (当两点一样时也属于这种)
-                        location.setX(points[0].x);
-                        location.setY(points[0].y);
-                        //this.cannotConfirmNormal = true; //不能确定面,因第三点可绕着纵轴线自由移动
+                    if(this.isRect){
+                        let vec = points[0].clone().sub(location) 
+                        if(Math.sqrt(vec.x*vec.x+vec.y*vec.y) > Math.abs(vec.z) ){//水平(高度差小于水平距离时)
+                            location.setZ(this.points[0].z) 
+                            //this.cannotConfirmNormal = false;//能确定面为水平方向
+                        }else{//垂直 (当两点一样时也属于这种)
+                            location.setX(points[0].x);
+                            location.setY(points[0].y);
+                            //this.cannotConfirmNormal = true; //不能确定面,因第三点可绕着纵轴线自由移动
+                        }
                     }
                     }
                 }else{ 
                 }else{ 
-                    {//判断cannotConfirmNormal
+                    {//判断cannotConfirmNormal. 如果前几段都在竖直线上,就不能固定出面方向。
                         this.cannotConfirmNormal = true
                         this.cannotConfirmNormal = true
-                        let max = this.isRect ? 1 : len-2
+                        let max = this.isRect ? 1 : len-2 
                         for(let i=0;i<max;i++){
                         for(let i=0;i<max;i++){
                             let p1 = points[i].clone()
                             let p1 = points[i].clone()
                             let p2 = points[i+1].clone()
                             let p2 = points[i+1].clone()
@@ -569,7 +572,7 @@ export class Measure extends THREE.Object3D {
                         if(points2){
                         if(points2){
                             let normal = math.getNormal2d({p1:points2[0], p2:points2[1]})  
                             let normal = math.getNormal2d({p1:points2[0], p2:points2[1]})  
                             normal = new THREE.Vector3(normal.x, normal.y, 0)
                             normal = new THREE.Vector3(normal.x, normal.y, 0)
-                            this.facePlane = new THREE.Plane().setFromNormalAndCoplanarPoint( normal, this.points[0].position  )
+                            this.facePlane = new THREE.Plane().setFromNormalAndCoplanarPoint( normal, this.points[0]  )
                         } 
                         } 
                     }
                     }
                 }
                 }
@@ -603,8 +606,8 @@ export class Measure extends THREE.Object3D {
                 
                 
                 if(this.isRect){ //是矩形 (即使没有faceDirection也能执行)
                 if(this.isRect){ //是矩形 (即使没有faceDirection也能执行)
                     //根据前两个点计算当前和下一个点
                     //根据前两个点计算当前和下一个点
-                    var p1 = this.points[(i-2+len)%len].position
-                    var p2 = this.points[(i-1+len)%len].position
+                    var p1 = this.points[(i-2+len)%len]
+                    var p2 = this.points[(i-1+len)%len]
                     if(p1.equals(p2)){//意外情况:重复点两次 ( bug点,改了好多遍)
                     if(p1.equals(p2)){//意外情况:重复点两次 ( bug点,改了好多遍)
                         if(this.faceDirection == 'vertical'){
                         if(this.faceDirection == 'vertical'){
                             p2.add(new THREE.Vector3(0,0,0.0001))
                             p2.add(new THREE.Vector3(0,0,0.0001))
@@ -625,15 +628,15 @@ export class Measure extends THREE.Object3D {
                     
                     
                 }  
                 }  
                 
                 
-                
+                let points2d;
                 if(this.facePlane){
                 if(this.facePlane){
                     var originPoint0 = points[0].clone() 
                     var originPoint0 = points[0].clone() 
                     var qua = math.getQuaBetween2Vector(this.facePlane.normal, new THREE.Vector3(0,0,1), new THREE.Vector3(0,0,1));
                     var qua = math.getQuaBetween2Vector(this.facePlane.normal, new THREE.Vector3(0,0,1), new THREE.Vector3(0,0,1));
-                    points.forEach(e=>e.applyQuaternion(qua))  
+                    points2d = points.map(e=>e.clone().applyQuaternion(qua))  
                 }
                 }
                 
                 
                 
                 
-                var isIntersectSelf = !this.isRect && len > 3 && this.intersectSelf(points)//检测相交
+                var isIntersectSelf = !this.isRect && len > 3 && this.intersectSelf(points2d)//检测相交
                 if(isIntersectSelf){
                 if(isIntersectSelf){
                     //not-allowed
                     //not-allowed
                     viewer.dispatchEvent({
                     viewer.dispatchEvent({
@@ -646,22 +649,22 @@ export class Measure extends THREE.Object3D {
                     })
                     })
                     this.facePlane && (this.point2dInfo = {
                     this.facePlane && (this.point2dInfo = {
                         originPoint0 ,
                         originPoint0 ,
-                        points2d : points,
+                        points2d,
                         quaInverse : qua.clone().invert()
                         quaInverse : qua.clone().invert()
                     })
                     })
                 }
                 }
                 
                 
-                var showGuideLine = this.isRect || len > 3
-                if(showGuideLine){
-                    this.updateLine(this.guideLine, intersectPos, location)
-                    this.guideLine.visible = true
-                } 
+                
                  
                  
             }
             }
             
             
-            
+            var showGuideLine = len>1 && (this.faceDirection || len > 3)
+            if(showGuideLine){
+                this.updateLine(this.guideLine, intersectPos, location)
+                this.guideLine.visible = true
+            } 
             this.setPosition(i, location);
             this.setPosition(i, location);
-            //console.log(this.points.map(e=>e.position.toArray())) 
+            //console.log(this.points.map(e=>e.toArray())) 
 
 
         }else{
         }else{
             this.setPosition(i, location);
             this.setPosition(i, location);
@@ -826,7 +829,7 @@ export class Measure extends THREE.Object3D {
     
     
 	setPosition (index, position) {
 	setPosition (index, position) {
 		let point = this.points[index];
 		let point = this.points[index];
-		point.position.copy(position);
+		point.copy(position);
 
 
 		let event = {
 		let event = {
 			type: 'marker_moved',
 			type: 'marker_moved',
@@ -837,7 +840,7 @@ export class Measure extends THREE.Object3D {
 		this.dispatchEvent(event);
 		this.dispatchEvent(event);
         
         
         let sphere = this.spheres[index];  
         let sphere = this.spheres[index];  
-        this.updateSphere(sphere, point.position)
+        this.updateSphere(sphere, point)
 	 
 	 
 	};
 	};
     intersectSelf(points2d){//add
     intersectSelf(points2d){//add
@@ -864,19 +867,7 @@ export class Measure extends THREE.Object3D {
         }
         }
           
           
     }
     }
-	/* getArea () {
-		let area = 0;
-		let j = this.points.length - 1;
-
-		for (let i = 0; i < this.points.length; i++) {
-			let p1 = this.points[i].position;
-			let p2 = this.points[j].position;
-			area += (p2.x + p1.x) * (p1.y - p2.y);
-			j = i;
-		}
-
-		return Math.abs(area / 2);
-	}; */
+	
 
 
 	getTotalDistance () {
 	getTotalDistance () {
 		if (this.points.length === 0) {
 		if (this.points.length === 0) {
@@ -886,16 +877,16 @@ export class Measure extends THREE.Object3D {
 		let distance = 0;
 		let distance = 0;
 
 
 		for (let i = 1; i < this.points.length; i++) {
 		for (let i = 1; i < this.points.length; i++) {
-			let prev = this.points[i - 1].position;
-			let curr = this.points[i].position;
+			let prev = this.points[i - 1];
+			let curr = this.points[i];
 			let d = prev.distanceTo(curr);
 			let d = prev.distanceTo(curr);
 
 
 			distance += d;
 			distance += d;
 		}
 		}
 
 
 		if (this.closed && this.points.length > 1) {
 		if (this.closed && this.points.length > 1) {
-			let first = this.points[0].position;
-			let last = this.points[this.points.length - 1].position;
+			let first = this.points[0];
+			let last = this.points[this.points.length - 1];
 			let d = last.distanceTo(first);
 			let d = last.distanceTo(first);
 
 
 			distance += d;
 			distance += d;
@@ -905,8 +896,8 @@ export class Measure extends THREE.Object3D {
 	}
 	}
 
 
 	getAngleBetweenLines (cornerPoint, point1, point2) {
 	getAngleBetweenLines (cornerPoint, point1, point2) {
-		let v1 = new THREE.Vector3().subVectors(point1.position, cornerPoint.position);
-		let v2 = new THREE.Vector3().subVectors(point2.position, cornerPoint.position);
+		let v1 = new THREE.Vector3().subVectors(point1, cornerPoint);
+		let v2 = new THREE.Vector3().subVectors(point2, cornerPoint);
 
 
 		// avoid the error printed by threejs if denominator is 0
 		// avoid the error printed by threejs if denominator is 0
 		const denominator = Math.sqrt( v1.lengthSq() * v2.lengthSq() );
 		const denominator = Math.sqrt( v1.lengthSq() * v2.lengthSq() );
@@ -928,7 +919,16 @@ export class Measure extends THREE.Object3D {
 
 
 		return this.getAngleBetweenLines(point, previous, next);
 		return this.getAngleBetweenLines(point, previous, next);
 	}
 	}
-
+    
+    getCenter(/* update */){ 
+        if(this.points.length>=3){
+            return this.center.clone()
+        }else if(this.points.length == 2){
+            return this.points[0].clone().add((this.points[1])).multiplyScalar(0.5)
+        }else return this.points[0].clone()
+        
+    }
+    
 	// updateAzimuth(){
 	// updateAzimuth(){
 	// 	// if(this.points.length !== 2){
 	// 	// if(this.points.length !== 2){
 	// 	// 	return;
 	// 	// 	return;
@@ -938,7 +938,7 @@ export class Measure extends THREE.Object3D {
 
 
 	// 	// const [p0, p1] = this.points;
 	// 	// const [p0, p1] = this.points;
 
 
-	// 	// const r = p0.position.distanceTo(p1.position);
+	// 	// const r = p0.distanceTo(p1);
 		
 		
 	// }
 	// }
     
     
@@ -977,7 +977,12 @@ export class Measure extends THREE.Object3D {
         })
         })
         areaLabel.addEventListener('mouseleave',()=>{
         areaLabel.addEventListener('mouseleave',()=>{
             this.setSelected(false, 'areaLabel')
             this.setSelected(false, 'areaLabel')
-        })  
+        }) 
+        areaLabel.addEventListener('click',()=>{
+            viewer.focusOnObject(this, 'measure')
+        })
+        viewer.setObjectLayers(areaLabel, 'measure' )
+      
         return areaLabel;
         return areaLabel;
         
         
         
         
@@ -1145,7 +1150,17 @@ export class Measure extends THREE.Object3D {
 
 
 
 
 
 
-
+    setUnitSystem(unitSystem){
+        if(unitSystem != this.unitSystem){
+            if(unitSystem == "metric"){
+                
+            }else if(unitSystem == 'imperial'){
+                
+            }
+            this.unitSystem = unitSystem
+            this.update()
+        }
+    }
 
 
 
 
 
 
@@ -1267,6 +1282,7 @@ function createAreaPlane(){
     },Measure.planeMats = planeMats)
     },Measure.planeMats = planeMats)
     var geometry = new THREE.Geometry();
     var geometry = new THREE.Geometry();
     var mesh = new THREE.Mesh(geometry, planeMats.default)
     var mesh = new THREE.Mesh(geometry, planeMats.default)
+    viewer.setObjectLayers(mesh, 'measure' )
     return mesh
     return mesh
 }
 }
 
 

+ 49 - 17
src/utils/MeasuringTool.js

@@ -178,7 +178,7 @@ export class MeasuringTool extends EventDispatcher{
 		e.scene.addEventListener('measurement_removed', this.onRemove);
 		e.scene.addEventListener('measurement_removed', this.onRemove);
 	}
 	}
 
 
-	startInsertion (args = {}) {
+	startInsertion (args = {}, callback) {
         
         
         
         
 		let domElement = this.viewer.renderer.domElement;
 		let domElement = this.viewer.renderer.domElement;
@@ -212,6 +212,8 @@ export class MeasuringTool extends EventDispatcher{
  
  
         let measure = new Measure(args);
         let measure = new Measure(args);
         this.scene.add(measure);
         this.scene.add(measure);
+        measure.isNew = true
+        
         
         
 		this.viewer.dispatchEvent({
 		this.viewer.dispatchEvent({
 			type: 'start_inserting_measurement',
 			type: 'start_inserting_measurement',
@@ -239,10 +241,10 @@ export class MeasuringTool extends EventDispatcher{
                         
                         
                     }
                     }
                     
                     
-                    var marker = measure.addMarker(measure.points[measure.points.length - 1].position.clone())
+                    var marker = measure.addMarker(measure.points[measure.points.length - 1].clone())
                      
                      
                     if(args.isRect && measure.spheres.length == 3){
                     if(args.isRect && measure.spheres.length == 3){
-                        measure.addMarker(measure.points[0].position.clone())
+                        measure.addMarker(measure.points[0].clone())
                     }
                     }
                     measure.editStateChange(true) //重新激活reticule状态
                     measure.editStateChange(true) //重新激活reticule状态
                     timer = setTimeout(()=>{//等 drag=null之后
                     timer = setTimeout(()=>{//等 drag=null之后
@@ -253,7 +255,7 @@ export class MeasuringTool extends EventDispatcher{
                 } 
                 } 
 				 
 				 
 			} else if (e.button === THREE.MOUSE.RIGHT /* e.drag.mouse === MOUSE.RIGHT */) {
 			} else if (e.button === THREE.MOUSE.RIGHT /* e.drag.mouse === MOUSE.RIGHT */) {
-				if(e.pressDistance < 2 )end();//非拖拽的话
+				if(e.pressDistance < 2 )end(e);//非拖拽的话
                 else {
                 else {
                     timer = setTimeout(()=>{//等 drag=null之后 //右键拖拽结束后需要重新得到drag
                     timer = setTimeout(()=>{//等 drag=null之后 //右键拖拽结束后需要重新得到drag
                         this.viewer.inputHandler.startDragging(e.drag.object,
                         this.viewer.inputHandler.startDragging(e.drag.object,
@@ -264,18 +266,30 @@ export class MeasuringTool extends EventDispatcher{
 			}
 			}
 		};
 		};
 
 
-		let end = (o={}) => {//确定、结束
+		let end = (e={}) => {//确定、结束
             if(args.minMarkers != void 0){
             if(args.minMarkers != void 0){
-                if(!o.complete && measure.spheres.length<=args.minMarkers){
-                    this.viewer.scene.removeMeasurement(measure)
+                if(!e.complete && measure.spheres.length<=args.minMarkers){//右键  当个数不够时取消 
+                    if(!Potree.settings.isOfficial) this.viewer.scene.removeMeasurement(measure)
+                    else if(e.drag){ //正式版本不允许右键退出, 继续
+                        timer = setTimeout(()=>{//等 drag=null之后 //右键拖拽结束后需要重新得到drag
+                            this.viewer.inputHandler.startDragging(e.drag.object,
+                                {endDragFun} 
+                            ); 
+                        },1) ;
+                        measure.editStateChange(true)
+                        return
+                    }
                 } 
                 } 
             }
             }
-            if (!o.complete && measure.spheres.length > 3) {
+            if (!e.complete && measure.spheres.length > 3) {
 				measure.removeMarker(measure.points.length - 1);
 				measure.removeMarker(measure.points.length - 1);
 			}
 			}
+            measure.isNew = false
             clearTimeout(timer) 
             clearTimeout(timer) 
 			this.viewer.removeEventListener('cancel_insertions', Exit);
 			this.viewer.removeEventListener('cancel_insertions', Exit);
-            this.viewer.inputHandler.removeEventListener('keydown', pressExit);
+            pressExit && this.viewer.inputHandler.removeEventListener('keydown', pressExit);
+            callback && callback()
+            
             /* this.viewer.dispatchEvent({
             /* this.viewer.dispatchEvent({
                 type: 'finish_inserting_measurement',
                 type: 'finish_inserting_measurement',
                 measure: measure
                 measure: measure
@@ -297,13 +311,18 @@ export class MeasuringTool extends EventDispatcher{
                 end()  //未结束时添加新的measure时会触发
                 end()  //未结束时添加新的measure时会触发
             }
             }
         }
         }
-        let pressExit = (e)=>{ 
-            if(e.keyCode == 27){//Esc
-                Exit()
-            }
-        }
-        viewer.inputHandler.addEventListener('keydown', pressExit) 
         this.viewer.addEventListener('cancel_insertions', Exit);
         this.viewer.addEventListener('cancel_insertions', Exit);
+        
+        
+        let pressExit
+        if(!Potree.settings.isOfficial){
+            pressExit = (e)=>{ 
+                if(e.keyCode == 27){//Esc
+                    Exit()
+                }
+            } 
+            this.viewer.inputHandler.addEventListener('keydown', pressExit) 
+        }
 		  
 		  
           
           
         var marker = measure.addMarker(new THREE.Vector3(0, 0, 0))
         var marker = measure.addMarker(new THREE.Vector3(0, 0, 0))
@@ -320,7 +339,20 @@ export class MeasuringTool extends EventDispatcher{
 	}
 	}
 	
 	
     
     
-    
+    createMeasureFromData(data){//add
+        const measure = new Measure(data);
+        
+        for(const point of data.points){
+            const pos = new THREE.Vector3().copy(point) 
+            measure.addMarker(pos); 
+        }
+        measure.dragChange(new THREE.Vector3().copy(data.points[data.points.length-1]) , data.points.length-1); 
+        //measure.update()
+        viewer.scene.addMeasurement(measure);
+        measure.setSelected(false )
+        if(measure.guideLine)measure.guideLine.visible = false
+        return  measure       
+    }
     
     
     
     
 	update(){
 	update(){
@@ -431,7 +463,7 @@ export class MeasuringTool extends EventDispatcher{
     
     
     
     
 	render(o={}){
 	render(o={}){
-        o.camera.layers.set(Potree.config.renderLayers.measure)
+        viewer.setCameraLayers(o.camera, ['measure'])
 		this.viewer.renderer.render(this.scene, o.camera/* this.viewer.scene.getActiveCamera() */);
 		this.viewer.renderer.render(this.scene, o.camera/* this.viewer.scene.getActiveCamera() */);
 	}
 	}
 };
 };

+ 72 - 4
src/utils/math.js

@@ -370,7 +370,7 @@ var math = {
             else{//否则考虑上距离,加一丢丢近大远小的效果
             else{//否则考虑上距离,加一丢丢近大远小的效果
                 var currentDis, nearBound, farBound
                 var currentDis, nearBound, farBound
                 if(op.camera.type == "OrthographicCamera"){
                 if(op.camera.type == "OrthographicCamera"){
-                    currentDis = op.camera.right - op.camera.left
+                    currentDis = (op.camera.right - op.camera.left) / op.camera.zoom
                 }else{
                 }else{
                     currentDis = op.position.distanceTo(op.camera.position);
                     currentDis = op.position.distanceTo(op.camera.position);
                 } 
                 } 
@@ -378,13 +378,13 @@ var math = {
                 //maxSize : mesh要表现的最大像素宽度;   nearBound: 最近距离,若比nearBound近,则使用maxSize
                 //maxSize : mesh要表现的最大像素宽度;   nearBound: 最近距离,若比nearBound近,则使用maxSize
             }
             }
             i.copy(op.position).project(op.camera),  //tag中心在屏幕上的二维坐标
             i.copy(op.position).project(op.camera),  //tag中心在屏幕上的二维坐标
-            o.set(op.resulution.x / 2, op.resulution.y / 2, 1).multiply(i), //转化成px   -w/2 到 w/2的范围
+            o.set(op.resolution.x / 2, op.resolution.y / 2, 1).multiply(i), //转化成px   -w/2 到 w/2的范围
             l.set(w / 2, 0, 0).add(o),  //加上tag宽度的一半
             l.set(w / 2, 0, 0).add(o),  //加上tag宽度的一半
-            c.set(2 / op.resulution.x, 2 / op.resulution.y, 1).multiply(l), //再转回  -1 到 1的范围
+            c.set(2 / op.resolution.x, 2 / op.resolution.y, 1).multiply(l), //再转回  -1 到 1的范围
             h.copy(c).unproject(op.camera);//再转成三维坐标,求得tag边缘的位置
             h.copy(c).unproject(op.camera);//再转成三维坐标,求得tag边缘的位置
             var g = h.distanceTo(op.position)//就能得到tag的三维半径
             var g = h.distanceTo(op.position)//就能得到tag的三维半径
         
         
-            return g
+            return g  //可能NAN  当相机和position重叠时
         }
         }
     }()
     }()
     ,
     ,
@@ -516,4 +516,72 @@ var math = {
     
     
 };
 };
 
 
+ 
+/* 
+   var e = this;
+            this.UnitService = t,
+            this.scopedConvert = function(t, n, i, r, o) {
+                return void 0 === i && (i = 2),
+                void 0 === r && (r = void 0),
+                void 0 === o && (o = void 0),
+                e.convert(t, n, i, r, o)
+            }
+        }
+        return t.prototype.convert = function(e, n, i, r, o, a) {
+            if (void 0 === i && (i = 2),
+            void 0 === r && (r = void 0),
+            void 0 === o && (o = void 0),
+            void 0 === a && (a = !1),
+            !e)
+                return "";
+            var s = t.getMostRelevantMeasurement(n, r || this.UnitService.currentSystem, e, o);
+            return t.getFormattedMeasurementString(s[0], s[1], i, a)
+        }
+        ,
+        t.getFormattedMeasurementString = function(t, e, n, i) {
+            return i && e.name === o.UnitsOfMeasurement.FOOT[0] ? this.formatImperialDistance(t * this.FEET_TO_INCHES_FACTOR) : i && e.name === o.UnitsOfMeasurement.INCH[0] ? this.formatImperialDistance(t) : t.toLocaleString(void 0, {
+                minimumFractionDigits: n,
+                maximumFractionDigits: n
+            }) + " " + e.symbol
+        }
+        ,
+        t.formatImperialDistance = function(e) {
+            var n = Math.round(8 * e)
+              , i = Math.floor(n / 8)
+              , r = Math.floor(i / t.FEET_TO_INCHES_FACTOR)
+              , o = i - r * t.FEET_TO_INCHES_FACTOR
+              , a = this.EIGHTHS_SYMBOLS[n % 8]
+              , s = 0 === o && "" !== a ? "" : o;
+            return "" !== s && "" !== a && (a = " " + a),
+            0 !== r ? r + "' " + s + a + '"' : "" + s + a + '"'
+        }
+        ,
+        t.getMostRelevantMeasurement = function(t, e, n, i) {
+            void 0 === i && (i = 0);
+            var a = r.values(o.UnitsOfMeasurement.getUnitsOfMeasurementByDomainAndSystem(t, e))
+              , s = r.filter(a, function(t) {
+                return t.factor >= i
+            })
+              , c = r.reduce(s, function(t, e) {
+                return e.fromBase(n) < t.fromBase(n) && e.fromBase(n) >= 1 ? e : t
+            });
+            return c ? [c.fromBase(n), c] : void 0
+        }
+        ,
+        t.FEET_TO_INCHES_FACTOR = 12,
+        t.EIGHTHS_SYMBOLS = ["", "⅛", "¼", "⅜", "½", "⅝", "¾", "⅞"],
+        t.ɵfac = function(e) {
+            return new (e || t)(c.ɵɵinject(l.UnitService))
+        }
+        ,
+        t.ɵprov = c.ɵɵdefineInjectable({
+            token: t,
+            factory: t.ɵfac,
+            providedIn: "root"
+        }),
+        t
+ */
+
+
+
 export default math
 export default math

+ 6 - 5
src/viewer/EDLRenderer.js

@@ -74,9 +74,9 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
 			width = this.screenshot.target.width;
 			width = this.screenshot.target.width;
 			height = this.screenshot.target.height;
 			height = this.screenshot.target.height;
 		} */
 		} */
-
-		this.rtEDL.setSize(e.resolution.x, e.resolution.y);
-		this.rtRegular.setSize(e.resolution.x, e.resolution.y);
+        let resolution = e.viewport.resolution2
+		this.rtEDL.setSize(resolution.x, resolution.y);
+		this.rtRegular.setSize(resolution.x, resolution.y);
         
         
 	}
 	}
 
 
@@ -221,12 +221,13 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
             viewer.renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
             viewer.renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
         }
         }
         
         
-        //skybox
-        camera.layers.set(Potree.config.renderLayers.skybox);
+        //skybox 
+        viewer.setCameraLayers(camera, ['skybox'])
         viewer.renderer.render(viewer.scene.scene, camera);
         viewer.renderer.render(viewer.scene.scene, camera);
         
         
         
         
         //pointcloud
         //pointcloud
+        viewer.setCameraLayers(camera, ['pointcloud'])
         camera.layers.set(Potree.config.renderLayers.pointcloud);
         camera.layers.set(Potree.config.renderLayers.pointcloud);
 		
 		
         //TODO adapt to multiple lights
         //TODO adapt to multiple lights

+ 4 - 25
src/viewer/LoadProject.js

@@ -89,32 +89,11 @@ function loadMeasurement(viewer, data){
 		return;
 		return;
 	}
 	}
     
     
+    data.points = data.points.map(point=>new THREE.Vector3(...point))
+    
+	const measure = viewer.measuringTool.createMeasureFromData(data)
 
 
-	const measure = new Measure(data);
-
-	/* measure.uuid = data.uuid;
-	measure.name = data.name;
-	measure.showDistances = data.showDistances;
-	measure.showCoordinates = data.showCoordinates;
-	measure.showArea = data.showArea;
-	measure.closed = data.closed;
-	measure.showAngles = data.showAngles;
-	measure.showHeight = data.showHeight;
-	measure.showCircle = data.showCircle;
-	measure.showAzimuth = data.showAzimuth;
-	measure.showEdges = data.showEdges; */
-	// color
-
-	for(const point of data.points){
-		const pos = new THREE.Vector3(...point);
-		measure.addMarker(pos);
-        
-	}
-    measure.dragChange(new THREE.Vector3(...data.points[data.points.length-1]), data.points.length-1); 
-    //measure.update()
-	viewer.scene.addMeasurement(measure);
-    measure.setSelected(false )
-    if(measure.guideLine)measure.guideLine.visible = false
+	 
 }
 }
 
 
 function loadVolume(viewer, data){
 function loadVolume(viewer, data){

+ 1 - 1
src/viewer/PropertyPanels/AreaPanel.js

@@ -38,7 +38,7 @@ export class AreaPanel extends MeasurePanel{
 	update(){
 	update(){
 		let elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
 		let elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
 		elCoordiantesContainer.empty();
 		elCoordiantesContainer.empty();
-		elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points.map(p => p.position)));
+		elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points));
 
 
 		let elArea = this.elContent.find(`#measurement_area`);
 		let elArea = this.elContent.find(`#measurement_area`);
 		elArea.html(this.measurement.area.toFixed(3));
 		elArea.html(this.measurement.area.toFixed(3));

+ 2 - 2
src/viewer/PropertyPanels/DistancePanel.js

@@ -56,9 +56,9 @@ export class DistancePanel extends MeasurePanel{
 	update(){
 	update(){
 		let elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
 		let elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
 		elCoordiantesContainer.empty();
 		elCoordiantesContainer.empty();
-		elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points.map(p => p.position)));
+		elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points));
 
 
-		let positions = this.measurement.points.map(p => p.position);
+		let positions = this.measurement.points;
 		let distances = [];
 		let distances = [];
 		for (let i = 0; i < positions.length - 1; i++) {
 		for (let i = 0; i < positions.length - 1; i++) {
 			let d = positions[i].distanceTo(positions[i + 1]);
 			let d = positions[i].distanceTo(positions[i + 1]);

+ 2 - 2
src/viewer/PropertyPanels/MeasurePanel.js

@@ -63,7 +63,7 @@ export class MeasurePanel{
 
 
 		let point = this.measurement.points[0];
 		let point = this.measurement.points[0];
 		
 		
-		for(let attributeName of Object.keys(point)){
+		/* for(let attributeName of Object.keys(point)){
 			if(attributeName === "position"){
 			if(attributeName === "position"){
 			
 			
 			}else if(attributeName === "rgba"){
 			}else if(attributeName === "rgba"){
@@ -87,7 +87,7 @@ export class MeasurePanel{
 					</tr>
 					</tr>
 				`));
 				`));
 			}
 			}
-		}
+		} */
 
 
 		return elTable;
 		return elTable;
 	}
 	}

+ 1 - 1
src/viewer/PropertyPanels/PointPanel.js

@@ -37,7 +37,7 @@ export class PointPanel extends MeasurePanel{
 	update(){
 	update(){
 		let elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
 		let elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
 		elCoordiantesContainer.empty();
 		elCoordiantesContainer.empty();
-		elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points.map(p => p.position)));
+		elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points));
 
 
 		let elAttributesContainer = this.elContent.find('.attributes_table_container');
 		let elAttributesContainer = this.elContent.find('.attributes_table_container');
 		elAttributesContainer.empty();
 		elAttributesContainer.empty();

+ 2 - 2
src/viewer/SaveProject.js

@@ -128,11 +128,11 @@ function createMeasurementData(measurement){
 		uuid: measurement.uuid,
 		uuid: measurement.uuid,
 		name: measurement.name,
 		name: measurement.name,
         measureType:measurement.measureType, //add 
         measureType:measurement.measureType, //add 
-		points: measurement.points.map(p => p.position.toArray()),
+		points: measurement.points.map(p => p.toArray()),
 		 
 		 
 	};
 	};
 	return data;
 	return data;
-}
+} 
 
 
 function createOrientedImagesData(images){
 function createOrientedImagesData(images){
 	const data = {
 	const data = {

+ 2 - 0
src/viewer/Scene.js

@@ -50,6 +50,8 @@ export class Scene extends EventDispatcher{
 
 
 		this.initialize();
 		this.initialize();
         
         
+        
+        //-------------
         this.axisArrow = new Axis();
         this.axisArrow = new Axis();
         this.scene.add(this.axisArrow)
         this.scene.add(this.axisArrow)
         this.axisArrow.visible = false
         this.axisArrow.visible = false

+ 5 - 1
src/viewer/View.js

@@ -202,6 +202,7 @@ export class View{
 
 
 
 
     setView(position, target, duration = 0, callback = null, onUpdate = null, Easing=''){
     setView(position, target, duration = 0, callback = null, onUpdate = null, Easing=''){
+        //待改成quater渐变
         let endPosition = null;
         let endPosition = null;
 		if(position instanceof Array){
 		if(position instanceof Array){
 			endPosition = new THREE.Vector3(...position);
 			endPosition = new THREE.Vector3(...position);
@@ -221,6 +222,7 @@ export class View{
 		if(duration === 0){
 		if(duration === 0){
 			this.position.copy(endPosition);
 			this.position.copy(endPosition);
 			endTarget && this.lookAt(endTarget);
 			endTarget && this.lookAt(endTarget);
+            onUpdate && onUpdate(1)
             callback && callback()
             callback && callback()
 		}else{
 		}else{
 
 
@@ -238,8 +240,10 @@ export class View{
                     this.lookAt(target);
                     this.lookAt(target);
                 }
                 }
 
 
+ 
+
                 onUpdate && onUpdate(t)//add
                 onUpdate && onUpdate(t)//add
-            }), duration, callback, 0, Easing ? easing[Easing] : easing.easeInOutQuad); 
+            }), duration, callback, 0, Easing ? easing[Easing] : easing.easeInOutQuad ); 
 
 
 
 
         } 
         } 

+ 4 - 4
src/viewer/sidebar.js

@@ -298,10 +298,10 @@ export class Sidebar{
 		));
 		));
         
         
         
         
-        // AREA
+        //Hor AREA
 		elToolbar.append(this.createToolIcon(
 		elToolbar.append(this.createToolIcon(
 			Potree.resourcePath + '/icons/area.svg',
 			Potree.resourcePath + '/icons/area.svg',
-			'[title]tt.area_measurement',
+			'[title]tt.Hor Area',
 			() => {
 			() => {
 				$('#menu_measurements').next().slideDown();
 				$('#menu_measurements').next().slideDown();
 				let measurement = this.measuringTool.startInsertion({
 				let measurement = this.measuringTool.startInsertion({
@@ -319,10 +319,10 @@ export class Sidebar{
 		));
 		));
         
         
         
         
-        // AREA
+        // Ver Area
 		elToolbar.append(this.createToolIcon(
 		elToolbar.append(this.createToolIcon(
 			Potree.resourcePath + '/icons/area.svg',
 			Potree.resourcePath + '/icons/area.svg',
-			'[title]tt.area_measurement',
+			'[title]tt.Ver Area',
 			() => {
 			() => {
 				$('#menu_measurements').next().slideDown();
 				$('#menu_measurements').next().slideDown();
 				let measurement = this.measuringTool.startInsertion({
 				let measurement = this.measuringTool.startInsertion({

+ 220 - 101
src/viewer/viewer.js

@@ -47,8 +47,11 @@ import Viewport from "./Viewport.js"
 import {ViewerBase} from "./viewerBase.js"
 import {ViewerBase} from "./viewerBase.js"
  
  
 import SplitScreen from '../utils/SplitScreen'
 import SplitScreen from '../utils/SplitScreen'
-
-
+import cameraLight from "../utils/cameraLight.js";
+import math from "../utils/math.js";
+ 
+import {UoMService}  from '../utils/UnitConvert'
+ 
  
  
 
 
 export class Viewer extends ViewerBase{
 export class Viewer extends ViewerBase{
@@ -68,7 +71,7 @@ export class Viewer extends ViewerBase{
         this.navigateMode = 'free' // 'panorama'; 'free'自由模式是只显示点云或者未进入到漫游点, 
         this.navigateMode = 'free' // 'panorama'; 'free'自由模式是只显示点云或者未进入到漫游点, 
         this.isEdit = true
         this.isEdit = true
         CursorDeal.attachToViewer(this)//ADD
         CursorDeal.attachToViewer(this)//ADD
-        
+        this.unitConvert = new UoMService();
 		//-------------
 		//-------------
         
         
         
         
@@ -396,6 +399,28 @@ export class Viewer extends ViewerBase{
 		}catch(e){
 		}catch(e){
 			this.onCrash(e);
 			this.onCrash(e);
 		}
 		}
+        
+        {
+            let pointDensity = ''
+            Object.defineProperty(Potree.settings , "pointDensity",{ 
+                get: function() {
+                    return pointDensity
+                },
+                set: (density)=>{
+                    if(pointDensity != density){
+                        var config = Potree.config.pointDensity[density];
+                        viewer.setPointBudget(config.pointBudget );
+                        Potree.maxPointLevel = config.maxLevel
+                        viewer.scene.pointclouds.forEach(e=>{
+                            e.maxLevel = config.maxLevel
+                        }) 
+                    }
+                }
+            })
+        }
+        
+        
+        
 	}
 	}
 
 
 	onCrash(error){
 	onCrash(error){
@@ -567,16 +592,18 @@ export class Viewer extends ViewerBase{
 		return this.showBoundingBox;
 		return this.showBoundingBox;
 	};
 	};
 
 
+    
+
 	setMoveSpeed (value) {
 	setMoveSpeed (value) {
-		if (this.moveSpeed !== value) {
-			this.moveSpeed = value;
+		if (this.getMoveSpeed() !== value) {
+			this.mainViewport.setMoveSpeed(value)
 			this.dispatchEvent({'type': 'move_speed_changed', 'viewer': this, 'speed': value});
 			this.dispatchEvent({'type': 'move_speed_changed', 'viewer': this, 'speed': value});
 		}
 		}
 	};
 	};
 
 
 	getMoveSpeed () {
 	getMoveSpeed () {
-		return this.moveSpeed;
-	};
+		return this.mainViewport.moveSpeed;
+	}; 
 
 
 	setWeightClassification (w) {
 	setWeightClassification (w) {
 		for (let i = 0; i < this.scene.pointclouds.length; i++) {
 		for (let i = 0; i < this.scene.pointclouds.length; i++) {
@@ -1185,7 +1212,7 @@ export class Viewer extends ViewerBase{
 
 
 	createControls () {
 	createControls () {
 		{ // create FIRST PERSON CONTROLS
 		{ // create FIRST PERSON CONTROLS
-			this.fpControls = new FirstPersonControls(this, this.scene.view);
+			this.fpControls = new FirstPersonControls(this, this.mainViewport);
 			this.fpControls.enabled = false;
 			this.fpControls.enabled = false;
 			this.fpControls.addEventListener('start', this.disableAnnotations.bind(this));
 			this.fpControls.addEventListener('start', this.disableAnnotations.bind(this));
 			this.fpControls.addEventListener('end', this.enableAnnotations.bind(this));
 			this.fpControls.addEventListener('end', this.enableAnnotations.bind(this));
@@ -2205,22 +2232,22 @@ export class Viewer extends ViewerBase{
         
         
         let renderSize = this.renderer.getSize(new THREE.Vector2());
         let renderSize = this.renderer.getSize(new THREE.Vector2());
         let needSResize = this.viewports.length > 1 || params_.resize
         let needSResize = this.viewports.length > 1 || params_.resize
-        
+        var viewports = params_.viewports || this.viewports
           
           
         
         
-        this.viewports.forEach(view=>{
+        viewports.forEach(view=>{
             let params = $.extend({},params_);
             let params = $.extend({},params_);
-            if(!params.target){
+            //if(!params.target){
                 params.camera = params.camera || view.camera;
                 params.camera = params.camera || view.camera;
-            }
+            //}
             
             
-            if(!view.active || params.viewport && params.viewport != view)return
+            if(!view.active)return
             var left,bottom,width,height
             var left,bottom,width,height
             if(!params_.target){
             if(!params_.target){
                 left = Math.floor(renderSize.x * view.left)
                 left = Math.floor(renderSize.x * view.left)
-                 , bottom = Math.floor(renderSize.y * view.bottom)
-                 , width = view.resolution.x
-                 , height = view.resolution.y
+                bottom = Math.floor(renderSize.y * view.bottom)
+                width = view.resolution.x // 用的是client的width和height
+                height = view.resolution.y
                 this.renderer.setViewport(left, bottom, width, height) //规定视口,影响图形变换 
                 this.renderer.setViewport(left, bottom, width, height) //规定视口,影响图形变换 
                 
                 
                 let scissorTest = view.width<1 || view.height<1 
                 let scissorTest = view.width<1 || view.height<1 
@@ -2232,7 +2259,7 @@ export class Viewer extends ViewerBase{
             /* needSResize && this.emitResizeMsg({ //resize everything  such as lines  targets 
             /* needSResize && this.emitResizeMsg({ //resize everything  such as lines  targets 
                 resolution: new THREE.Vector2(width,height), 
                 resolution: new THREE.Vector2(width,height), 
             }); */
             }); */
-            needSResize && this.emitResizeMsg(new THREE.Vector2(width,height), new THREE.Vector2(left, bottom/* renderSize.y-bottom-height */),view)
+            needSResize && this.emitResizeMsg(view)
             
             
             viewer.dispatchEvent({type: "render.begin",  viewer: viewer, viewport:view, params });
             viewer.dispatchEvent({type: "render.begin",  viewer: viewer, viewport:view, params });
             
             
@@ -2292,8 +2319,11 @@ export class Viewer extends ViewerBase{
     renderOverlay(params){
     renderOverlay(params){
         let camera = params.camera ? params.camera : this.scene.getActiveCamera();
         let camera = params.camera ? params.camera : this.scene.getActiveCamera();
         
         
+        
+        
+        
         if(!params.magnifier){//为什么要在点云之后渲染,否则透明失效 、 会被点云覆盖 
         if(!params.magnifier){//为什么要在点云之后渲染,否则透明失效 、 会被点云覆盖 
-            camera.layers.set(Potree.config.renderLayers.marker);//透明贴图层 skybox 、reticule marker 不能遮住测量线
+            this.setCameraLayers(camera, ['marker','reticule']) //透明贴图层 skybox 、reticule marker 不能遮住测量线
             this.renderer.render(this.scene.scene, camera); 
             this.renderer.render(this.scene.scene, camera); 
         } 
         } 
         this.dispatchEvent({type: "render.pass.scene", viewer: viewer});
         this.dispatchEvent({type: "render.pass.scene", viewer: viewer});
@@ -2306,11 +2336,11 @@ export class Viewer extends ViewerBase{
          
          
          
          
         if(!params.magnifier){ 
         if(!params.magnifier){ 
-            //测量线
+            //测量线 
             this.dispatchEvent({type: "render.pass.perspective_overlay", viewer:this, camera});
             this.dispatchEvent({type: "render.pass.perspective_overlay", viewer:this, camera});
             
             
-            if(!params.screenshot){
-                camera.layers.set(Potree.config.renderLayers.magnifier);//magnifier 遮住测量线
+            if(!params.screenshot && !params.isMap){
+                this.setCameraLayers(camera, ['magnifier']) //magnifier 遮住测量线 
                 this.renderer.render(this.scene.scene, camera);
                 this.renderer.render(this.scene.scene, camera);
             }
             }
         } 
         } 
@@ -2326,6 +2356,28 @@ export class Viewer extends ViewerBase{
     }
     }
     
     
     
     
+    setCameraLayers(camera, enableLayers){//add
+        camera.layers.disableAll()
+        enableLayers.forEach(e=>{
+            let layer = Potree.config.renderLayers[e]
+            if(layer == void 0){
+                console.error('setCameraLayer没找到layer!');
+                return 
+            }
+            camera.layers.enable(layer)
+        })
+    }
+    setObjectLayers(object, layerName){//add
+        let layer = Potree.config.renderLayers[layerName]
+        if(layer == void 0){
+            console.error('setCameraLayer没找到layer!');
+            return 
+        }
+        object.traverse(e=>{ 
+            e.layers.set(layer)
+        })
+    }
+    
     
     
     
     
 	render(params){//add params
 	render(params){//add params
@@ -2536,83 +2588,7 @@ export class Viewer extends ViewerBase{
 	}
 	}
     
     
     
     
-    /* makeScreenshot(camera, size, callback){
-
-		if(camera === undefined || camera === null){
-			camera = this.scene.getActiveCamera();
-		}
-
-		if(size === undefined || size === null){
-			size = this.renderer.getSize(new THREE.Vector2());
-		}
-        let {width, height} = size;
-        const aspect = width / height; 
-        camera.aspect = aspect
-        camera.updateProjectionMatrix() 
-        
-        
-        
-        let oldBudget = Potree.pointBudget;
-        Potree.pointBudget = Math.max(10 * 1000 * 1000, 2 * oldBudget);
-        let result = Potree.updatePointClouds(this.scene.pointclouds, camera, size );
-        Potree.pointBudget = oldBudget;
-        
-         
-		this.dispatchEvent({ //resize everything  such as lines  targets
-            type: 'resize', 
-            resolution: new THREE.Vector2(width,height), 
-        });
-       
-		let target = new THREE.WebGLRenderTarget(width, height, {
-			format: THREE.RGBAFormat,
-		});
- 
-		// HACK? removed because of error, was this important?
-		  
-		this.renderDefault({
-            target ,
-            camera ,
-            screenshot : true, 
-            width ,
-            height, 
-        });
-
-		let pixelCount = width * height;
-		let buffer = new Uint8Array(4 * pixelCount);
-
-		this.renderer.readRenderTargetPixels(target, 0, 0, width, height, buffer);
-
-        callback && callback(buffer) 
-		target.dispose();
-        
-        //resize back 
-        this.updateScreenSize({forceUpdateSize:true})   
-        
-		return {
-			width: width,
-			height: height,
-			buffer: buffer
-		};
-	} */
     
     
-    Screenshot(type, width=800, height=400, compressRatio){//add
-        let viewport,camera
-        if(type == 'mainView'){
-            viewport = this.mainViewport
-        }else if(type == 'map'){
-            viewport = this.mapViewer.viewports[0]
-        }
-         
-        
-        
-        var { buffer  } = this.makeScreenshot(camera, new THREE.Vector2(width,height), viewport);
-        
-        var dataUrl = Potree.Utils.pixelsArrayToDataUrl(buffer, width, height, compressRatio)
-        
-        Common.downloadFile(dataUrl, 'screenshot.jpg')
-        
-        
-    }
     
     
     
     
     getBoundingBox (pointclouds) {
     getBoundingBox (pointclouds) {
@@ -2628,13 +2604,156 @@ export class Viewer extends ViewerBase{
              
              
     }
     }
     
     
+    startScreenshot(info={},  width=800, height=400, compressRatio){//add
+        //可能需要一定时间,因在全景图模式需要加载完图片,所以返回一个promise
+        
+        let deferred = $.Deferred();
+        var screenshot = ()=>{
+            var { buffer  } = this.makeScreenshot( new THREE.Vector2(width,height)  );
+        
+            var dataUrl = Potree.Utils.pixelsArrayToDataUrl(buffer, width, height, compressRatio)
+            
+            Common.downloadFile(dataUrl, 'screenshot.jpg')
+            
+            deferred.resolve()
+        }
+        let oldStates = {
+            attachedToViewer : this.mapViewer.attachedToViewer,
+            views : this.viewports.map(e=>{
+                return {
+                    view : e.view.clone(),
+                    name : e.name
+                } 
+            })
+        }
+        if(info.type == 'measure'){//要截图双屏
+            if(!oldStates.attachedToViewer){
+                this.mapViewer.attachToMainViewer(true, 'measure')
+            }
+            viewer.updateScreenSize({forceUpdateSize:true, width, height}) 
+            
+            
+            let promise = this.focusOnObject(info.measurement, 'measure', 0)
+            promise.done(()=>{
+                screenshot()
+                
+            })
+            
+        }else{
+            screenshot()
+        }            
+         
+        /* const aspect = width / height; 
+        camera.aspect = aspect
+        camera.updateProjectionMatrix() */ 
+        
+        
+        
+        
+        
+        {
+        //恢复:
+            if(oldStates.attachedToViewer != this.mapViewer.attachedToViewer){
+                if(info.type == 'measure'){
+                    this.mapViewer.attachToMainViewer(false)
+                }
+                
+            }
+            oldStates.views.forEach(e=>{//恢复相机
+                var viewport = this.viewports.find(v=>v.name == e.name);
+                viewport.view.applyToCamera(viewport.camera);
+                
+            })
+                
+            
+            
+        }
+        
+        return deferred.promise()
+        
+        
+    }
     
     
     
     
-    
-    /* attachMapToViewer(state){
-        state ? viewer.mapViewer.attachToMainViewer(state);  
+    focusOnObject(object, type, duration ) {
+        //飞向热点、测量线等 。
+        let deferred = $.Deferred();
+        let target  = new THREE.Vector3,
+            position = new THREE.Vector3, 
+            dis;
+        duration = duration == void 0 ? 2000 : duration;     
+        let camera = viewer.scene.getActiveCamera()
         
         
-    } */
+        if (type == 'measure') {
+            let bound = new THREE.Box3() 
+            object.points.forEach(p => bound.expandByPoint(p))
+            
+            let boundSize = bound.getSize(new THREE.Vector3)
+            let {center,radius} = bound.getBoundingSphere({center:new THREE.Vector3}) //用不box的算不准,就保守用sphere了,缺点是无法占满屏,优点是不会靠太近
+            target.copy(object.getCenter())//copy(center)
+           
+            let aspect = 1 
+             
+            if(camera.aspect > aspect){//视野更宽则用bound的纵向来决定
+                dis = radius/ THREE.Math.degToRad(camera.fov / 2)
+            }else{
+                let hfov = cameraLight.getHFOVForCamera(camera, camera.aspect, 1 );
+                dis =  radius / THREE.Math.degToRad(hfov / 2)
+            }
+            
+            
+            if(Potree.settings.displayMode == 'showPointCloud'){ 
+                
+              
+                let dir = new THREE.Vector3().subVectors(camera.position, target).normalize() 
+                position.copy(target).add(dir.multiplyScalar(dis))
+                
+                if(this.mapViewer.attachedToViewer){ 
+                    this.mapViewer.fitToBound(target.clone(), boundSize.clone().multiplyScalar(2), duration)
+                }
+                
+            }else if(Potree.settings.displayMode == 'showPanos'){
+                let pano = viewer.images360.fitPanoTowardPoint({
+                    point : target,
+                    bestDistance : dis * 0.5 //乘以小数是为了尽量靠近
+                })
+                pano && viewer.images360.flyToPano({pano, target, duration, deferred })
+                return 
+            }
+        } else if (type == 'tag') {
+            const bestDistance = 2
+            target.copy(object.position)
+            if(Potree.settings.displayMode == 'showPointCloud'){ 
+                dis = bestDistance
+                let dir = new THREE.Vector3().subVectors(camera.position, target).normalize() 
+                position.copy(target).add(dir.multiplyScalar(dis))
+            
+            }else if(Potree.settings.displayMode == 'showPanos'){
+                let pano = viewer.images360.fitPanoTowardPoint({
+                    point : target,
+                    bestDistance  //越近越好,但不要太近,bestDistance左右差不多
+                })
+                pano && viewer.images360.flyToPano({pano, target, duration, deferred })
+                return                
+            }
+            
+        }
+
+        viewer.scene.view.setView(position, target, duration, ()=>{
+            deferred.resolve()
+        })
+        
+        
+        
+        
+        
+        
+        
+        
+        return deferred.promise()
+    }
+    
+   
     
     
 };
 };