Browse Source

fix: 12312

xzw 3 years ago
parent
commit
5fc9c30438

+ 51 - 9
src/Potree.js

@@ -145,21 +145,63 @@ export {scriptPath, resourcePath};
 
 
 export async function loadFile(path, callback){
-    let response = await fetch(path); 
-    let text = await response.text();
-    var data = JSON.parse(text)
-    callback && callback(data) 
-    return data
+    if(Potree.fileServer){
+        Potree.fileServer.get(path).then(data=>{
+            callback && callback(data)
+        })
+    }else{
+        let response = await fetch(path); 
+        let text = await response.text();
+        var data = JSON.parse(text)
+        callback && callback(data) 
+        return data
+    }
+    
+    //查询: http://192.168.0.26:8080/doc.html#/default/filter-%E6%BC%AB%E6%B8%B8%E7%82%B9/filterUsingGET    
 }
 
-export async function loadDatasets(path, callback){//之后直接把path写进来
-    return loadFile(path, callback) 
+export async function loadDatasets(callback){//之后直接把path写进来
+    var path 
+    if(Potree.fileServer){
+        path = `/laser/dataset/${Potree.settings.number}/getDataSet` 
+    }else{
+        path = `https://${Potree.config.urls.prefix2}/indoor/${Potree.settings.number}/api/datasets`
+          
+    }
+    return loadFile(path, callback)
     
 }
-export async function loadMapEntity(path, callback){
-    return loadFile(path, callback) 
+export async function loadMapEntity(callback){
+    var path 
+    if(Potree.fileServer){
+        path = `/laser/tiledMap/${Potree.settings.number}/tiledMap` 
+    }else{
+        path = `https://${Potree.config.urls.prefix2}/indoor/${Potree.settings.number}/api/tiled_maps`
+        
+    }
+    return loadFile(path, callback)
+     
+    
 }
  
+export async function loadPanos(center, callback){
+    var path 
+    let query = `?lat=${center.lat}&lon=${center.lon}&radius=200000`
+    if(Potree.fileServer){
+        path = `/laser/filter/${Potree.settings.number}/query` + query
+    }else{ 
+        path = `https://${Potree.config.urls.prefix2}/indoor/${Potree.settings.number}/api/images/filter` + query
+             
+    }
+    return loadFile(path, callback) 
+    
+}
+
+
+
+
+
+
 
 
 export function Log(value, color, fontSize){

+ 42 - 44
src/modules/Images360/Images360.js

@@ -46,6 +46,7 @@ export class Images360 extends EventDispatcher{
 
 		this.panos = [];
 		this.node = new THREE.Object3D();
+        this.node.name = 'ImagesNode'
         //this.node2 = new THREE.Object3D();
         
      
@@ -58,13 +59,8 @@ export class Images360 extends EventDispatcher{
         this.cube.layers.set(Potree.config.renderLayers.skybox)
         this.cube.name = 'skybox'
         viewer.scene.scene.add(this.cube)
-        
-        
-        
-        /* this.axisArrow = new Axis(params.center);
-        this.node.add(this.axisArrow) */
-        
-		//this.node.add(this.sphere);
+          
+      
 		this._visible = true;
 		 
 
@@ -763,7 +759,7 @@ export class Images360 extends EventDispatcher{
 
 
     closestPanoChanging(oldPano, newPano){
-        if(!Potree.setting.ifShowMarker)return
+        if(!Potree.settings.ifShowMarker)return
         
         oldPano && oldPano.hoverOff()
         newPano && newPano.hoverOn()
@@ -1084,50 +1080,52 @@ Images360.sortFunctions =  {//排序函数,涉及到两个item相减
 
 export class Images360Loader{ 
 
-    static async load2(url, viewer, params = {}){
+    static async load(viewer, params, callback ){
 
-		if(!params.transform){
-			params.transform = {
-				forward: a => a,
-			};
-		}
-		
 		 
-        var data = await Potree.loadFile(url)
-              
-        let images360 = new Images360(viewer, params);
+		
+		let center = viewer.transform.lonlatToLocal.inverse(viewer.bound.center)
+        center = {lat:center.y, lon:center.x} //中心点 
         
-        data = data.sort(function(a,b){return a.id-b.id})
-       
-        data.forEach(info=>{ 
-			let pano = new Panorama( info,  params.transform, images360   );
+        Potree.loadPanos(center,(data)=>{
             
-            pano.mesh.layers.set(Potree.config.renderLayers.marker)
-            pano.marker.layers.set(Potree.config.renderLayers.marker) 
-		 
-			images360.panos.push(pano);
-
-        })
+            let images360 = new Images360(viewer, params);
+            
+            data = data.sort(function(a,b){return a.id-b.id})
+           
+            data.forEach((info,i)=>{  
+                if(Potree.fileServer){
+                    info.id = i //info的id是一长串数字,改简单点
+                } 
+                let pano = new Panorama( info,  params.transform, images360   );
+                
+                /* pano.mesh.layers.set(Potree.config.renderLayers.marker)
+                pano.marker.layers.set(Potree.config.renderLayers.marker)  */
+             
+                images360.panos.push(pano);
 
-        console.log(data)
-        viewer.images360 = window.images360 = images360//add
-        images360.tileDownloader.setPanoData(images360.panos, [] /* , Potree.settings.number */);
+            })
+            
+            
+            viewer.setObjectLayers(images360.node, 'marker')
+             
+            viewer.images360 = window.images360 = images360//add
+            images360.tileDownloader.setPanoData(images360.panos, [] /* , Potree.settings.number */);
 
-        {
-            var panosBound = new THREE.Box3
-            images360.panos.forEach(pano=>{
-                panosBound.expandByPoint(pano.position)
-            }) 
-            images360.bound = {
-                bounding:panosBound,
-                size: panosBound.getSize(new THREE.Vector3),
-                center: panosBound.getCenter(new THREE.Vector3)
+            {
+                var panosBound = new THREE.Box3
+                images360.panos.forEach(pano=>{
+                    panosBound.expandByPoint(pano.position)
+                }) 
+                images360.bound = {
+                    bounding:panosBound,
+                    size: panosBound.getSize(new THREE.Vector3),
+                    center: panosBound.getCenter(new THREE.Vector3)
+                }
             }
-        }
-
-
 
-		return images360;
+            callback && callback(images360)
+        })   
 	}
 };
 

+ 3 - 2
src/modules/Images360/Panorama.js

@@ -63,7 +63,8 @@ class Panorama extends EventDispatcher{
         this.originPosition = new THREE.Vector3().fromArray(o.dataset_location) 
         this.originFloorPosition = new THREE.Vector3().fromArray(o.dataset_floor_location)
         
-        this.originID = parseInt(o.file_id)//"file_id":"00022"对应是原本的4dkk的id  
+        this.originID = parseInt(o.file_id)//"file_id":"00022"对应是原本的4dkk的id --来自vision.txt
+        
         
         
         this.pointcloud = viewer.scene.pointclouds.find(e=>e.dataset_id == o.dataset_id) || viewer.scene.pointclouds[0]
@@ -377,7 +378,7 @@ class Panorama extends EventDispatcher{
     createTextLabel(){
         this.removeTextLabel()
         this.label = new TextSprite($.extend(
-           labelProp, {text: this.id}) 
+           labelProp, {text: this.id}) //{text: `id:${this.id}, dataset:${this.pointcloud.name}, 4dkkId:${this.originID}`}
         );
         this.images360.node.add(this.label);
         this.floorPosition && this.label.position.copy(this.floorPosition)

+ 5 - 3
src/settings.js

@@ -101,7 +101,7 @@ const config = {//配置参数   不可修改
         backColor:'#333333',
         guideLineColor:"#FFFFFF",
         lineWidth: 4,
-        labelOpacity:0.6,
+        labelOpacity:0.8,
         textColor: "#FFFFFF"
         
     },
@@ -124,9 +124,11 @@ const config = {//配置参数   不可修改
         reticule: 3,
         measure:4,  
         magnifier:5, 
+        volume:6,
+        transformationTool:7,
         
-        map:6,
-        mapObjects:7,
+        map:8,
+        mapObjects:9,
     },
     
     tiling: {

+ 22 - 1
src/utils/Common.js

@@ -78,7 +78,7 @@ var Common = {
     ,
      
     CloneObject : function(copyObj, result, isSimpleCopy, extraReplace) {
-        //isSimpleCopy只复制最外层
+        //isSimpleCopy 只复制最外层
         //复制json		result的可能:普通数字或字符串、普通数组、复杂对象
         if(!copyObj)return copyObj //0 null undefined ''
         result = result || {};
@@ -110,6 +110,27 @@ var Common = {
         return result;
     }
     ,
+    CloneClassObject :function(copyObj ){//复杂类对象
+        var newobj = new copyObj.constructor();
+        this.CopyClassObject(newobj, copyObj) 
+        
+        return newobj
+    }
+    
+    ,
+     
+    CopyClassObject :function(targetObj,  copyObj){//复杂类对象
+        for(let i in copyObj){
+            if(i in copyObj.__proto__)break; //到函数了跳出 
+            if(copyObj[i].clone instanceof Function ){
+                targetObj[i] = copyObj[i].clone()
+            }else{
+                targetObj[i] = copyObj[i];
+            } 
+        }
+    }
+    ,
+    
     ifSame : function(object1, object2){
         if(object1 == object2  )return true // 0 != undefined  , 0 == ''
         else if(!object1 || !object2) return false

+ 11 - 7
src/utils/Magnifier.js

@@ -1,8 +1,7 @@
 
 import * as THREE from "../../libs/three.js/build/three.module.js";
 import math from './math'
- 
- 
+import Viewport from '../viewer/Viewport'
  
 let texLoader = new THREE.TextureLoader() 
 let circleGeo = new THREE.CircleGeometry(1.45,100);
@@ -22,7 +21,12 @@ export default class Magnifier extends THREE.Object3D {//放大镜or望远镜
         this.width = this.height = 256;
         this.camera = new THREE.PerspectiveCamera(50, 1, 0.1, 10000);  //fov aspect near far
         this.camera.up = new THREE.Vector3(0,0,1) 
-         
+        
+        
+        this.viewport = new Viewport( null, this.camera, {
+            left:0, bottom:0, width:1, height: 1, name:'magnifier' 
+        })
+        
         this.renderTarget = new THREE.WebGLRenderTarget(this.width,this.height, { 
             minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter,
             format: THREE.RGBAFormat ,
@@ -199,12 +203,12 @@ export default class Magnifier extends THREE.Object3D {//放大镜or望远镜
         //this.visible = false;//防止放大镜里有自己
         viewer.render({
             target : this.renderTarget,
-            viewports : [viewer.mainViewport],
+            viewports : [this.viewport],
             camera : this.camera,
             magnifier : true,
-            rtEDL: this.rtEDL,
-            width :this.renderTarget.width,
-            height: this.renderTarget.height,
+            rtEDL: this.rtEDL 
+            /* width :this.renderTarget.width,
+            height: this.renderTarget.height, */
         })
         //this.visible = true;
         this.waitRender = false

+ 4 - 4
src/utils/Measure.js

@@ -75,7 +75,7 @@ export class Measure extends THREE.Object3D {
 		this.edgeLabels = [];
 		this.angleLabels = [];
 		this.coordinateLabels = [];
-        this.area = 0
+        this.area = {value:0,string:''}
 
         
         
@@ -100,7 +100,7 @@ export class Measure extends THREE.Object3D {
             this.azimuth = createAzimuth();
             this.add(this.azimuth.node);
         }
-         
+        
 		
         /* this.heightLabel = createHeightLabel();
 		this.add(this.heightEdge);
@@ -114,7 +114,7 @@ export class Measure extends THREE.Object3D {
         
         this.selectStates = {}
         
-        this.setUnitSystem(viewer.unitConvert.UnitService.defaultSystem)
+        this.setUnitSystem(prop.unit || viewer.unitConvert.UnitService.defaultSystem)
          
 	}
  
@@ -188,7 +188,7 @@ export class Measure extends THREE.Object3D {
                     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 = "m";
                     let txtLength = Utils.addCommas(distance.toFixed(2));
                     edgeLabel.setText(`${txtLength} ${suffix}`); */

+ 8 - 3
src/utils/TransformationTool.js

@@ -99,7 +99,7 @@ export class TransformationTool {
 		}
 		this.frame = new THREE.LineSegments(boxFrameGeometry, new THREE.LineBasicMaterial({color: 0xffff00}));
 		this.scene.add(this.frame);
-
+        viewer.setObjectLayers(this.scene, 'transformationTool' )
 		
 	}
 
@@ -840,8 +840,13 @@ export class TransformationTool {
 				{
 					let ray = Utils.mouseToRay(pointer, camera, domElement.clientWidth, domElement.clientHeight);
 					let raycaster = new THREE.Raycaster(ray.origin, ray.direction);
-					let intersects = raycaster.intersectObjects(this.pickVolumes.filter(v => v.visible), true);
-
+					raycaster.layers.enableAll()//add
+                    
+                    let intersects = raycaster.intersectObjects(this.pickVolumes.filter(v => v.visible), true);
+                    
+                    
+                    
+                    
 					if(intersects.length > 0){
 						let I = intersects[0];
 						let handleName = I.object.handle;

+ 2 - 1
src/utils/Volume.js

@@ -145,7 +145,8 @@ export class BoxVolume extends Volume{
 		this.frame = new THREE.LineSegments(boxFrameGeometry, new THREE.LineBasicMaterial({color: 0x000000}));
 		// this.frame.mode = THREE.Lines;
 		this.add(this.frame);
-
+        
+        viewer.setObjectLayers(this, 'volume' )
 		this.update();
 	}
 

+ 3 - 3
src/viewer/EDLRenderer.js

@@ -74,9 +74,9 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
 			width = this.screenshot.target.width;
 			height = this.screenshot.target.height;
 		} */
-        let resolution = e.viewport.resolution2
-		this.rtEDL.setSize(resolution.x, resolution.y);
-		this.rtRegular.setSize(resolution.x, resolution.y);
+     
+		this.rtEDL.setSize(e.resolution.x, e.resolution.y);
+		this.rtRegular.setSize(e.resolution.x, e.resolution.y);
         
 	}
 

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

@@ -41,6 +41,6 @@ export class AreaPanel extends MeasurePanel{
 		elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points));
 
 		let elArea = this.elContent.find(`#measurement_area`);
-		elArea.html(this.measurement.area.toFixed(3));
+		elArea.html(this.measurement.area.value.toFixed(3));
 	}
 };

+ 15 - 4
src/viewer/View.js

@@ -1,6 +1,6 @@
 import * as THREE from "../../libs/three.js/build/three.module.js";
 import {transitions, easing, lerp} from '../utils/transitions.js'
-
+import Common from '../utils/Common'
 
 export class View{
 	constructor () {
@@ -12,6 +12,7 @@ export class View{
 
 		this.maxPitch = Math.PI / 2;
 		this.minPitch = -Math.PI / 2;
+        this.zoom = 1
 	}
     
     applyToCamera(camera){//add
@@ -19,19 +20,29 @@ export class View{
         camera.rotation.order = "ZXY";
         camera.rotation.x = Math.PI / 2 + this.pitch;
         camera.rotation.z = this.yaw;
+         
+        camera.updateMatrix();
+        camera.updateMatrixWorld();
+        camera.matrixWorldInverse.copy(camera.matrixWorld).invert();
+           
+        
     }
     
-    
+    copy(a){
+        Common.CopyClassObject(this, a)
+    }
     
 	clone () {
-		let c = new View();
+		/* let c = new View();
 		c.yaw = this.yaw;
 		c._pitch = this.pitch;
 		c.radius = this.radius;
 		c.maxPitch = this.maxPitch;
 		c.minPitch = this.minPitch;
 
-		return c;
+		return c; */
+        
+        return Common.CloneClassObject(this)
 	}
 
 	get pitch () {

+ 242 - 183
src/viewer/viewer.js

@@ -72,6 +72,7 @@ export class Viewer extends ViewerBase{
         this.isEdit = true
         CursorDeal.attachToViewer(this)//ADD
         this.unitConvert = new UoMService();
+       
 		//-------------
         
         
@@ -163,7 +164,25 @@ export class Viewer extends ViewerBase{
                 
             }
              
-            
+            if(!Potree.settings.isOfficial){
+                let domRoot = this.renderer.domElement.parentElement; 
+                let elAttach = $("<input type='button' value='test'></input>");
+                elAttach.css({
+                    position : "absolute",
+                    right : '10%',
+                    bottom: '20px',
+                    zIndex: "10000",
+                    fontSize:'1em', color:"black",
+                    background:'rgba(255,255,255,0.8)',
+                })
+                let state = false
+                elAttach.on("click", () => {
+                    window.buttonFunction &&  window.buttonFunction()
+                }); 
+                domRoot.appendChild(elAttach[0]);
+                
+                
+            }
             
 		}
         
@@ -319,7 +338,7 @@ export class Viewer extends ViewerBase{
             this.reticule = new Reticule(this) 
             this.scene.scene.add(this.magnifier) 
             this.scene.scene.add(this.reticule)
-            this.mainViewport = new Viewport(this.renderer, this.scene.view, this.scene.cameraP, {
+            this.mainViewport = new Viewport(  this.scene.view, this.scene.cameraP, {
                 left:0, bottom:0, width:1, height: 1, name:'MainView' 
             }) 
             this.viewports = [this.mainViewport]
@@ -1864,10 +1883,7 @@ export class Viewer extends ViewerBase{
             this.viewports.forEach(viewport=>{
                 if(!viewport.active)return
                 viewport.view.applyToCamera(viewport.camera)  
-                viewport.camera.updateMatrix();
-                viewport.camera.updateMatrixWorld();
-                viewport.camera.matrixWorldInverse.copy(viewport.camera.matrixWorld).invert();
-                 
+                  
             }) 
 		}
 		 
@@ -2228,12 +2244,18 @@ export class Viewer extends ViewerBase{
 
 	renderDefault(params_={}){
 		let pRenderer = this.getPRenderer();
-         
+        let renderSize
+        if(params_.target){
+            renderSize =  new THREE.Vector2(params_.target.width, params_.target.height)
+        }else{
+            renderSize = this.renderer.getSize(new THREE.Vector2());
+        }
+           
         
-        let renderSize = this.renderer.getSize(new THREE.Vector2());
-        let needSResize = this.viewports.length > 1 || params_.resize
         var viewports = params_.viewports || this.viewports
-          
+        let needSResize = viewports.length > 1 || params_.resize  
+        
+        
         
         viewports.forEach(view=>{
             let params = $.extend({},params_);
@@ -2243,28 +2265,41 @@ export class Viewer extends ViewerBase{
             
             if(!view.active)return
             var left,bottom,width,height
-            if(!params_.target){
+            { 
                 left = Math.floor(renderSize.x * view.left)
                 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) //规定视口,影响图形变换 
                 
-                let scissorTest = view.width<1 || view.height<1 
-                scissorTest && this.renderer.setScissor( left, bottom, width, height );//规定渲染范围 
-                this.renderer.setScissorTest( scissorTest );//开启WebGL剪裁测试功能,如果不开启,.setScissor方法设置的范围不起作用 | width==1且height==1时开启会只有鼠标的地方刷新,很奇怪
+                if(params_.target){//有target时最好viewport是专门建出来的
+                    width = Math.floor(renderSize.x * view.width)
+                    height = Math.floor(renderSize.y * view.height)
+                }else{
+                    width = view.resolution.x // 用的是client的width和height
+                    height = view.resolution.y
+                }
+                
+                
+                let scissorTest = view.width<1 || view.height<1
+                if(params_.target){
+                    params_.target.viewport.set(left, bottom, width, height);
+                    scissorTest && params_.target.scissor.set(left, bottom, width, height);
+                    params_.target.scissorTest = scissorTest
+                }else{
+                    this.renderer.setViewport(left, bottom, width, height) //规定视口,影响图形变换 
+                    scissorTest && this.renderer.setScissor( left, bottom, width, height );//规定渲染范围
+                    this.renderer.setScissorTest( scissorTest );//开启WebGL剪裁测试功能,如果不开启,.setScissor方法设置的范围不起作用 | width==1且height==1时开启会只有鼠标的地方刷新,很奇怪
+                    
+                }
+               
+            }    
              
-            }
-            
-            /* needSResize && this.emitResizeMsg({ //resize everything  such as lines  targets 
-                resolution: new THREE.Vector2(width,height), 
-            }); */
-            needSResize && this.emitResizeMsg(view)
+              
+
+            needSResize && this.emitResizeMsg({resolution: new THREE.Vector2(width,height), left:view.left,  bottom:view.bottom })//resize everything  such as lines  targets 
             
             viewer.dispatchEvent({type: "render.begin",  viewer: viewer, viewport:view, params });
             
             if(view.render){
-               view.render({renderer:this.renderer, renderOverlay: this.renderOverlay.bind(this) })
+               view.render({target: params_.target, renderer:this.renderer, renderOverlay: this.renderOverlay.bind(this) })
             } 
             
             
@@ -2272,9 +2307,9 @@ export class Viewer extends ViewerBase{
             
             if(!view.noPointcloud ){
                 
-                if(!params.target){ 
+                //if(!params.target){ 
                     params.width = width; params.height = height;
-                }
+                //}
                 
                 
                 
@@ -2298,7 +2333,7 @@ export class Viewer extends ViewerBase{
                 this.updateViewPointcloud(params.camera, new THREE.Vector2(params.width,params.height), true)
                 pRenderer.clear(params); 
                 pRenderer.render(params);
-                this.renderer.setRenderTarget(null)
+                
                 
                  
             } 
@@ -2310,7 +2345,7 @@ export class Viewer extends ViewerBase{
             this.dispatchEvent({type: "render.end",  viewer: this, viewport:view  });
         })
         
-         
+        this.renderer.setRenderTarget(null)
         
         
 	}
@@ -2346,14 +2381,14 @@ export class Viewer extends ViewerBase{
         } 
         
          
-          
+        this.setCameraLayers(camera, ['volume','transformationTool'])  
         this.renderer.render(this.clippingTool.sceneVolume, camera);
         this.renderer.render(this.transformationTool.scene, camera);
-         
-        
-        
+          
         
     }
+     
+    
     
     
     setCameraLayers(camera, enableLayers){//add
@@ -2378,8 +2413,7 @@ export class Viewer extends ViewerBase{
         })
     }
     
-    
-    
+     
 	render(params){//add params
 		if(Potree.measureTimings) performance.mark("render-start");
 
@@ -2403,6 +2437,180 @@ 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)
+            
+            if(!Potree.settings.isOfficial){
+                Common.downloadFile(dataUrl, 'screenshot.jpg') 
+            } 
+            deferred.resolve(dataUrl)
+           
+        }
+        
+        let mapViewport = this.mapViewer.viewports[0]
+        let mainViewport = this.mainViewport
+        let oldStates = {
+            attachedToViewer : this.mapViewer.attachedToViewer,
+            viewports : [mapViewport, mainViewport].map(e=>{
+                return  e.clone()  
+            }),
+            mapZoom: mapViewport.camera.zoom
+        }
+        if(info.type == 'measure'){//要截图双屏
+             
+            this.mapViewer.attachToMainViewer(true, 'measure', 0.5)
+           
+            //viewer.updateScreenSize({forceUpdateSize:true, width, height}) 
+            
+            //不同角度截图 得到三维的会不一样,因为focusOnObject是根据方向的
+            let promise = this.focusOnObject(info.measurement, 'measure', 0, /*  {mapDont:true} */)
+            promise.done(()=>{ 
+                 
+                this.viewports.forEach(e=>{
+                    e.view.applyToCamera(e.camera)
+                     
+                    this.dispatchEvent({  //update map
+                        type: "camera_changed", 
+                        camera: e.camera,
+                        viewport : e
+                    })   
+                    
+                }) 
+                screenshot()
+                
+            })
+            
+        }else{
+            screenshot()
+        }            
+         
+         
+        {
+        //恢复:
+            if(oldStates.attachedToViewer != this.mapViewer.attachedToViewer){
+                if(info.type == 'measure'){
+                    this.mapViewer.attachToMainViewer(false)
+                } 
+            }
+            mapViewport.camera.zoom = oldStates.mapZoom
+            
+            
+            
+            oldStates.viewports.forEach(old=>{//恢复相机
+                var viewport = [mapViewport, mainViewport].find(v=>v.name == old.name);
+                viewport.left = old.left;
+                viewport.width = old.width;
+                viewport.view.copy(old.view) 
+                viewport.view.applyToCamera(viewport.camera);  
+                 
+            }) 
+            
+            viewer.updateScreenSize({forceUpdateSize:true})//更新像素
+            
+            oldStates.viewports.forEach(old=>{//恢复相机
+                var viewport = [mapViewport, mainViewport].find(v=>v.name == old.name);
+                this.dispatchEvent({  //update map
+                    type: "camera_changed", 
+                    camera: viewport.camera,
+                    viewport : viewport
+                }) 
+            })
+        }
+        
+        return deferred.promise()
+        
+        
+    }
+    
+    
+    focusOnObject(object, type, duration, o={} ) {
+        //飞向热点、测量线等 。
+        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(o.mapDont || this.mapViewer.attachedToViewer){ 
+                this.mapViewer.fitToBound(target.clone(), boundSize.clone().multiplyScalar(2), duration)
+            }
+            
+            
+            if(Potree.settings.displayMode == 'showPointCloud'){  
+                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 : dis * 0.5 //乘以小数是为了尽量靠近
+                })
+                pano && viewer.images360.flyToPano({pano, target, duration, deferred })
+                return deferred
+            }
+        } 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 deferred                
+            }
+            
+        }
+
+        viewer.scene.view.setView(position, target, duration, ()=>{
+            deferred.resolve()
+        })
+         
+        
+        
+        return deferred.promise()
+    }
+    
+
+
+
+
+
+
+
+
+
 	resolveTimings(timestamp){
 		if(Potree.measureTimings){
 			if(!this.toggle){
@@ -2604,155 +2812,6 @@ 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()
-        
-        
-    }
-    
-    
-    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()
-    }
-    
    
     
 };