فهرست منبع

土方量结束

xzw 1 سال پیش
والد
کامیت
9cd6b850d6

+ 16 - 18
src/custom/modules/datasetAlignment/Alignment.js

@@ -9,16 +9,7 @@ var Alignment = {
     handleState:null,  //操作状态 'translate'|'rotate'
     bus: new THREE.EventDispatcher(), 
     
-    history : new History({ 
-        applyData: (data)=>{    
-            data.forEach(item=>{
-                Alignment.applyTemp(item)  
-            }) 
-        },
-        getData:(pointclouds)=>{ 
-            return Alignment.getTemp(pointclouds)
-        } 
-    }),
+    
 
     /* prepareRecord : true, 
     
@@ -59,7 +50,20 @@ var Alignment = {
     
     
     init:function(){ 
-        let transfromInfo   
+        let transfromInfo 
+        
+        this.history = new History({ 
+            applyData: (data)=>{    
+                data.forEach(item=>{
+                    Alignment.applyTemp(item)  
+                }) 
+                return true
+            },
+            getData:(pointclouds)=>{ 
+                return Alignment.getTemp(pointclouds)
+            } 
+        })
+        
         
         viewer.fpControls.addEventListener("transformPointcloud",(e)=>{ 
             if(e.pointclouds[0].dataset_id == Potree.settings.originDatasetId){//禁止手动移动初始数据集
@@ -154,13 +158,7 @@ var Alignment = {
             transfromInfo = null 
         })
         
-        viewer.inputHandler.addEventListener('keydown',e=>{ 
-            if(e.keyCode == 90 && e.event.ctrlKey){//Z
-                this.history.undo()
-            }else if(e.keyCode == 89 && e.event.ctrlKey){//Y
-                this.history.redo()
-            }
-        })  
+        
 		 
         
         // cursor:

+ 7 - 7
src/custom/modules/panos/Images360.js

@@ -358,7 +358,7 @@ export class Images360 extends THREE.EventDispatcher{
                             
                         if(config2.showSkybox || config2.pointUsePanoTex){ 
                             let wait = ( )=> { 
-                                console.log('waitdone')
+                                //console.log('waitdone')
                                 //if(e.pano && e.pano != this.currentPano)return  //loadedDepthImg
                                 setTimeout( ()=>{
                                     if(this.latestRequestMode == mode ){
@@ -369,7 +369,7 @@ export class Images360 extends THREE.EventDispatcher{
                             
                             //this.updateDepthTex()  
                             if(this.checkAndWaitForPanoLoad(this.currentPano,  this.basePanoSize, wait)){
-                                console.log('等待贴图加载2', this.currentPano.id)
+                                //console.log('等待贴图加载2', this.currentPano.id)
                                 return
                             }  
                         } 
@@ -490,7 +490,7 @@ export class Images360 extends THREE.EventDispatcher{
                 },
                 set: function(e) {
                     if(e != currentPano){
-                         console.log('set currentPano ', e.id)
+                        //console.log('set currentPano ', e.id)
                         currentPano && currentPano.exit()
                         e && e.enter()
                         currentPano = e
@@ -660,7 +660,7 @@ export class Images360 extends THREE.EventDispatcher{
 
 	cancelFlyToPano(toPano){//取消当前已有的飞行准备,前提是相机还未移动 
         if(viewer.mainViewport.view.isFlying() || toPano && this.latestToPano != toPano)return
-        Potree.Log('cancelFlyToPano', this.latestToPano && this.latestToPano.pano.id)
+        //Potree.Log('cancelFlyToPano', this.latestToPano && this.latestToPano.pano.id)
         this.nextPano = null 
         this.latestToPano = null 
     }
@@ -1250,7 +1250,7 @@ export class Images360 extends THREE.EventDispatcher{
                 }
             }
             if(wellCount / angles.length > minRatio){//合格个数
-                console.log('ifSheltered haha',  'id:', mainPano.id, subPano.id)
+                //console.log('ifSheltered haha',  'id:', mainPano.id, subPano.id)
                 return true
             }
         }  
@@ -1294,7 +1294,7 @@ export class Images360 extends THREE.EventDispatcher{
                 let dir = new THREE.Vector3().subVectors(dirPoints[i][0], dirPoints[i][1]).normalize();
                 let intersectPoint = viewer.images360.depthSampler.sample({dir}, mainPano, true) 
                 if(!intersectPoint || intersectPoint.distance+margin > dirPoints[i][0].distanceTo(dirPoints[i][1])){ 
-                    if(i>2)console.log('haha',i,'id:',mainPano.id,subPano.id)
+                    //if(i>2)console.log('haha',i,'id:',mainPano.id,subPano.id)
                     return true
                 }
             }
@@ -1760,7 +1760,7 @@ export class Images360 extends THREE.EventDispatcher{
     
     //等待部分加载完
     checkAndWaitForTiledPanoLoad(pano, basePanoSize, callback1, callback2, progressCallback, iswait, isclear, l) {
-        console.log('checkAndWaitForTiledPanoLoad',pano.id)  
+        //console.log('checkAndWaitForTiledPanoLoad',pano.id)  
         if (!pano) {
             console.error("Player.checkAndWaitForTiledPanoLoad() -> Cannot load texture for null pano.");
         }

+ 4 - 5
src/custom/modules/siteModel/BuildingBox.js

@@ -424,9 +424,8 @@ export class BuildingBox extends ctrlPolygon{//建筑实体,包括building, fl
                 this.updateTwoMidMarker(index+1) 
                 this.setMarkerSelected(marker, 'unhover') 
                 viewer.inputHandler.startDragging(newMarker , {/* dragViewport:viewer.mapViewer.viewports[0],  */   } ); //notPressMouse代表不是通过按下鼠标来拖拽.  dragViewport指定了只能在地图上拖拽
-            }
-            marker.addEventListener('drag', drag );
-            //marker.addEventListener('drop', drop);
+            } 
+            marker.addEventListener('drag', drag );  
             marker.addEventListener('mouseover', mouseover);
             marker.addEventListener('mouseleave', mouseleave);
         }
@@ -761,7 +760,7 @@ export class BuildingBox extends ctrlPolygon{//建筑实体,包括building, fl
         
         this.lineMesh.visible = true
         this.markers && this.markers.forEach(e=>Potree.Utils.updateVisible(e,'select',true) )
-        this.midMarkers && this.midMarkers.forEach(e=>e.visible = true)
+        this.midMarkers && this.midMarkers.forEach(e=>Potree.Utils.updateVisible(e,'select',true) )
         
         let holes = this.holes.concat(this.parentHoles)
         holes.forEach(e=>e.select()) 
@@ -795,7 +794,7 @@ export class BuildingBox extends ctrlPolygon{//建筑实体,包括building, fl
         
         this.lineMesh.visible = false
         this.markers && this.markers.forEach(e=>Potree.Utils.updateVisible(e,'select',false) )
-        this.midMarkers && this.midMarkers.forEach(e=>e.visible = false)
+        this.midMarkers && this.midMarkers.forEach(e=>Potree.Utils.updateVisible(e,'select',false) )
         
         let holes = this.holes.concat(this.parentHoles)
         holes.forEach(e=>e.unselect()) 

+ 39 - 3
src/custom/modules/siteModel/SiteModel.js

@@ -6,6 +6,9 @@ import {Images360} from '../panos/Images360.js'
 import {KeyCodes} from '../../../KeyCodes.js' 
 import {config } from "../../settings.js";
 import math from "../../utils/math.js";
+import History from "../../utils/History.js"
+
+
  
 const minFloorHeight = 0.5
 const ifDrawDatasetBound = true //显示一下数据集的tightBound线框
@@ -36,6 +39,34 @@ var SiteModel = {
           
         this.createHeightPull();
         
+        
+        
+        this.history = new History({ 
+            applyData: (data)=>{ 
+                if(data.entity.parent && data.entity.visible){
+                    data = Potree.Common.CloneObject(data) //避免使用后更改数据又被使用
+                    data.entity.reDraw() 
+                    data.entity.initData(data) 
+                    data.entity.addMidMarkers()
+                    data.entity.dispatchEvent('changeByHistory') 
+                    return true
+                }  
+            },
+            getData:(entity)=>{  
+                if(entity.isNew)return
+                return {
+                    entity, 
+                    points: entity.points.map(e=>e.clone()),
+                    ifDraw: true
+                }
+            } 
+        })  
+        
+        
+        
+        
+        
+        
         if(Potree.settings.isTest && ifDrawDatasetBound){
             viewer.addEventListener('allLoaded',()=>{
             
@@ -376,7 +407,8 @@ var SiteModel = {
             clearTimeout(timer) 
             entity.editStateChange(false)  
             //pressExit && viewer.inputHandler.removeEventListener('keydown', pressExit);
-            callback && callback(entity) 
+            callback && callback(entity)
+            viewer.dispatchEvent('endBuildEntity')            
         }
 
 
@@ -470,7 +502,7 @@ var SiteModel = {
              
         marker.isDragging = true 
         viewer.inputHandler.startDragging(marker , {dragViewport:mapViewport, endDragFun, notPressMouse:true} ); //notPressMouse代表不是通过按下鼠标来拖拽.  dragViewport指定了只能在地图上拖拽
-        
+        viewer.dispatchEvent('startBuildEntity')
           
         return entity;
     
@@ -696,9 +728,13 @@ var SiteModel = {
         }
         //console.log('添加实体:', entity.buildType, entity.sid, entity.uuid)
         this.bus.dispatchEvent('updated')
+        entity.addEventListener('startDragging',()=>{
+            this.history.beforeChange(entity)
+        })
         entity.addEventListener('marker_dropped',()=>{
             this.bus.dispatchEvent('updated')
-        })  
+            this.history.afterChange(entity)
+        })   
         
     },
     

+ 12 - 7
src/custom/objects/Magnifier.js

@@ -40,15 +40,19 @@ export default class Magnifier extends THREE.Object3D {//放大镜or望远镜
             let sizeType
             let colorType
             let opacityBefore = new Map()
+            let sizeBefore = new Map()
             let visiMap = new Map()
+            
+            
+            
             this.viewport.beforeRender = ()=>{
-                
-                
+                 
                 viewer.scene.pointclouds.forEach(e=>{//因为更改pointDensity时会自动变opacity,所以这项最先获取
                     visiMap.set(e,e.visible)
                     e.visible = Potree.Utils.getObjVisiByReason(e, 'datasetSelection'); //先将隐藏的点云显示
                 
                     opacityBefore.set(e,e.temp.pointOpacity)  
+                    sizeBefore.set(e,e.temp.pointSize)  
                 }) 
                 
                 
@@ -64,11 +68,12 @@ export default class Magnifier extends THREE.Object3D {//放大镜or望远镜
                     colorType = e.material.activeAttributeName
                     e.material.activeAttributeName = 'rgba'
                     e.changePointOpacity(1) 
-                   
+                    e.changePointSize(Potree.config.material.realPointSize, true)
                 }) 
             };
             
             
+            
             this.viewport.afterRender = ()=>{
                 Potree.settings.pointDensity = density
                 
@@ -78,8 +83,8 @@ export default class Magnifier extends THREE.Object3D {//放大镜or望远镜
                     e.material.pointSizeType = sizeType
                     e.material.activeAttributeName = colorType  
                     e.changePointOpacity(opacityBefore.get(e))  
-                }) 
-                
+                    e.changePointSize(sizeBefore.get(e)) 
+                })  
             } 
         }
         
@@ -141,8 +146,8 @@ export default class Magnifier extends THREE.Object3D {//放大镜or望远镜
         this.add(this.overlayMesh)
         
         this.position.set(-1000,-1000,-100000)//令它看不见
-        this.mesh.renderOrder = 10;
-        this.overlayMesh.renderOrder = 11;
+        this.mesh.renderOrder = Potree.config.renderOrders.magnifier;
+        this.overlayMesh.renderOrder = Potree.config.renderOrders.magnifier+1;
         this.aimPos
         Potree.Utils.setObjectLayers(this, 'magnifier' )
         //viewer.inputHandler.addInputListener(this)

+ 7 - 1
src/custom/objects/Reticule.js

@@ -30,7 +30,7 @@ export default class Reticule extends THREE.Mesh{
         this.crosshairTex.anisotropy = 4 
         this.forbitTex.anisotropy = 4 
         //this.layers.set(0/* RenderLayers.RETICULE */);
-        this.renderOrder = 100
+        this.renderOrder = Potree.config.renderOrders.reticule
         this.layers.set(Potree.config.renderLayers.marker);
         
         
@@ -65,9 +65,15 @@ export default class Reticule extends THREE.Mesh{
         
         viewer.addEventListener('measureMovePoint',startCrossStyle) 
         viewer.addEventListener('endMeasureMove',endCrossStyle)
+        viewer.addEventListener('startBuildEntity',startCrossStyle) 
+        viewer.addEventListener('endBuildEntity',endCrossStyle) 
         viewer.addEventListener('start_inserting_tag',startCrossStyle) 
         viewer.addEventListener('endTagMove',endCrossStyle)
         
+        
+        
+        
+        
         viewer.addEventListener('reticule_forbit',(e)=>{
             if(this.state.forbit != e.v){
                 console.log('change forbit ',e.v)

+ 4 - 0
src/custom/objects/TextSprite.js

@@ -195,6 +195,10 @@ export class TextSprite extends THREE.Object3D{
 		context.canvas.width = spriteWidth;
 		context.canvas.height = spriteHeight;
 		context.font = this.fontWeight + ' ' + this.fontsize * r + 'px ' + this.fontface; 
+        
+        if(spriteWidth>1000){
+            console.error('spriteWidth',spriteWidth,'spriteHeight',spriteHeight,this.fontsize,r,this.text,margin)
+        }
  
         /* let diff = 2//针对英文大部分在baseLine之上所以降低一点(metrics.fontBoundingBoxAscent - metrics.fontBoundingBoxDescent) / 2
 

+ 62 - 21
src/custom/objects/tool/Measure.js

@@ -48,7 +48,8 @@ const mainLabelProp = {
     textBorderThick:3  ,
     fontsize: 15 * textSizeRatio, 
     borderRadius : 12, margin:{x:20,y:4},
-    renderOrder : 5, pickOrder:5, 
+    renderOrder : Potree.config.renderOrders.measureLabel, 
+    pickOrder: Potree.config.renderOrders.measureLabel,  
     disToLine:-0.15,
     
     useDepth : true , 
@@ -65,7 +66,8 @@ const subLabelProp = {
     textBorderColor: {r:255, g: 255, b:255, a: 1.0},
     textBorderThick:3  ,
     fontsize: 14 * textSizeRatio,  
-    renderOrder : 4, pickOrder:4,
+    renderOrder : Potree.config.renderOrders.measureLabelSub, 
+    pickOrder: Potree.config.renderOrders.measureLabelSub,  
     disToLine:-0.13,
 }
 
@@ -143,7 +145,8 @@ export class Measure extends ctrlPolygon{
         this.addEventListener('isVisible', ()=>{
             viewer.mapViewer && viewer.mapViewer.dispatchEvent({type:'content_changed'})
         })
-         
+        
+        this.lastDropTime = 0
 	}
  
  
@@ -254,11 +257,11 @@ export class Measure extends ctrlPolygon{
             this.setEdgeLabelPos(label,p1,p2) 
             distance = distance == void 0 ? p1.distanceTo(p2) : distance; 
             //var text = viewer.unitConvert.convert(distance, 'distance', Potree.settings.precision, this.unitSystem, 1 , true)//distance要传0.1 这个factor
-            var text = viewer.unitConvert.convert(distance, 'distance',  Potree.settings.precision , this.unitSystem, 0.01 , true  )//distance要传0.1 这个factor
+            var text = this.getConvertString(distance, 'distance')   
             label.setText(text)
             return distance
         }
-         
+        
          
         /* let setEdgeLabel = (label,p1,p2,distance)=>{//设置label位置和字
             this.setEdgeLabelPos(label,p1,p2)
@@ -365,13 +368,20 @@ export class Measure extends ctrlPolygon{
         }else{//mulDistance Ring 2d面
             area = Math.abs(math.getArea(this.points))
         }
-        
-        let msg = viewer.unitConvert.convert(area, 'area', Potree.settings.precision, this.unitSystem/* , 0.1 */ )
+        let msg = this.getConvertString(area, 'area')   
+        //let msg = viewer.unitConvert.convert(area, 'area', Potree.settings.precision, this.unitSystem/* , 0.1 */ )
         this.area = {value:area, string:msg}
         return this.area
     }
     
-    
+    getConvertString(num, type){
+        return viewer.unitConvert.convert(num, type, Potree.settings.precision, this.unitSystem, true , 
+            {
+                'imperial': {minFactor: 0.01 },  
+                'metric': {minFactor: 0.01} 
+            }
+        )  
+    }
     
     
     ifShowTotalDis(){ 
@@ -545,23 +555,43 @@ export class Measure extends ctrlPolygon{
 
       
 	addMarker (o={}) {
-         
+        var index = o.index == void 0 ? this.points.length : o.index  //要当第几个
+        
         let marker = new Sprite({mat:this.getMarkerMaterial('default'), sizeInfo: markerSizeInfo, name:"measure_point"} )
         Potree.Utils.setObjectLayers(marker, 'measure' )
-        marker.pickOrder = marker.renderOrder = 3 
+        marker.pickOrder = marker.renderOrder = Potree.config.renderOrders.measureMarker 
         marker.markerSelectStates = {} 
         marker.addEventListener('startDragging',(e)=>{
             /*  if(e.drag.dragViewport.name == 'MainView') */viewer.inputHandler.dispatchEvent( {type: 'measuring',v:true, cause:'startDragging', situation:'dragging', object:this})
+        
+     
+            //add for 调试,方便后期增加点
+            if(!this.isNew && viewer.inputHandler.pressedKeys['M'.charCodeAt(0)] && this.points.length<this.maxMarkers){  
+                this.addMarker({index:this.markers.indexOf(marker)+1, point:marker.position.clone()})
+                   
+            }
+
+
+            viewer.measuringTool.history.beforeChange(this)
+            
         })
+        
+         
         marker.addEventListener('drop',(e)=>{
             viewer.inputHandler.dispatchEvent({type: 'measuring',  v:false, cause:'stopDragging', situation:'dragging', object:this}  )
-        
+            
+            this.lastDropTime = Date.now()
+            
             if(Potree.settings.adsorption){
                 this.isNew || viewer.viewports.forEach((viewport)=>{
                     this.getPointsPos2d(viewport, true )//forceUpdate
                 })  
             }
+             
+            viewer.measuringTool.history.afterChange(this)
+            
         })
+        
         //marker.measure = this 
         let edge
 		{ // edges 
@@ -580,21 +610,23 @@ export class Measure extends ctrlPolygon{
                 edge.addEventListener('mouseleave', mouseleave); 
                 edge.removeEventListener('addHoverEvent', addHoverEvent);
                 
-                edge.addEventListener('click',()=>{
-                    this.isNew || viewer.focusOnObject(this, 'measure')
+                edge.addEventListener('click',(e)=>{
+                    let now = Date.now()
+                    if(now - this.lastDropTime<100)return ;//防止拖拽marker时误触导致focus, 以及点到marker不focus
+                    this.isNew || viewer.measuringTool.isAdding || viewer.focusOnObject(this, 'measure') //正在添加测量线时不要focus其他线(容易误触)
                 })
                  
             }
             edge.addEventListener('addHoverEvent', addHoverEvent);
 		}
         
-        super.addMarker({point:o.point, marker:marker,  edge})
+        super.addMarker({point:o.point, index, marker,  edge})
         
         
 		if(this.showEdges){ // edge labels  
-            const edgeLabel = this.createEdgeLabel('edgeLabel', !this.closed) 
-			this.edgeLabels.push(edgeLabel); 
-			 
+            const edgeLabel = this.createEdgeLabel('edgeLabel', !this.closed)  
+			this.edgeLabels = [...this.edgeLabels.slice(0,index), edgeLabel, ...this.edgeLabels.slice(index,this.edgeLabels.length)]
+		 
 		}
 
 		
@@ -675,8 +707,10 @@ export class Measure extends ctrlPolygon{
         }
         if(absoluteState){
             marker.material = this.getMarkerMaterial('select')
+            marker.renderOrder = marker.pickOrder = Potree.config.renderOrders.measureMarker+1
         }else{
             marker.material = this.getMarkerMaterial('default')
+            marker.renderOrder = marker.pickOrder = Potree.config.renderOrders.measureMarker
         }
         
         marker.selected = absoluteState
@@ -710,8 +744,11 @@ export class Measure extends ctrlPolygon{
         if(absoluteState){
             this.markers.forEach(e=>this.setMarkerSelected(e, 'hover', 'selectAll' ) )
             
-            this.edges.forEach(e=>e.material = this.getLineMat('edgeSelect')   )
-			 
+            this.edges.forEach(e=>{
+                e.renderOrder = Potree.config.renderOrders.lines + 1
+                e.material = this.getLineMat('edgeSelect')   
+            }) 
+            
 			this.areaPlane && (this.areaPlane.material = planeMats.selected)
              
             
@@ -909,7 +946,7 @@ export class Measure extends ctrlPolygon{
                 this.setSelected(false, 'edgeLabel')
             })  
             edgeLabel.addEventListener('click',()=>{
-                this.isNew || viewer.focusOnObject(this, 'measure')
+                this.isNew || viewer.measuringTool.isAdding || viewer.focusOnObject(this, 'measure')
             })
         }
         edgeLabel.visible = false
@@ -951,7 +988,7 @@ export class Measure extends ctrlPolygon{
             this.setSelected(false, 'centerLabel')
         }) 
         centerLabel.addEventListener('click',()=>{
-            this.isNew || viewer.focusOnObject(this, 'measure')
+            this.isNew || viewer.measuringTool.isAdding || viewer.focusOnObject(this, 'measure')
         })
         Potree.Utils.setObjectLayers(centerLabel, 'measure' )
         centerLabel.setVisible(false) 
@@ -1498,7 +1535,11 @@ function createCircle(){
 
 
 
+
 /* 
+     按alt鼠标滚轮或WS键放慢。 
+     按Alt键可以平行屏幕拖拽点。&dragPolyBeyondPoint 后缀在拖拽到无点云区域也是此效果。
+     按M键拖拽点可以复制出当前点 
      
 
  */

+ 141 - 121
src/custom/objects/tool/MeasuringTool.js

@@ -1,6 +1,6 @@
 import * as THREE from "../../../../libs/three.js/build/three.module.js";
 import {Measure} from "./Measure.js";
-
+import History from "../../utils/History.js"
 import {Utils} from "../../../utils.js"; 
 import math from "../../utils/math.js";
 import {CameraMode} from "../../../defines.js"; 
@@ -8,123 +8,7 @@ import {TextSprite} from '../TextSprite.js'
  
 import {Prism} from "../../modules/volumeCompute/Prism.js";
  
- 
- 
-function updateAzimuth(viewer, measure){
-    if(!measure.showAzimuth)return
-	const azimuth = measure.azimuth;
-
-	const isOkay = measure.points.length === 2;
-
-	azimuth.node.visible = isOkay  
-
-	if(!azimuth.node.visible){
-		return;
-	}
-
-	const camera = viewer.scene.getActiveCamera();
-	const renderAreaSize = viewer.renderer.getSize(new THREE.Vector2());
-	const width = renderAreaSize.width;
-	const height = renderAreaSize.height;
-	
-	const [p0, p1] = measure.points;
-	const r = p0.position.distanceTo(p1.position);
-	const northVec = Utils.getNorthVec(p0.position, r, viewer.getProjection());
-	const northPos = p0.position.clone().add(northVec);
-
-	azimuth.center.position.copy(p0.position);
-	azimuth.center.scale.set(2, 2, 2);
-	
-	azimuth.center.visible = false;
-	// azimuth.target.visible = false;
-
-
-	{ // north
-		azimuth.north.position.copy(northPos);
-		azimuth.north.scale.set(2, 2, 2);
-
-		let distance = azimuth.north.position.distanceTo(camera.position);
-		let pr = Utils.projectedRadius(1, camera, distance, width, height);
-
-		let scale = (5 / pr);
-		azimuth.north.scale.set(scale, scale, scale);
-	}
-
-	{ // target
-		azimuth.target.position.copy(p1.position);
-		azimuth.target.position.z = azimuth.north.position.z;
-
-		let distance = azimuth.target.position.distanceTo(camera.position);
-		let pr = Utils.projectedRadius(1, camera, distance, width, height);
-
-		let scale = (5 / pr);
-		azimuth.target.scale.set(scale, scale, scale);
-	}
-
- 
-	azimuth.circle.position.copy(p0.position);
-	azimuth.circle.scale.set(r, r, r);
-	azimuth.circle.material.resolution.set(width, height);
-
-	// to target
-	azimuth.centerToTarget.geometry.setPositions([
-		0, 0, 0,
-		...p1.position.clone().sub(p0.position).toArray(),
-	]);
-	azimuth.centerToTarget.position.copy(p0.position);
-	azimuth.centerToTarget.geometry.verticesNeedUpdate = true;
-	azimuth.centerToTarget.geometry.computeBoundingSphere();
-	azimuth.centerToTarget.computeLineDistances();
-	azimuth.centerToTarget.material.resolution.set(width, height);
-
-	// to target ground
-	azimuth.centerToTargetground.geometry.setPositions([
-		0, 0, 0,
-		p1.position.x - p0.position.x,
-		p1.position.y - p0.position.y,
-		0,
-	]);
-	azimuth.centerToTargetground.position.copy(p0.position);
-	azimuth.centerToTargetground.geometry.verticesNeedUpdate = true;
-	azimuth.centerToTargetground.geometry.computeBoundingSphere();
-	azimuth.centerToTargetground.computeLineDistances();
-	azimuth.centerToTargetground.material.resolution.set(width, height);
-
-	// to north
-	azimuth.centerToNorth.geometry.setPositions([
-		0, 0, 0,
-		northPos.x - p0.position.x,
-		northPos.y - p0.position.y,
-		0,
-	]);
-	azimuth.centerToNorth.position.copy(p0.position);
-	azimuth.centerToNorth.geometry.verticesNeedUpdate = true;
-	azimuth.centerToNorth.geometry.computeBoundingSphere();
-	azimuth.centerToNorth.computeLineDistances();
-	azimuth.centerToNorth.material.resolution.set(width, height);
-
-	// label
-	const radians = Utils.computeAzimuth(p0.position, p1.position, viewer.getProjection());
-	let degrees = THREE.Math.radToDeg(radians);
-	if(degrees < 0){
-		degrees = 360 + degrees;
-	}
-	const txtDegrees = `${degrees.toFixed(2)}°`;
-	const labelDir = northPos.clone().add(p1.position).multiplyScalar(0.5).sub(p0.position);
-	if(labelDir.length() > 0){
-		labelDir.z = 0;
-		labelDir.normalize();
-		const labelVec = labelDir.clone().multiplyScalar(r);
-		const labelPos = p0.position.clone().add(labelVec);
-		azimuth.label.position.copy(labelPos);
-	}
-	azimuth.label.setText(txtDegrees);
-	let distance = azimuth.label.position.distanceTo(camera.position);
-	let pr = Utils.projectedRadius(1, camera, distance, width, height);
-	let scale = (70 / pr);
-	azimuth.label.scale.set(scale, scale, scale);
-}
-
+  
 export class MeasuringTool extends THREE.EventDispatcher{
 	constructor (viewer) {
 		super();
@@ -145,7 +29,27 @@ export class MeasuringTool extends THREE.EventDispatcher{
 		//this.scene.add(this.light);  
 		this.viewer.inputHandler.registerInteractiveScene(this.scene);
 		  
-        
+        this.history = new History({ 
+            applyData: (data)=>{ 
+                if(data.measure.parent && data.measure.visible){
+                    data = Potree.Common.CloneObject(data) //避免使用后更改数据又被使用
+                    data.measure.reDraw() 
+                    data.measure.initData(data) 
+                    data.measure.dispatchEvent('changeByHistory') 
+                    return true
+                }  
+            },
+            getData:(measure)=>{  
+                if(measure.isNew)return
+                return {
+                    measure, 
+                    points: measure.points.map(e=>e.clone()),
+                    dataset_points: measure.dataset_points.map(e=>e.clone()),
+                    points_datasets: measure.points_datasets.slice(),
+                    datasetId: measure.datasetId
+                }
+            } 
+        }),
         //this.scene = viewer.overlay//
         
         
@@ -427,7 +331,7 @@ export class MeasuringTool extends THREE.EventDispatcher{
         measure.editStateChange(true)
         
         let timer;
-        
+        this.isAdding = true
  
 
 		let endDragFun = (e) => {  
@@ -544,7 +448,7 @@ export class MeasuringTool extends THREE.EventDispatcher{
                 measure: measure
             }); */
             
-            
+            this.isAdding = false
             
             measure.dispatchEvent('createDone')
 		};
@@ -718,3 +622,119 @@ export class MeasuringTool extends THREE.EventDispatcher{
     
     
 };
+
+
+function updateAzimuth(viewer, measure){
+    if(!measure.showAzimuth)return
+	const azimuth = measure.azimuth;
+
+	const isOkay = measure.points.length === 2;
+
+	azimuth.node.visible = isOkay  
+
+	if(!azimuth.node.visible){
+		return;
+	}
+
+	const camera = viewer.scene.getActiveCamera();
+	const renderAreaSize = viewer.renderer.getSize(new THREE.Vector2());
+	const width = renderAreaSize.width;
+	const height = renderAreaSize.height;
+	
+	const [p0, p1] = measure.points;
+	const r = p0.position.distanceTo(p1.position);
+	const northVec = Utils.getNorthVec(p0.position, r, viewer.getProjection());
+	const northPos = p0.position.clone().add(northVec);
+
+	azimuth.center.position.copy(p0.position);
+	azimuth.center.scale.set(2, 2, 2);
+	
+	azimuth.center.visible = false;
+	// azimuth.target.visible = false;
+
+
+	{ // north
+		azimuth.north.position.copy(northPos);
+		azimuth.north.scale.set(2, 2, 2);
+
+		let distance = azimuth.north.position.distanceTo(camera.position);
+		let pr = Utils.projectedRadius(1, camera, distance, width, height);
+
+		let scale = (5 / pr);
+		azimuth.north.scale.set(scale, scale, scale);
+	}
+
+	{ // target
+		azimuth.target.position.copy(p1.position);
+		azimuth.target.position.z = azimuth.north.position.z;
+
+		let distance = azimuth.target.position.distanceTo(camera.position);
+		let pr = Utils.projectedRadius(1, camera, distance, width, height);
+
+		let scale = (5 / pr);
+		azimuth.target.scale.set(scale, scale, scale);
+	}
+
+ 
+	azimuth.circle.position.copy(p0.position);
+	azimuth.circle.scale.set(r, r, r);
+	azimuth.circle.material.resolution.set(width, height);
+
+	// to target
+	azimuth.centerToTarget.geometry.setPositions([
+		0, 0, 0,
+		...p1.position.clone().sub(p0.position).toArray(),
+	]);
+	azimuth.centerToTarget.position.copy(p0.position);
+	azimuth.centerToTarget.geometry.verticesNeedUpdate = true;
+	azimuth.centerToTarget.geometry.computeBoundingSphere();
+	azimuth.centerToTarget.computeLineDistances();
+	azimuth.centerToTarget.material.resolution.set(width, height);
+
+	// to target ground
+	azimuth.centerToTargetground.geometry.setPositions([
+		0, 0, 0,
+		p1.position.x - p0.position.x,
+		p1.position.y - p0.position.y,
+		0,
+	]);
+	azimuth.centerToTargetground.position.copy(p0.position);
+	azimuth.centerToTargetground.geometry.verticesNeedUpdate = true;
+	azimuth.centerToTargetground.geometry.computeBoundingSphere();
+	azimuth.centerToTargetground.computeLineDistances();
+	azimuth.centerToTargetground.material.resolution.set(width, height);
+
+	// to north
+	azimuth.centerToNorth.geometry.setPositions([
+		0, 0, 0,
+		northPos.x - p0.position.x,
+		northPos.y - p0.position.y,
+		0,
+	]);
+	azimuth.centerToNorth.position.copy(p0.position);
+	azimuth.centerToNorth.geometry.verticesNeedUpdate = true;
+	azimuth.centerToNorth.geometry.computeBoundingSphere();
+	azimuth.centerToNorth.computeLineDistances();
+	azimuth.centerToNorth.material.resolution.set(width, height);
+
+	// label
+	const radians = Utils.computeAzimuth(p0.position, p1.position, viewer.getProjection());
+	let degrees = THREE.Math.radToDeg(radians);
+	if(degrees < 0){
+		degrees = 360 + degrees;
+	}
+	const txtDegrees = `${degrees.toFixed(2)}°`;
+	const labelDir = northPos.clone().add(p1.position).multiplyScalar(0.5).sub(p0.position);
+	if(labelDir.length() > 0){
+		labelDir.z = 0;
+		labelDir.normalize();
+		const labelVec = labelDir.clone().multiplyScalar(r);
+		const labelPos = p0.position.clone().add(labelVec);
+		azimuth.label.position.copy(labelPos);
+	}
+	azimuth.label.setText(txtDegrees);
+	let distance = azimuth.label.position.distanceTo(camera.position);
+	let pr = Utils.projectedRadius(1, camera, distance, width, height);
+	let scale = (70 / pr);
+	azimuth.label.scale.set(scale, scale, scale);
+}

+ 43 - 4
src/custom/objects/tool/ctrlPolygon.js

@@ -43,6 +43,11 @@ export class ctrlPolygon extends THREE.Object3D {
     
     initData(prop){
         //开始加数据  
+        
+        prop.dataset_points && (this.dataset_points = prop.dataset_points)
+        prop.datasetId && (this.datasetId = prop.datasetId)
+        prop.points_datasets && (this.points_datasets = prop.points_datasets)
+        
         if(Potree.settings.editType == 'merge' || this.measureType == 'MulDistance Ring'){ //融合页面没有地图,measure的不需要指定datasetId,每个点都有各自的datasetId,跟着各自的模型走
             if(this.dataset_points){
                 this.dataset_points = this.dataset_points.map(e=>{
@@ -62,7 +67,7 @@ export class ctrlPolygon extends THREE.Object3D {
         
         
         if(prop.points){ 
-        
+            
             for(const p of prop.points){
                 const pos = new THREE.Vector3().copy(p) 
                 this.addMarker({point:pos}); 
@@ -110,8 +115,9 @@ export class ctrlPolygon extends THREE.Object3D {
             this.add(o.marker)
             this.markers = [...this.markers.slice(0,index), o.marker, ...this.markers.slice(index,this.markers.length)]
             this.updateMarker(o.marker, o.point)
-            o.marker.addEventListener('drag', this.dragMarker.bind(this));
-            o.marker.addEventListener('drop', this.dropMarker.bind(this));
+            o.marker.addEventListener('drag', this.dragMarker.bind(this),{importance:2});
+            o.marker.addEventListener('drop', this.dropMarker.bind(this),{importance:2});
+             
             o.marker.createTime = Date.now()
             
             let addHoverEvent = (e)=>{
@@ -132,6 +138,7 @@ export class ctrlPolygon extends THREE.Object3D {
                 
                 o.marker.addEventListener('startDragging', (e)=>{//for mobile
                     this.setMarkerSelected(o.marker, 'hover', 'single'); 
+                    this.dispatchEvent('startDragging')
                 });
                 o.marker.addEventListener('drop', (e)=>{//for mobile
                     this.setMarkerSelected(o.marker, 'unhover', 'single'); 
@@ -185,10 +192,38 @@ export class ctrlPolygon extends THREE.Object3D {
         
         I = e.intersect && (e.intersect.adsorption ? e.intersect.location : (e.intersect.orthoIntersect || e.intersect.location))
         
+        
+        let dragPolyBeyondPoint = ()=>{ 
+            let i = this.markers.indexOf(e.drag.object);
+            let point = this.points[i]
+               
+            const projected = point.clone().project(e.drag.dragViewport.camera);
+            projected.x = e.pointer.x
+            projected.y = e.pointer.y
+            
+            
+            const unprojected = projected.clone().unproject(e.drag.dragViewport.camera);
+            point.copy(unprojected);
+            
+            this.setPosition(i, point); 
+	        this.update();
+	        
+	        this.dispatchEvent({type:'dragChange', index:i});
+            
+            this.editStateChange(true)
+            
+        }
         //记录数据集
         
         //在三维中脱离点云(在map中拉到周围都没有点云的地方)的顶点,无法拖拽怎么办
          
+         
+        if(viewer.inputHandler.pressedKeys[18]){//alt 
+            dragPolyBeyondPoint()
+            return true
+        } 
+         
+         
         if (I) {  
             let i = this.markers.indexOf(e.drag.object);
             if (i !== -1) {  
@@ -208,6 +243,10 @@ export class ctrlPolygon extends THREE.Object3D {
             }
             this.editStateChange(true)
             return true
+            
+        }else if(Potree.settings.dragPolyBeyondPoint){//可以平移拖拽到无点的地方---测试用
+            dragPolyBeyondPoint()
+            return true 
         }
         
         
@@ -803,7 +842,7 @@ export class ctrlPolygon extends THREE.Object3D {
         object.isDragging = true 
         this.editStateChange(true)
         var timer = setTimeout(()=>{//等 drag=null之后 //右键拖拽结束后需要重新得到drag 
-            if(this.parent && object.isDragging){
+            if(this.parent && object.parent && object.isDragging){
                 //console.log('continueDrag')        
                 viewer.inputHandler.startDragging( object ,
                     {endDragFun: e.drag.endDragFun, notPressMouse:e.drag.notPressMouse, dragViewport:e.drag.dragViewport} 

+ 0 - 2
src/custom/potree.shim.js

@@ -1942,8 +1942,6 @@ PointCloudOctreeGeometryNode.prototype.loadPoints = function(){
     let name = this.name
     this.pcoGeometry.loader.load(this, ()=>{//callback
         viewer.dispatchEvent('pointcloud_changed')  
-         
-        
         //console.log('loadPoints success   ', name) 
     });
 } 

+ 18 - 7
src/custom/settings.js

@@ -100,7 +100,7 @@ const config = {//配置参数   不可修改
     pointDensity:{
         magnifier:{  
             maxLevelPercent: 1,
-            pointBudget : 8*1000*1000,  
+            //pointBudget : 8*1000*1000,  //手机崩溃
         }, 
         panorama:{//显示全景时的漫游。因为点只能显示1个像素的大小,所以必须很密集,但又要限制点的数量
             maxLevelPercent: 0.6,
@@ -134,7 +134,7 @@ const config = {//配置参数   不可修改
         middle:{//balanced  //不同场景相同级别所产生的numVisibleNodes和numVisiblePoints不同,如果分层比较细,可能要到level8才能看清,那么level5看到的点就很大且很少,如隧道t-e2Kb2iU
             maxLevelPercent: 0.7,
             percentByUser:true,
-            pointBudget: browser.isMobile() ? 2.0*1000*1000 : 3.5*1000*1000, 
+            pointBudget: browser.isMobile() ? 1.5*1000*1000 : 3.5*1000*1000, 
             minNodeSize :  30 / window.devicePixelRatio ,
         },
         high:{//highQuality
@@ -247,8 +247,18 @@ const config = {//配置参数   不可修改
     },
     
     renderOrders:{ //会影响到绘制、pick时的顺序。
-        model:10
+        model:10,
+        reticule:5,
+        measureMarker: 6,
+        measureLabelSub: 7,
+        measureLabel: 8,
+        sorptionSign:10,
+        model:10,
+        
+        
+        magnifier:50,
     }, 
+    
     siteModel:{
         names:{
             'building': '建筑',
@@ -296,8 +306,8 @@ const config = {//配置参数   不可修改
     highQualityMaxZoom: 2,
     ultraHighQualityMaxZoom: 3,
     panoFieldRadius : 10, //当前位置多远范围内可以切全景模式
-    clickMaxDragDis:5,
-    clickMaxPressTime:500, //ms
+    clickMaxDragDis:3,
+    clickMaxPressTime:200, //ms
     doubleClickTime:300,//双击间隔时间
     testNodeCount1: browser.isMobile() ? 6 : 4,  //testMaxNode次数达到这个数字时,changePointSize才使用nodeMaxLevel。 (调试时比较卡,在线上实际只需要3)
      
@@ -454,7 +464,8 @@ let settings = {//设置   可修改
     // moveToCenter:true, //针对数据集间隔很远的场景  dis>5000 容易抖动
     tiles3DMaxMemory: config.tiles3DMaxMemory,
     adsorption:false,//测量时吸附点 
-   
+    
+    dragPolyBeyondPoint: browser.urlHasValue('dragPolyBeyondPoint'),  //ctrlPolygon是否可以拖拽到没点云的地方
 }
 
 
@@ -469,6 +480,6 @@ if(settings.isFormal){
     settings.webSite = 'datav1'
 }
 
-console.log('2023-11')
+ 
  
 export {config, settings}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 59 - 0
src/custom/start.js


+ 14 - 10
src/custom/utils/DrawUtil.js

@@ -45,7 +45,7 @@ var LineDraw = {
         
         
         var line = new THREE.LineSegments(new THREE.BufferGeometry, mat);
-		line.renderOrder = o.renderOrder || 4
+		line.renderOrder = o.renderOrder || Potree.config.renderOrders.lines
   
         this.moveLine(line, posArr)
         
@@ -54,7 +54,7 @@ var LineDraw = {
 	},
     
 	moveLine: function (line, posArr) {
-        if(posArr.length == 0)return
+        //if(posArr.length == 0)return
         if(!line.uncontinuous)posArr = dealPosArr(posArr)
         let position = []
         posArr.forEach(e=>position.push(e.x,e.y,e.z))
@@ -114,7 +114,7 @@ var LineDraw = {
 		//line.computeLineDistances();
         line.uncontinuous = o.uncontinuous //线不连续,由线段组成
 		line.scale.set( 1, 1, 1 );
-		line.renderOrder = 2;
+		line.renderOrder = Potree.config.renderOrders.lines;
         
         this.moveFatLine(line, posArr)
         
@@ -272,18 +272,22 @@ var MeshDraw = {
         var shape = this.getShape(points, holes) //points是横截面 [vector2,...]
         
         if(options.extrudePath ){// 路径 :[vector3,...]
-            
-            var length = extrudePath.reduce((total, currentValue, currentIndex, arr)=>{
+             
+            var length = options.extrudePath.reduce((total, currentValue, currentIndex, arr)=>{
                 if(currentIndex == 0)return 0
                 return total + currentValue.distanceTo(arr[currentIndex-1]);
             },0)
-            options.extrudePath = new THREE.CatmullRomCurve3(extrudePath, options.closed ,  'catmullrom'  /* 'centripetal' */  , options.tension)
-            
-           
+            options.extrudePath = new THREE.CatmullRomCurve3(options.extrudePath, options.closed ,  'catmullrom'  /* 'centripetal' */  , options.tension)//tension:拐弯剧烈程度,但随着长度增长,该值需要减小,否则会扭曲
+            //options.extrudePath = new THREE.CatmullRomCurve3(options.extrudePath)
+            if(options.extrudePath.length == 2){
+                options.tension = 0 ;//否则一端扭曲
+                options.steps = 1
+            }
         }
-         
+        
+ 
         var extrudeSettings = $.extend(options,{
-            steps: options.steps != void 0 ? options.steps : ( options.extrudePath ? Math.round(length/0.3) : 1),
+            steps: options.steps != void 0 ? options.steps : ( options.extrudePath ? Math.round(length/(options.spaceDis || 0.3)) : 1), //分成几段    spaceDis每段长度
             bevelEnabled: false, //不加的话,height为0时会有圆弧高度
             //depth
         }) 

+ 20 - 4
src/custom/utils/History.js

@@ -15,16 +15,32 @@ class History extends THREE.EventDispatcher{
         this.getData = o.getData        //获取数据的方法
         
         this.dataBefore 
+        
+        
+       
+        ;(o.viewer || viewer).inputHandler.addEventListener('keydown', (e)=>{
+            if(e.keyCode == 90 && e.event.ctrlKey){//Z
+                this.undo()
+            }else if(e.keyCode == 89 && e.event.ctrlKey){//Y
+                this.redo()
+            }
+        })
+       
+         
+        
+        
+        
     }
     
     undo(){//回退 
         let length = this.undoList.length
          
         if(length>0){  
+            let unExist 
             let last = this.undoList.pop(); 
-            this.applyData && this.applyData(last.before) 
-            this.redoList.push(last);
-             
+            this.applyData && (unExist = !this.applyData(last.before)) 
+            unExist || this.redoList.push(last); 
+            unExist && this.undo()//找不到就回退下一个。
             this.dispatchEvent('undo')
             //console.log('undo',last)
         } 
@@ -47,7 +63,7 @@ class History extends THREE.EventDispatcher{
     beforeChange(o){//在变化之前(可能执行好几次直到变化完,但只有第一次有效)。 o的内容完全根据getData怎么定义
         if(!this.dataBefore){
             let data = this.getData(o)
-            this.dataBefore = data 
+            data && (this.dataBefore = data)
         } 
     } 
     

+ 11 - 8
src/custom/utils/SplitScreen4Views.js

@@ -108,8 +108,7 @@ SplitScreen4Views.split = function(o={}){
      
     viewer.scene.pointclouds.forEach(e=>{
         matBefore.opacity.set(e, e.temp.pointOpacity) 
-        matBefore.colorType = e.material.activeAttributeName
-        
+        matBefore.colorType = e.material.activeAttributeName 
         /* { 
             var map = new Map()
             newOpacityMap.set(e, map )
@@ -133,8 +132,8 @@ SplitScreen4Views.split = function(o={}){
         viewer.scene.pointclouds.forEach(e=>{ 
             if(this.name == "MainView"){ 
                 e.material.activeAttributeName = matBefore.colorType // 'rgba'
-                
                 e.material.useFilterByNormal = false 
+                //e.material.pointSizeType = Potree.config.material.pointSizeType
                 e.changePointOpacity(matBefore.opacity.get(e)) //1 //恢复下 e.temp.pointOpacity 其实就是1
                 
                 Potree.settings.pointDensity = 'fourViewportsMain'/* 'fourViewports' */ //本来想比另外三屏高一点质量,结果发现会闪烁,因为点云加载需要时间 (navvis仿版也是一样,以后看看能否优化)
@@ -142,6 +141,7 @@ SplitScreen4Views.split = function(o={}){
             }else{ 
                 e.material.activeAttributeName = "color"
                 e.material.useFilterByNormal = true 
+                //e.material.pointSizeType = 'ADAPTIVE'
                 
                 Potree.settings.pointDensity = 'fourViewports' //强制降低点云质量
                 
@@ -231,12 +231,15 @@ SplitScreen4Views.recover = function(){
         Potree.settings.displayMode = this.statesBefore.displayMode
     }
     
-    viewer.scene.pointclouds.forEach(e=>{ 
-        //e.material.color.set(this.statesBefore.mat.color)
-        //e.material.activeAttributeName = this.statesBefore.mat.colorType 
-        e.material.useFilterByNormal = false
-        //e.material.opacity = this.statesBefore.mat.opacity  
+    viewer.scene.pointclouds.forEach(e=>{  
+        e.material.useFilterByNormal = false 
+        //e.material.pointSizeType = Potree.config.material.pointSizeType        
     }) 
+    
+    
+    
+    
+    
     viewer.setPointStandardMat(false)
     viewer.mapViewer.setViewLimit('standard')
     

+ 19 - 9
src/custom/utils/UnitConvert.js

@@ -270,9 +270,10 @@ class UoMService{
         return  this.convert(t, n, precision, r, minFactor)
     }
     
-    convert(number, domain, precision = 2, system, minFactor, ifEighths = !1, ifRestrictFactor ) { 
+    convert(number, domain, precision = 2, system, ifEighths = !1,  o   /* minFactor,   ifRestrict  */) {
+        let {minFactor,  restrictUnit} = o[system]
         //if (!number) return "";
-        var s = this.getMostRelevantMeasurement(domain, system || this.UnitService.currentSystem, number, minFactor, ifRestrictFactor);
+        var s = this.getMostRelevantMeasurement(domain, system || this.UnitService.currentSystem, number, minFactor, restrictUnit);
         return this.getFormattedMeasurementString(s[0], s[1], precision, ifEighths)
     }
     
@@ -322,7 +323,7 @@ class UoMService{
         return  0 !== r ? r + "' " + s + a + '"' : "" + s + a + '"'
     }
     
-    getMostRelevantMeasurement(domain, system, number, minFactor=0, ifRestrictFactor) {
+    getMostRelevantMeasurement(domain, system, number, minFactor=0, restrictUnit) {
         /* var a = r.values(UnitsOfMeasurement.getUnitsOfMeasurementByDomainAndSystem(domain, system))
           , s = r.filter(a, function(t) {  
             return t.factor >= i
@@ -334,12 +335,14 @@ class UoMService{
         let u = UnitsOfMeasurement.getUnitsOfMeasurementByDomainAndSystem(domain, system)
         for(let i in u){a.push(u[i])}
          
-        let s   
-        if(ifRestrictFactor){//是否只用这一单位,如只用mm。如果不是,就会寻找最大的接近的单位,如设置最小为mmminFactor=0.001),则1.2米时是'1.2m'、0.2米时是'20cm'、0.002米时是'2mm'
-            s = a.filter(m=>m.factor == minFactor)  
-        }else{
-            s = a.filter(m=>m.factor >= minFactor)
-        } 
+        let s = a  
+        if(s.length > 1){
+            if(restrictUnit){//是否只用这一单位,如只用mm。如果不是,就会寻找最大的接近的单位,如设置最小为mmminFactor=0.001),则1.2米时是'1.2m'、0.2米时是'20cm'、0.002米时是'2mm'
+                s = a.filter(m=>m.name == restrictUnit)  
+            }else{
+                s = a.filter(m=>m.factor >= minFactor)
+            } 
+        }
        
         let c = s.reduce(function(prev, currentValue) {//reduce最终值是最后一次return的值 ( 没看懂这句话作用) 
             return currentValue.fromBase(number) < prev.fromBase(number) && currentValue.fromBase(number) >= 1 ? currentValue : prev
@@ -389,6 +392,13 @@ class UoMService{
     长度:
         var text = viewer.unitConvert.convert(distance, 'distance', void 0, unitSystem, 0.1 , true)//distance要传0.1这个factor。 最后一个参数传true代表使用八分之一表示。
 
+
+
+长度每种system有多种单位, 而面积和体积都只有一种
+
+
+
+
  */
 
 

+ 2 - 2
src/custom/utils/math.js

@@ -635,8 +635,8 @@ var math = {
     linearClamp(value, xArr , yArr){ //xArr需要按顺序从小到大,yArr对应xArr中的值
         
         let len = xArr.length 
-        if(value < xArr[0]) return yArr[0]
-        if(value > xArr[len - 1]) return yArr[len - 1]
+        if(value <= xArr[0]) return yArr[0]
+        if(value >= xArr[len - 1]) return yArr[len - 1]
         let i = 0 
         
         while(++i < len ){

+ 177 - 81
src/custom/viewer/ViewerNew.js

@@ -619,11 +619,11 @@ export class Viewer extends ViewerBase{
                         let pointBudget;
                         var config = Potree.config.pointDensity[density];
                         
-                        if(this.magnifier.visible){//放大镜打开时不要切换pointBudget,否则点云会闪烁。这时使用最高密度。
+                        /* if(this.magnifier.visible){//放大镜打开时不要切换pointBudget,否则点云会闪烁。这时使用最高密度。
                             pointBudget = Potree.config.pointDensity['magnifier'].pointBudget
                         }else{
                             pointBudget = config.pointBudget
-                        }
+                        } */
                         
                         
                         viewer.setMinNodeSize(config.minNodeSize || Potree.config.minNodeSize)
@@ -1682,7 +1682,7 @@ export class Viewer extends ViewerBase{
 	}
 
 	setPointBudget (value) { //pointBudget: 每次刷新显示点数量的最大值。  缓存中的点数量也跟此有关,但大于这个数值。
-		if (Potree.pointBudget !== value) {
+		if (Potree.pointBudget !== value && value) {
 			Potree.pointBudget = parseInt(value);
 			this.dispatchEvent({'type': 'point_budget_changed', 'viewer': this});
 		}
@@ -3144,8 +3144,7 @@ export class Viewer extends ViewerBase{
 		}
 		
 		params.target || renderer.clear();
-   
-		 
+    
 	}
 
     getBuffer(viewport){//根据不同viewport返回rtEDL的texture
@@ -3258,6 +3257,7 @@ export class Viewer extends ViewerBase{
                 this.clear(params)  
                 pRenderer.clearTargets(params);
                  
+                 
                 this.renderBG(view)
                  
                 if(Potree.settings.notAdditiveBlending){
@@ -3657,7 +3657,7 @@ export class Viewer extends ViewerBase{
             
             {//恢复:
                 
-                 
+                this.backgroundOpacity = oldStates.bgOpacity;
                 
                 if(info.type == 'measure' || info.type.includes('prism2d')){
                     this.modules.SiteModel.pauseUpdateEntity = false
@@ -3668,13 +3668,12 @@ export class Viewer extends ViewerBase{
                 
                 if(info.type.includes('prism2d')){
                     //viewer.mapViewer.transparentBG = false;
-                    this.backgroundOpacity = oldStates.bgOpacity; 
+                     
                     (info.prisms || [info.prism]).forEach(prism=>{
                         prism.changeStyleForScreenshot(false)
                     })  
                 }
-                
-                
+                 
                 
                 this.images360.panos.forEach(pano=>{
                     Potree.Utils.updateVisible(pano, 'screenshot', true)
@@ -3735,7 +3734,8 @@ export class Viewer extends ViewerBase{
         let mainViewport = this.mainViewport
         let viewports = [],  oldStates = {
             viewports:[],
-            pano: Potree.settings.displayMode == 'showPanos' ? viewer.images360.currentPano : null
+            pano: Potree.settings.displayMode == 'showPanos' ? viewer.images360.currentPano : null,
+            bgOpacity : this.backgroundOpacity
         }
         if(!info.type.includes('prism2d')){
             viewports.push(mainViewport)
@@ -3759,7 +3759,13 @@ export class Viewer extends ViewerBase{
             }) 
         }                    
         Potree.Utils.updateVisible(this.reticule, 'screenshot', false)//令reticule不可见 
-                                  
+         
+         
+        
+        if(info.bgOpacity != void 0){
+            this.backgroundOpacity = info.bgOpacity
+        }
+         
         Potree.settings.pointDensity = 'screenshot'
         
         
@@ -3896,29 +3902,32 @@ export class Viewer extends ViewerBase{
                 prism.changeStyleForScreenshot(true, {hideLabel: info.type != 'prism2d-all',  showName: info.type == 'prism2d-all' })
                    
             }) 
+            this.scene.measurements.forEach(e=>Potree.Utils.updateVisible(e,'screenshot', prisms.includes(e))  )
+            
+            
             
             let {promise} = this.focusOnObject({points}, 'prisms2d', 0, { 
                 minMapWidth: 0.5  , onlyMap:true,  focusBoundCenter:true, boundExpandRatio:1.4
             })  
-            
-            oldStates.bgOpacity = this.backgroundOpacity
+             
             this.backgroundOpacity = 0
                  
             promise.done(()=>{
                 updateCamera() 
-                 
+                focusDatasets(prisms) //更新平面图  可能有漏洞,当不在任何一个数据集内的话?
+                this.mapViewer.waitLoadDone(screenshot.bind(this))//等待地图所有加载完
+                
                 if(info.type == 'prism2d-all'){//全部 带平面图   
-                    focusDatasets(prisms) //更新平面图  可能有漏洞,当不在任何一个数据集内的话?
-                    this.mapViewer.waitLoadDone(screenshot.bind(this))//等待地图所有加载完
+                    
                 }else{//单个
                  
-                    this.scene.measurements.forEach(e=>Potree.Utils.updateVisible(e,'screenshot', e == info.prism)  )
+                    
                     //info.prism.setSelected(true, 'screenshot')
                     //viewer.mapViewer.transparentBG = true
                 
-                    Potree.Utils.updateVisible(viewer.mapViewer.mapLayer.sceneGroup, 'screenshot-prism', false)
+                    /* Potree.Utils.updateVisible(viewer.mapViewer.mapLayer.sceneGroup, 'screenshot-prism', false)
 
-                    screenshot()
+                    screenshot() */
                 }
             })
              
@@ -4964,68 +4973,7 @@ export class Viewer extends ViewerBase{
         return r && r.score > 1 ? result[0].item : null  
     }
     
-    /* addObjectTest1(){//加水管
-        
-        if(Potree.settings.number == 't-8KbK1JjubE'){
-            
-            let boundingBox = new THREE.Box3()
-            boundingBox.min.set(-1,-1,-1); boundingBox.max.set(1,1,1)
-            
-            
-            let radius = 0.08;
-            let radialSegments = 5 
-            let radSegments = Math.PI*2 / radialSegments
-            var circlePts = [];//横截面
-            for(let i=0;i<radialSegments;i++){
-                let angle = radSegments * i;
-                circlePts.push(new THREE.Vector2(radius * Math.cos(angle),   radius * Math.sin(angle) ))
-            }  
-            var count = 0
-            var addMesh = (color, path, height)=>{//height:在path之上的高度,负数代表在path之下
-                var name = 'cylinder'+count
-                var mat = new THREE.MeshStandardMaterial({color,  depthTest:false, roughness:0.4,metalness:0.5}) 
-                let linePath = path.map(e=>new THREE.Vector3().copy(e).setZ(e.z+height))
-                let geo = MeshDraw.getExtrudeGeo( circlePts, null,{ extrudePath:linePath, tension:0.2}   )
-                var mesh = new THREE.Mesh(geo,mat);
-                mesh.name = name
-                window[name] = mesh
-                
-                mesh.boundingBox = boundingBox
-                mesh.matrixAutoUpdate = false
-                mesh.matrix.copy(viewer.scene.pointclouds[0].transformMatrix)
-                mesh.matrixWorldNeedsUpdate = true
-                
-                this.scene.scene.add(mesh);
-                 
-                count ++
-            }
-            
-            
-            let linePath, height 
-            
-            //地上管子 黄色 
-            linePath = [{"x":-109.83,"y":-68.33,"z":-7.52},{"x":-95.17,"y":-59.3,"z":-7.38},  {"x":-38.75,"y":-24.01,"z":-6.01},{"x":0.5,"y":0.19,"z":-3.89},{"x":39.29,"y":24.41,"z":-1.31}
-               ,{"x":43.58,"y":27.7,"z":-0.97},{"x":40.22,"y":35.37,"z":-0.67}// 拐弯向右 
-               ,   {"x":39.18,"y":36.71,"z":0.35},{"x":38.69,"y":36.04,"z":18.04} // 拐弯向上  
-            ]
-            height = radius + 0.05;
-            addMesh('#b86', linePath, height)
-             
-             
-            
-            //地下管子 藍色
-            linePath = [{"x":-108.24,"y":-70.61,"z":-7.52}, {"x":-57.8,"y":-39.31,"z":-6.72},{"x":-18.8,"y":-15.35,"z":-5.01},{"x":55.87,"y":31.67,"z":-0.04},{"x":110.53,"y":66.48,"z":5.14}
-            ] 
-            height = -0.5;
-            addMesh('#48a', linePath, height)
-              
-            
-            
-        }
-        
-        
-    } 
-     */
+    
     /*  createRoomEv(){ 
         
         const environment = new RoomEnvironment();
@@ -5578,6 +5526,154 @@ export class Viewer extends ViewerBase{
         */
     }
     
+    
+    
+    
+    /* addTube(){//加水管 自动生成
+        
+        if(Potree.settings.number == 't-8KbK1JjubE'){
+            
+            let boundingBox = new THREE.Box3()
+            boundingBox.min.set(-1,-1,-1); boundingBox.max.set(1,1,1)
+            
+            
+            let radius = 0.08;
+            let radialSegments = 5 
+            let radSegments = Math.PI*2 / radialSegments
+            var circlePts = [];//横截面
+            for(let i=0;i<radialSegments;i++){
+                let angle = radSegments * i;
+                circlePts.push(new THREE.Vector2(radius * Math.cos(angle),   radius * Math.sin(angle) ))
+            }  
+            var count = 0
+            var addMesh = (color, path, height)=>{//height:在path之上的高度,负数代表在path之下
+                var name = 'cylinder'+count
+                var mat = new THREE.MeshStandardMaterial({color,  depthTest:false, roughness:0.4,metalness:0.5}) 
+                let linePath = path.map(e=>new THREE.Vector3().copy(e).setZ(e.z+height))
+                let geo = MeshDraw.getExtrudeGeo( circlePts, null,{ extrudePath:linePath, tension:0.2}   )
+                var mesh = new THREE.Mesh(geo,mat);
+                mesh.name = name
+                window[name] = mesh
+                
+                mesh.boundingBox = boundingBox
+                mesh.matrixAutoUpdate = false
+                mesh.matrix.copy(viewer.scene.pointclouds[0].transformMatrix)
+                mesh.matrixWorldNeedsUpdate = true
+                
+                this.scene.scene.add(mesh);
+                 
+                count ++
+            }
+            
+            
+            let linePath, height 
+            
+            //地上管子 黄色 
+            linePath = [{"x":-109.83,"y":-68.33,"z":-7.52},{"x":-95.17,"y":-59.3,"z":-7.38},  {"x":-38.75,"y":-24.01,"z":-6.01},{"x":0.5,"y":0.19,"z":-3.89},{"x":39.29,"y":24.41,"z":-1.31}
+               ,{"x":43.58,"y":27.7,"z":-0.97},{"x":40.22,"y":35.37,"z":-0.67}// 拐弯向右 
+               ,   {"x":39.18,"y":36.71,"z":0.35},{"x":38.69,"y":36.04,"z":18.04} // 拐弯向上  
+            ]
+            height = radius + 0.05;
+            addMesh('#b86', linePath, height)
+             
+             
+            
+            //地下管子 藍色
+            linePath = [{"x":-108.24,"y":-70.61,"z":-7.52}, {"x":-57.8,"y":-39.31,"z":-6.72},{"x":-18.8,"y":-15.35,"z":-5.01},{"x":55.87,"y":31.67,"z":-0.04},{"x":110.53,"y":66.48,"z":5.14}
+            ] 
+            height = -0.5;
+            addMesh('#48a', linePath, height)
+              
+            
+            
+        }
+        
+        
+    }  */
+    
+    
+    addTube(datas){//加水管 自动生成
+        
+        
+        for(let number in datas){  
+            if(number == Potree.settings.number){
+                
+                let data = datas[number]
+                
+                
+                
+                let boundingBox = new THREE.Box3()
+                boundingBox.min.set(-1,-1,-1); boundingBox.max.set(1,1,1)
+                
+                
+                
+                
+                var index = 0
+                var addMesh = ({color, path, height,fromDataset, radius=0.08, datasetId=Potree.settings.originDatasetId, spaceDis, tension=0.1, visiEntity}={})=>{//height:在path之上的高度,负数代表在path之下
+                    var name = 'tube_'+index
+                    
+                
+                    let radialSegments = 30//THREE.Math.clamp( Math.round(radius * 800), 10, 40)
+                    let radSegments = Math.PI*2 / radialSegments
+                    var circlePts = [];//横截面
+                    for(let i=0;i<radialSegments;i++){
+                        let angle = radSegments * i;
+                        circlePts.push(new THREE.Vector2(radius * Math.cos(angle),   radius * Math.sin(angle) ))
+                    }
+                    
+                    var mat = new THREE.MeshStandardMaterial({color,   /* wireframe:true,   depthTest:false,*/  roughness:0.9,metalness:0.3}) 
+                    let linePath = path.map(e=>{
+                        e instanceof Array && (e = new THREE.Vector3().fromArray(e))
+                        let pos 
+                        if(fromDataset){
+                            //获取:JSON.stringify(viewer.scene.measurements[0].dataset_points.map(e=>Potree.math.toPrecision(e.toArray(),3)))
+                            pos = Potree.Utils.datasetPosTransform({ fromDataset: true, position:e, datasetId}) 
+                        }else{
+                            pos = new THREE.Vector3().copy(e)
+                        }
+                         
+                        return pos.setZ(pos.z+height)
+                    })
+                    console.log(linePath)
+                    let geo = MeshDraw.getExtrudeGeo( circlePts, null,{ extrudePath:linePath, tension, spaceDis}   )
+                    var mesh = new THREE.Mesh(geo,mat);
+                    mesh.name = name
+                    window[name] = mesh
+                    
+                    mesh.boundingBox = boundingBox
+                    mesh.matrixAutoUpdate = false
+                    fromDataset || mesh.matrix.copy(viewer.scene.pointclouds[0].transformMatrix)
+                    mesh.matrixWorldNeedsUpdate = true
+                    
+                    this.scene.scene.add(mesh);
+                     
+                     
+                     
+                    if(visiEntity){
+                        this.modules.SiteModel.bus.addEventListener('buildingChange',(e)=>{
+                            Potree.Utils.updateVisible(mesh,'isInEntity', e.entity && e.entity.name == visiEntity)
+                        })
+                    }
+                    
+                }
+                
+                
+                while(index < data.length){ 
+                    addMesh(data[index])
+                    index++
+                }
+                
+            } 
+        }
+        
+        /* 
+        可能用到的
+        viewer.scene.measurements.forEach(e=>e.edgeLabels.forEach(e=>Potree.Utils.updateVisible(e,'f',false)))
+        JSON.stringify(viewer.scene.measurements.find(e=>e.visible).dataset_points.map(e=>Potree.math.toPrecision(e.toArray(),3)))
+     
+         */
+    } 
+    
     addSprite(e){//api
         let sprite 
         

+ 1 - 1
src/custom/viewer/viewerBase.js

@@ -156,7 +156,7 @@ export class ViewerBase extends THREE.EventDispatcher{
         
         if(this.viewports){
             this.viewports.forEach((view,i)=>{
-                if(!view.active)return
+                //if(!view.active)return
                 
                 var width_ = width * view.width
                 var height_ = height * view.height

+ 1 - 1
src/materials/ExtendPointCloudMaterial.js

@@ -374,7 +374,7 @@ export class ExtendPointCloudMaterial extends PointCloudMaterial {
          
         let doUpdate = (this.clipBoxes_in.length !== clipBoxes_in.length) || (this.clipBoxes_out.length != clipBoxes_out.length)
                     || this.highlightBoxes.length !== highlightBoxes.length || this.bigClipInBox != bigClipInBox 
-                    || (this.prisms.length != prismPolygons.length)                                                                                                                                                                                                                                                                                                                                                                                  
+                    || (this.prisms.length != prismPolygons.length) || this.prisms.maxPointsCount != prismPolygons.maxPointsCount                                                                                                                                                                                                                                                                                                                                                                              
 		//this.clipBoxes = clipBoxes; 
 		if (doUpdate){
 			this.shaderNeedsUpdate = true 

+ 10 - 3
src/navigation/FirstPersonControlsNew.js

@@ -414,6 +414,13 @@ export class FirstPersonControls extends THREE.EventDispatcher {
                     if (e.delta < 0) {
                         speed *= -1
                     }
+                    
+                    
+                    let slightly = this.keys.ALT.some(e => this.viewer.inputHandler.pressedKeys[e]); 
+                    slightly && (speed *= 0.1)
+                    
+                    
+                    
                     this.useAttenuation = true
                 }else{//触屏缩放
                     direction = this.viewer.inputHandler.getMouseDirection(e.pointer).direction  //定点缩放
@@ -755,7 +762,7 @@ export class FirstPersonControls extends THREE.EventDispatcher {
             
             this.lockElevation = this.lockElevationOri || this.keys.SPACE.some(e => ih.pressedKeys[e]);
             
-            
+            let slightly = this.keys.ALT.some(e => ih.pressedKeys[e]);
             
             if(!this.lockRotation){
                 if(rotateLeft){
@@ -787,9 +794,9 @@ export class FirstPersonControls extends THREE.EventDispatcher {
                     if (moveForward && moveBackward) {
                         this.translationDelta.y = 0;
                     } else if (moveForward) {
-                        this.translationDelta.y = this.currentViewport.getMoveSpeed();
+                        this.translationDelta.y = this.currentViewport.getMoveSpeed() * (slightly ? 0.1 : 1);
                     } else if (moveBackward) {
-                        this.translationDelta.y = -this.currentViewport.getMoveSpeed();
+                        this.translationDelta.y = -this.currentViewport.getMoveSpeed() * (slightly ? 0.1 : 1);
                     }
                 }
 

+ 5 - 5
src/utils/TransformationToolNew.js

@@ -158,9 +158,9 @@ export class TransformationTool extends THREE.EventDispatcher{
                 applyData: (data)=>{  
                     if(exist(data.object)){//viewer.scene.volumes.includes(data.box) //或许还要识别是否matrixAuto
                         data.matrix.decompose( data.object.position, data.object.quaternion, data.object.scale );
-                    }else{
-                        this.history.undo()//找不到就回退下一个。(直接写这?)
-                    }
+                        viewer.dispatchEvent('content_changed')
+                        return true
+                    } 
                 } ,
                 getData:(data)=>{ 
                     return data
@@ -176,13 +176,13 @@ export class TransformationTool extends THREE.EventDispatcher{
                 let object = viewer.transformationTool.selection[0]
                 object && this.history.afterChange({object, matrix:object.matrix.clone()} )
             })
-            viewer.inputHandler.addEventListener('keydown', (e)=>{
+            /* viewer.inputHandler.addEventListener('keydown', (e)=>{
                 if(e.keyCode == 90 && e.event.ctrlKey){//Z
                     this.history.undo()
                 }else if(e.keyCode == 89 && e.event.ctrlKey){//Y
                     this.history.redo()
                 }
-            })
+            }) */
         }
 	}