xzw 1 년 전
부모
커밋
81b282e700

+ 4 - 4
libs/three.js/build/three.module.js

@@ -31317,12 +31317,12 @@ class ExtrudeBufferGeometry extends BufferGeometry {
 
 			}
 
-			function sidewalls( contour, layeroffset ) {
+			function sidewalls( contour, layeroffset) {
 
 				let i = contour.length;
-
-				while ( -- i >= 0 ) {
-
+                let shapeDontClose = shape.dontClose    //xzw add不闭合
+				while ( -- i >= 0 ) {      
+                    if(shapeDontClose && i==0)break; //xzw add
 					const j = i;
 					let k = i - 1;
 					if ( k < 0 ) k = contour.length - 1;

+ 1 - 1
src/ExtendPointCloudOctree.js

@@ -574,7 +574,7 @@ export class ExtendPointCloudOctree extends PointCloudOctree{
                 if(value){
                     size = value
                 }else{
-                    
+                    if(this.maxLevel == Infinity)return
                     let base = this.material.spacing / Math.pow(2, this.maxLevel) //点云大小在level为0时设置为spacing,每长一级,大小就除以2.  (不同场景还是会有偏差)
                     let r = nodeMaxLevel > 0 ? this.maxLevel /  nodeMaxLevel : 0.5  //越大,越精细,需要越缩小
                     base *=  nodeMaxLevel > 0 ? Math.max(0.1, Math.pow(r, 3*r+0.3 )) : 0.1 //低质量的缩小点,因为视觉上看太大了。navvis是不铺满的,我们也留一点缝隙(但是ortho是不用缩小的,如果能分开判断就好了)

+ 2 - 2
src/PotreeRendererNew.js

@@ -1274,7 +1274,7 @@ export class Renderer {
                     `#define num_highlightBox ${num_highlightBox}`,   //改  
                     `#define num_clipspheres ${numClipSpheres}`, 
                      
-                    `#define num_prism ${material.prisms.length}`, //土方量数
+                    `#define num_prism ${material.prisms.pointsCount ? material.prisms.length : 0}`, //土方量数  如果num_prism>0,prismPointCountSum为0 会报错 :array size must be greater than zero
                     `#define prismPointCountSum ${material.prisms.pointsCount}`,//点总个数
                     `#define prism_maxPointsCount ${material.prisms.maxPointsCount}`, //单个prism最大点个数 (如果define也能传递个数数组,就不用再uniform里传了,呜 )      
                      
@@ -1364,7 +1364,7 @@ export class Renderer {
                         //renderTarget的texture在创建renderTarget时已经初始化过 见setupRenderTarget
                         continue
                     } */
-                    
+                     
 					if (!this.textures.has(texture) || texture.needsRebuild) {
 						let webglTexture = new WebGLTexture(gl, texture, this.threeRenderer);
 

+ 11 - 2
src/custom/mergeStartTest.js

@@ -71,7 +71,8 @@ var start = function(dom, mapDom, number, fileServer, webSite){ //t-Zvd3w0m
 
     Potree.loadDatasetsCallback = function(data, ifReload){ 
         if(!data || data.length == 0)return console.error('getDataSet加载的数据为空')
-           
+        if(data.length>1)console.log('该场景有多个数据集只取第一个')    
+        data = [data[0]] //只需要一个
         Potree.datasetData = data
         viewer.transform = null
         var datasetLength = data.length 
@@ -177,7 +178,15 @@ var start = function(dom, mapDom, number, fileServer, webSite){ //t-Zvd3w0m
         data.forEach((dataset,index)=>{  
             if(!ifReload){
                 var datasetCode = dataset.sceneCode || dataset.name //对应4dkk的场景码
-                var cloudPath = `${Potree.settings.urls.prefix1}/${Potree.settings.webSite}/${datasetCode}/data/${datasetCode}/webcloud/cloud.js` 
+                //var cloudPath = `${Potree.settings.urls.prefix1}/${Potree.settings.webSite}/${datasetCode}/data/${datasetCode}/webcloud/cloud.js` 
+                if(Potree.settings.isLocal && dataset.mapping){
+                    var cloudPath = `${Potree.settings.urls.prefix1}/${dataset.mapping}/${dataset.webBin}`  //webBin添加原因:每次裁剪之类的操作会换路径,因为oss文件缓存太严重,更新慢
+                }else{
+                    var cloudPath = `${Potree.settings.urls.prefix1}/${dataset.webBin}`  //webBin添加原因:每次裁剪之类的操作会换路径,因为oss文件缓存太严重,更新慢
+                }
+                
+                
+                
                 var timeStamp = dataset.createTime ? dataset.createTime.replace(/[^0-9]/ig,'') : '';  //每重算一次后缀随createTime更新一次 
                 //console.warn(dataset.name, 'timeStamp', timeStamp)
                 Potree.loadPointCloud(cloudPath, dataset.name ,datasetCode, timeStamp, e => {

+ 7 - 7
src/custom/modules/clipping/Clipping.js

@@ -335,10 +335,10 @@ export class Clipping extends THREE.EventDispatcher{ //实时剪裁
     
     
     
-    saveClipData(){//输出所有的clip volumeBox
+    saveClipData(boxes){//输出所有的clip volumeBox
         let oldState = !viewer.clipUnabled;
-        viewer.setClipState(true)
-        let data = this.getAllBoxes().filter(e=>!e.isNew).map(volume=>{
+        //viewer.setClipState(true)
+        let data = (boxes || this.getAllBoxes()).filter(e=>!e.isNew).map(volume=>{
             return {  
                 clipTask: volume.clipTask,
                 position: Potree.Utils.datasetPosTransform({position:volume.position, toDataset: true, datasetId: Potree.settings.originDatasetId}).toArray(),
@@ -346,9 +346,9 @@ export class Clipping extends THREE.EventDispatcher{ //实时剪裁
                 scale: volume.scale.toArray(),  
             }
         })
-        console.log(data)
-        console.log(JSON.stringify(data))
-        viewer.setClipState(oldState)
+        //console.log(data)
+        //console.log(JSON.stringify(data))
+        //viewer.setClipState(oldState)
         return data
     }
     
@@ -372,7 +372,7 @@ export class Clipping extends THREE.EventDispatcher{ //实时剪裁
 
 
 
-//注意:实时裁剪只对初始数据集有效
+//注意:实时裁剪只对初始数据集有效,其他数据集已经隐藏
 
 
 /* 

+ 56 - 15
src/custom/modules/volumeCompute/Prism.js

@@ -10,20 +10,19 @@ let areaPlaneMats = {
 } 
 
 
-console.log('prism 11111111111')
-
+ 
 export class Prism extends Measure{
     constructor(args){
         super(args)
         this.isPrism = true 
         this.volumeInfo = {}
         this.needsCompute = true
-        this.createPrismLines(new THREE.Color('#FFF') )
+        /*this.createPrismLines(new THREE.Color('#FFF') )
         this.lineMesh.material.transparent = true
-        this.lineMesh.material.opacity = 0.5 
-        Potree.Utils.setObjectLayers(this.lineMesh, 'measure' )  
-        
+        this.lineMesh.material.opacity = 0.5  
+        Potree.Utils.setObjectLayers(this.lineMesh, 'measure' ) */ 
         
+        this.setClipBox()
         this.setTopOrBtm('zMin')
         this.setTopOrBtm('zMax')
         this.setHorizonHeight('btm')
@@ -36,9 +35,9 @@ export class Prism extends Measure{
             this.getBound()
             this.dispatchEvent('updated')
         }
-        this.addEventListener('marker_moved',update)
+        this.addEventListener('marker_dropped'/* 'marker_moved' */,update)
         this.addEventListener('changeByHistory',update)
-            
+        this.addEventListener('changed',update)
        
         
         
@@ -50,13 +49,26 @@ export class Prism extends Measure{
         
         
         this.getBound()
-        
+        this.addEventListener('needsCompute',()=>{
+            this.needsCompute = true
+        },10)
         
         //Potree.Utils.setObjectLayers(this.lineMesh, 'bothMapAndScene' ) 
     }
     
     
-    
+    set needsCompute(state){
+        if(state == 'byVolume'){
+            this.needsCompute_ =  this.volumeInfo.Vupper == void 0
+        }else{
+            this.needsCompute_  = !!state
+            //console.error('needsCompute', state)
+        }
+        
+    }
+    get needsCompute(){
+        return this.needsCompute_
+    }
     
     setHorizonHeight(v){
         let old = this.horizonZ
@@ -85,6 +97,16 @@ export class Prism extends Measure{
         
     }
     
+    setBaseModel(model){
+        this.baseModel = model
+      
+        Potree.Utils.updateVisible(this.areaPlane,'useBaseModel',!model)
+    }
+    
+    setClipBox(boxes){//clipBoxes_out
+        this.clipBoxes = boxes || []
+    }
+    
    
     setTopOrBtm(name,v){
         if(v != void 0 ){
@@ -171,7 +193,7 @@ export class Prism extends Measure{
         return (new THREE.Matrix4).multiplyMatrices(invMatrix, pointcloud.transformMatrix).transpose()
     } 
 
-    
+   
     
     changeStyleForScreenshot(state, {hideLabel,showName}={}){//截图前变一下外观。根据高度变化颜色
     
@@ -203,13 +225,13 @@ export class Prism extends Measure{
         let name = color.getHexString() 
         
         if(state){
-             
+            Potree.Utils.updateVisible(this.areaPlane,'screenshot', true, 2, 'add') //强制显示
             
             let mat = areaPlaneMats[name] 
             if(!mat){
                 
                 mat = new THREE.MeshBasicMaterial({
-                    color, transparent:true, opacity:0.7,
+                    color, transparent:true, opacity:0.6,
                     side:THREE.DoubleSide, 
                 })
                 areaPlaneMats[name] = mat
@@ -234,7 +256,7 @@ export class Prism extends Measure{
             
             this.markers.forEach(marker=>Potree.Utils.updateVisible(marker,'screenshot-Prism',false))
             this.edges.forEach(edge=>Potree.Utils.updateVisible(edge,'screenshot-Prism',false)) 
-            Potree.Utils.updateVisible(this.lineMesh,'screenshot-Prism',false)
+            //Potree.Utils.updateVisible(this.lineMesh,'screenshot-Prism',false)
             
             
             this.styleRecover = ()=>{
@@ -250,7 +272,7 @@ export class Prism extends Measure{
                 }
                 this.markers.forEach(marker=>Potree.Utils.updateVisible(marker,'screenshot-Prism',true))
                 this.edges.forEach(edge=>Potree.Utils.updateVisible(edge,'screenshot-Prism',true))
-                Potree.Utils.updateVisible(this.lineMesh,'screenshot-Prism',true)
+                //Potree.Utils.updateVisible(this.lineMesh,'screenshot-Prism',true)
                 this.styleRecover = null
                 
                 
@@ -260,8 +282,25 @@ export class Prism extends Measure{
              
             this.styleRecover && this.styleRecover() 
             
+            Potree.Utils.updateVisible(this.areaPlane, 'screenshot', false, 2, 'cancel') 
         }
     }
+    
+    dispose(){
+        super.dispose()
+        this.clipBoxes.forEach(e=>viewer.scene.removeVolume(e))
+    }
+    
+    setEditState(state){//编辑页面or截图
+        state = !!state
+        this.editing = state
+        this.dontHighlight = !state 
+        this.clipBoxes.forEach(box=>{
+            Potree.Utils.updateVisible(box,'hidden',state),  box.clip = state
+        })  
+                    
+    }
+     
     /* {
             fill: [
                 {color: [236, 213, 143, 1], min: 0, max: 5},
@@ -279,4 +318,6 @@ export class Prism extends Measure{
             every: { color: [49, 200, 181, 1] }
     } */
     
+    
+     
 }

+ 170 - 124
src/custom/modules/volumeCompute/VolumeComputer.js

@@ -133,6 +133,9 @@ const notify = (areas, num, str )=>{ //num: 0-1
             str == 'loadpoints' && Potree.settings.isTest &&  console.log('notify pro', p, str)
             deferred.notify(p) 
             curPercent = p
+            if(isNaN(p)){
+                console.log('nan')
+            }
         }
         setTimeout(resolve, delayForNotify)
     }) 
@@ -170,7 +173,7 @@ export default class VolumeComputer extends THREE.EventDispatcher{
         
         this.material = new ExtendPointCloudMaterial();
      
-		this.material.activeAttributeName = "rgba"// testPoint ? "rgba" : 'heightCpt' ;// 'rgba' indices prismHeight
+		this.material.activeAttributeName = testPoint ? "rgba" : 'heightCpt' ;// 'rgba' indices prismHeight
          
         this.prisms = []
            
@@ -205,13 +208,18 @@ export default class VolumeComputer extends THREE.EventDispatcher{
         }) 
         
  
-        
+        let this_ = this
         this.events = {
-            transfromCallback:()=>{
-                let object = viewer.transformationTool.selection[0]
-                if(object == this.baseModel){
-                    this.updateModelBound()
-                }
+            transformCallback: ()=>{
+                if(!this_.currentPrism)return 
+                //Common.intervalTool.isWaiting('volCptTransformed', ()=>{ //延时update,防止卡顿  
+                    let object = viewer.transformationTool.selection[0] 
+                    if(object == this_.currentPrism.baseModel ){  
+                        this.updateModelBound({modelChange:true})  
+                    } 
+                    this_.currentPrism.dispatchEvent('needsCompute') //模型变动或clipBox变动后要重算 
+                //}, 1000)  
+                
             },  
         }
     }
@@ -225,16 +233,17 @@ export default class VolumeComputer extends THREE.EventDispatcher{
         Potree.settings.rotAroundPoint = false
          
         //viewer.objs.traverse(e=>e.material && ( e.material = this.material))
-        viewer.transformationTool.addEventListener('transformed', this.events.transfromCallback)
-        
+        viewer.transformationTool.addEventListener('stopDrag', this.events.transformCallback)
+        viewer.transformationTool.addEventListener('changeByHistory', this.events.transformCallback)
     }
     
     leave(){ 
         this.entered = false
         Potree.settings.rotAroundPoint = this.oldStates.rotAroundPoint
-        this.setCurrentPrismAndModel(null)
+        this.setCurrentPrism(null)
         
-        viewer.transformationTool.removeEventListener('transformed', this.events.transfromCallback) 
+        viewer.transformationTool.removeEventListener('stopDrag', this.events.transformCallback) 
+        viewer.transformationTool.removeEventListener('changeByHistory', this.events.transformCallback)
     }
     
     add(prism){
@@ -246,14 +255,14 @@ export default class VolumeComputer extends THREE.EventDispatcher{
         i>-1 && this.prisms.splice(i,1)
     }
     
-    
+    cancel(){
+        if(this.computingObject){
+            interrupt = true 
+        }
+    }
    
     startCompute(model,dontCompute){//test
         this.enter();
-        
-         
-        
-        
         let deferred = $.Deferred() 
         deferred.done((e)=>{
             console.log('done', e)
@@ -265,43 +274,38 @@ export default class VolumeComputer extends THREE.EventDispatcher{
             console.log('progress', e)
         })  */  
         if(model){
-            this.setCurrentPrismAndModel(this.prisms[this.prisms.length-1], model)
-            dontCompute || this.compute(this.prisms[this.prisms.length-1], model)  
+            this.prisms[this.prisms.length-1].setBaseModel(model)
+            this.setCurrentPrism(this.prisms[this.prisms.length-1])
+            dontCompute || this.compute(this.prisms[this.prisms.length-1])  
         }else{
             this.compute(this.prisms[this.prisms.length-1],  deferred )
-        }
-        
-        
+        } 
     }
     
-    cancel(){
-        if(this.computingObject){
-            interrupt = true 
-        }
-    }
+    
     
    
-    setCurrentPrismAndModel(prism, model){//当进入单个prism编辑后才会高亮点云
-        
-        
+    setCurrentPrism(prism ){//当进入单个prism编辑后才会高亮点云 
         if(this.currentPrism){
             this.currentPrism.removeEventListeners('updated')
-        }
-        
-        if(!model || !prism){  
-            return  //this.setModelMat(this.baseModel, 'recover')
-        }
-        
-        this.baseModel = model
-        this.currentPrism = prism
-        this.setModelMat(model )
+        } 
+        this.currentPrism = prism  //允许没有model
+        if(!prism || !prism.baseModel/*  || !prism.baseModel.visible */){   
+            viewer.scene.pointclouds.forEach(e=>{ 
+                this.updateMatForModel(e.material ) //取消高亮
+            }) 
+            return  
+        }  
         
         prism.addEventListener('updated',()=>{
+            if(this.currentPrism != prism){
+                return  console.log('currentPrism changed? 侦听没删除')
+            }
             this.updateModelBound()
         })
         
          
-        this.updateModelBound()
+        this.updateModelBound({regetMap:true})
         
     }
      
@@ -314,29 +318,45 @@ export default class VolumeComputer extends THREE.EventDispatcher{
     } 
      
      
-    updateModelBound(){
-        let model = this.baseModel
+    updateModelBound({modelChange, regetMap}={}){ //regetMap是在更换currentPrism必须重绘map,但不需要needUpdate
         let prism = this.currentPrism
+        let model = this.currentPrism.baseModel
+        
+        if(!model)return
         model.currentBound = model.boundingBox.clone().applyMatrix4(model.matrixWorld) //作用同prismBound
         let oldBound = model.clipBound && model.clipBound.clone()
        
         model.clipBound = model.currentBound.clone()//高亮范围 
-        model.clipBound.min.max(prism.prismBound.min)
+        model.clipBound.min.max(prism.prismBound.min)//xy为交集
         model.clipBound.max.min(prism.prismBound.max)
-        model.clipBound.min.z = Math.min(model.currentBound.min.z, prism.prismBound.min.z)
+        model.clipBound.min.z = Math.min(model.currentBound.min.z, prism.prismBound.min.z)//z为并集,范围覆盖prism点、点云、model三者 
         model.clipBound.max.z = Math.max(model.currentBound.max.z, prism.prismBound.max.z)
         this.modelMat.uniforms.boundZ.value.set(model.clipBound.min.z,model.clipBound.max.z)
       
-         
-        if(!oldBound || !oldBound.equals(model.clipBound)){
-            model.baseHeightAreaMap = this.getModelHeightMap()//包含cad在俯视中的范围 + 高度信息
-            //this.setModelMat(model,this.overBound ? 'recover' : null)
-            
-            viewer.scene.pointclouds.forEach(e=>{//暂时先只支持一个高亮区域
-                this.updateMatForModel(e.material, model) 
-            })
-            
+        let boundChanged = !oldBound || !oldBound.equals(model.clipBound)
+        
+        let boundSize = this.currentPrism.baseModel.clipBound.getSize(new THREE.Vector3)
+        this.boundSizeZero = boundSize.x<=0 ||boundSize.y<=0 || boundSize.z<=0  //会造成renderTarget尺寸为0,背景变白,报错:Framebuffer is incomplete: Attachment has zero size 和  The texture is a non-power-of-two texture.
+        
+        
+        if( (modelChange || regetMap || boundChanged) && !this.boundSizeZero){
+            this.setModelHeightMap()//包含cad在俯视中的范围 + 高度信息
+            //this.setModelMat(model,this.boundSizeZero ? 'recover' : null) 
         } 
+        viewer.scene.pointclouds.forEach(e=>{//暂时先只支持一个高亮区域
+            this.updateMatForModel(e.material, model) 
+        })
+        
+        //需要重新渲染modelHeightmap的情况:bound改变、模型变动、更换currentPrism后
+        //注意,即使上传几种都没发生,仅仅移动prism的marker也要重算,假设一个marker在model范围内,移动后bound可能不变但体积肯定变。
+        /* if(boundChanged){
+            if(prism.recoverNeedCptNextTime){
+                prism.needsCompute = 'byVolume'  //初始化,有volume就不用重算
+                prism.recoverNeedCptNextTime = false
+            }else{
+                prism.dispatchEvent('needsCompute')
+            } 
+        } */
         
     }
      
@@ -344,7 +364,7 @@ export default class VolumeComputer extends THREE.EventDispatcher{
     updateMatForModel(material, model){
         let oldMap = material.uniforms.baseHeightAreaMap.value 
         if(model){ 
-            material.uniforms.baseHeightAreaMap.value = model.baseHeightAreaMap ;
+            material.uniforms.baseHeightAreaMap.value = this.renderTarget2.texture    //model.baseHeightAreaMap ;
             material.uniforms.baseHeightBoundZ.value.set(model.clipBound.min.z,model.clipBound.max.z)
             material.uniforms.baseHeightBoundXY.value.set(model.clipBound.min.x, model.clipBound.max.x, model.clipBound.min.y, model.clipBound.max.y)
         }else{
@@ -359,23 +379,25 @@ export default class VolumeComputer extends THREE.EventDispatcher{
     
     
     
-    getModelHeightMap(){
-        let oldTarget = viewer.renderer.getRenderTarget()
-        let oldParent = this.baseModel.parent
-        
+    setModelHeightMap(){
          
-        
-        let boundSize = this.baseModel.clipBound.getSize(new THREE.Vector3)
-        if(boundSize.x<=0||boundSize.y<=0||boundSize.z<=0){
-            this.overBound = true 
-            return 
-        }
-        this.overBound = false
+        let oldTarget = viewer.renderer.getRenderTarget()
+        let oldParent = this.currentPrism.baseModel.parent
+        let oldVisi = this.currentPrism.baseModel.visible
         
         
-        let boundCenter = this.baseModel.clipBound.getCenter(new THREE.Vector3)
+        let boundSize = this.currentPrism.baseModel.clipBound.getSize(new THREE.Vector3)
+          
+        let boundCenter = this.currentPrism.baseModel.clipBound.getCenter(new THREE.Vector3)
         let {w, h} = this.getResByBound(boundSize,'forModel')
         
+        if(w<=0 || h<=0){
+            return console.error('w<=0 || h<=0!!!!!!!!!', w,h)
+        }
+         
+        /* w = THREE.Math.floorPowerOfTwo( w );
+        h = THREE.Math.floorPowerOfTwo( h ); */ //for warning:The texture is a non-power-of-two texture
+         
         this.camera.far = boundSize.z + 10 
         this.camera.right = w / 2
         this.camera.left = -this.camera.right
@@ -386,44 +408,49 @@ export default class VolumeComputer extends THREE.EventDispatcher{
         
         viewer.renderer.setRenderTarget(this.renderTarget2);
         
-        console.log('getModelHeightMap')
+        console.log('setModelHeightMap')
         
         //最高处朝下看
         
         let endPosition = new THREE.Vector3
         
-        endPosition.copy(boundCenter).setZ(this.baseModel.clipBound.max.z + this.camera.near+0.1)
+        endPosition.copy(boundCenter).setZ(this.currentPrism.baseModel.clipBound.max.z + this.camera.near+0.1)
         this.view.pitch = -Math.PI / 2; 
           
         this.view.moveOrthoCamera(this.viewport,  {boundSize , endPosition }, 0)
         this.view.applyToCamera(this.camera) 
-        this.scene.add(this.baseModel)
+        this.scene.add(this.currentPrism.baseModel)
+        this.setModelMat(this.currentPrism.baseModel)
+        this.currentPrism.baseModel.visible = true;
         
-        
-        let gl = viewer.renderer.getContext();  
-        gl.clearColor(0, 0, 0, 0);
-        viewer.renderer.clear(true, true, true);
+        let gl = viewer.renderer.getContext();   
+        viewer.renderer.setClearColor(new THREE.Color('#000'), 0);
+        viewer.renderer.clear()
         
         viewer.renderer.render(this.scene,this.camera)  
-        
+        this.setModelMat(this.currentPrism.baseModel, 'recover')
         
         
         let pixelCount = this.renderTarget2.width * this.renderTarget2.height
 		buffer2 = new Uint8Array(4 * pixelCount);
         
-        
+         
         //因为需要渲染完立即readPixels才能获取到,所以只能这时候就read了  
         gl.readPixels(0, 0, this.renderTarget2.width , this.renderTarget2.height, gl.RGBA, gl.UNSIGNED_BYTE, buffer2); //这句花费最多时间 pc:2-4, 即使只有1*1像素
-        modelZs = [] //等待计算
+        modelZs = [] //等待计算 
          
         if(window.needDownload) {
             let dataUrl = Potree.Utils.renderTargetToDataUrl(this.renderTarget2, this.renderTarget2.width, this.renderTarget2.height, viewer.renderer)
             Common.downloadFile(dataUrl, (name || 'screenshot') + '-' +   Date.now() +'.png')   
         }
-        oldParent.add(this.baseModel)
+        oldParent.add(this.currentPrism.baseModel)
+        
+        this.currentPrism.baseModel.visible = oldVisi
+         
         viewer.renderer.setRenderTarget(oldTarget);
         
-        this.renderTarget2.texture.needsRebuild = true //renderTarget在resize后会触发dispose, 然后 _gl.deleteTexture( textureProperties.__webglTexture )所以需要重新建立
+         
+        this.renderTarget2.texture.needsRebuild = true //renderTarget在resize后会触发dispose, 然后 _gl.deleteTexture( textureProperties.__webglTexture )所以需要重新建立 否则图片变黑
         return this.renderTarget2.texture
     }
     
@@ -433,8 +460,8 @@ export default class VolumeComputer extends THREE.EventDispatcher{
     
      
     getResByBound(boundSize, type){
-        let pxPerMetric = math.linearClamp(Math.max(boundSize.x,boundSize.y), [4, 10, 20, 80, 500, 2000], [300, 200, 100, 30, 6, 3])
-        
+        //let pxPerMetric = math.linearClamp(Math.max(boundSize.x,boundSize.y), [4, 10, 20, 80, 500, 2000], [300, 200, 100, 30, 6, 3])
+        let pxPerMetric = math.linearClamp(Math.max(boundSize.x,boundSize.y), [ 10,  60,  100, 500, 2000], [150, 60, 40, 6, 3])
         let w = pxPerMetric * boundSize.x, h = boundSize.y * pxPerMetric
         
         let cW = 1 , cH = 1   //横向纵向渲染次数  超过maxWidth时分批渲染
@@ -461,25 +488,39 @@ export default class VolumeComputer extends THREE.EventDispatcher{
     }
     
     //法1:只用一个顶部相机(当挖方遮挡填方时不准,但好算)
-    async compute(prism, model, deferred_, getResolveResult){
+    async compute(prism, deferred_, getResolveResult){
         if(!prism)return console.log('无prism?') 
         if(this.computingObject) return console.log('正在计算,请稍等')
              
+        let oldCurPrism = this.currentPrism
+        if(prism != this.currentPrism){//在列表外点击计算
+            this.setCurrentPrism(prism)
+        }
         
-        if(model && this.overBound){ 
+        let computeDone = ({highest,lowest,Vupper,Vlower}, deferred )=>{
             prism && prism.setVolumeInfo({
-                highest:0,lowest:0,Vupper:0,Vlower:0,   
+                highest,lowest,Vupper,Vlower   
             }) 
+             
+            if(oldCurPrism != prism){
+                this.setCurrentPrism(oldCurPrism)
+            }
+            
             deferred && deferred.resolve(getResolveResult && getResolveResult())
-        
-            return  
-        }
             
-        deferred = deferred_
-        timestamp = Date.now()
+        }
+         
+        if(prism.baseModel && this.boundSizeZero){ //bound没有交集 或 prism的boundsize为0
+            return  computeDone({highest:0,lowest:0,Vupper:0,Vlower:0}, deferred_ )
+        }
+         
+         
+         
+
         
-        this.computingObject = {prism, model} 
         
+        this.computingObject = {prism, model: prism.baseModel} 
+        deferred = deferred_  
          
         
         
@@ -505,22 +546,23 @@ export default class VolumeComputer extends THREE.EventDispatcher{
             viewer.mapViewer && (viewer.mapViewer.viewports[0].active = true )
             viewer.magnifier.viewport.active = true 
             viewer.pauseTestMaxLevel = false
-            console.log('pxPerMetric',pxPerMetric, 'boundSize',boundSize)
+            
         }
         
-        
-        let startTime = Date.now()
-        
-        let pointcloud = viewer.scene.pointclouds[0]
        
         
+        let pointcloud = viewer.scene.pointclouds[0] 
         let center = new THREE.Vector3
         let boundSize = new THREE.Vector3
-        let bound  
-        
-        
-        
-        if(!model){
+        let bound 
+        let gl = viewer.renderer.getContext();        
+        let statesBefore = {
+            mode: Potree.settings.displayMode,
+            pointDensity:Potree.settings.pointDensity
+        }
+        timestamp = Date.now() 
+         
+        if(!this.computingObject.model){
             horizonZ = prism.horizonZ
             zMin = prism.zMin
             zMax = prism.zMax
@@ -529,9 +571,9 @@ export default class VolumeComputer extends THREE.EventDispatcher{
                 bound.expandByPoint(prism.points[i])
             }
         }else{
-            zMin = model.clipBound.min.z
-            zMax = model.clipBound.max.z
-            bound = model.clipBound
+            zMin = this.computingObject.model.clipBound.min.z
+            zMax = this.computingObject.model.clipBound.max.z
+            bound = this.computingObject.model.clipBound
              
             //读取model的高度
             for (let u = 0; u < this.renderTarget2.width; u++) {
@@ -555,6 +597,12 @@ export default class VolumeComputer extends THREE.EventDispatcher{
         
         bound.getCenter(center)
         bound.getSize(boundSize) 
+        
+        this.boundSizeZero = boundSize.x<=0 ||boundSize.y<=0 || boundSize.z<=0 //prism的问题
+        if(this.boundSizeZero){
+            computeDone({highest:0,lowest:0,Vupper:0,Vlower:0}, deferred )
+            return computeFinish('finish', true)
+        }
         center.z = zMax + this.camera.near + 0.1
         this.camera.far = zMax - zMin + 10 
         
@@ -576,11 +624,7 @@ export default class VolumeComputer extends THREE.EventDispatcher{
         wDelta = boundSize.x / (w * cW )
         sDelta = Math.pow(wDelta,  2) 
         
-        //准备 
-        let statesBefore = {
-            mode: Potree.settings.displayMode,
-            pointDensity:Potree.settings.pointDensity
-        }
+        //准备  
         Potree.settings.displayMode = 'showPointCloud'
         Potree.settings.pointDensity = 'screenshot'
         viewer.mainViewport.active = false //暂停渲染,否则影响这边点云的加载
@@ -590,18 +634,21 @@ export default class VolumeComputer extends THREE.EventDispatcher{
         
         {//material
         
-            if(!model){  
+            if(!this.computingObject.model){  
                 //this.material.shape = Potree.PointShape.PARABOLOID;//加上之后depth出错,后排点云会挡前排,可pick时为什么不会?
                 
                 this.updateMatForModel(this.material, null) //计算时的shader这两种类型只能选一个,要么prism要么model,只能渲染一块区域
                 //this.material.opacity = 1;
             }else{ 
-                this.updateMatForModel(this.material, model) 
+                this.updateMatForModel(this.material, this.computingObject.model) 
                 //this.material.opacity = 0.9; //为了输出透明度,负数高度的alpha是0.5
                 
             }
-            this.material.setClipBoxes(null,[],[],[],[prism])
-            this.material.pointSizeType = 'ADAPTIVE' //node会自动根据的其level更改点大小
+            let clipBoxes_out = prism.clipBoxes.map(box=>{return {inverse:box.matrixWorld.clone().invert(),  box}} )
+            this.material.setClipBoxes(null,[], clipBoxes_out,[],[prism]) 
+           
+           
+            this.material.pointSizeType = 'FIXED'      //'ADAPTIVE' //node会自动根据的其level更改点大小 使用ADAPTIVE后会使baseModelMap整片是黑的,原因未知
             this.material.uniforms.minSize.value = 0.1
             this.material.uniforms.orthoMaxSize.value = 5; //px
              
@@ -610,7 +657,7 @@ export default class VolumeComputer extends THREE.EventDispatcher{
             this.material.shaderNeedsUpdate = true
             pointcloud.updateMaterial(this.material, null, this.camera, viewer.renderer, this.viewport.resolution);
              
-            this.material.size = this.getPointsize(pointcloud.maxLevel)   //0.025  米   //视图缩小(截图面积变大)后点会自动缩小,但至少是1个像素大小
+            this.material.size = 1//this.getPointsize(pointcloud.maxLevel)   //0.025  米   //视图缩小(截图面积变大)后点会自动缩小,但至少是1个像素大小
             
         }
         
@@ -618,7 +665,7 @@ export default class VolumeComputer extends THREE.EventDispatcher{
         
         
         
-        let gl = viewer.renderer.getContext();
+        
 	  
 		viewer.renderer.state.buffers.depth.setTest(this.material.depthTest);
 		viewer.renderer.state.buffers.depth.setMask(this.material.depthWrite);
@@ -659,7 +706,8 @@ export default class VolumeComputer extends THREE.EventDispatcher{
                 this.view.pitch = -Math.PI / 2; 
                 let endPosition = new THREE.Vector3(center.x + (i-cW/2+0.5) * boundSize_.x,  center.y + (j-cH/2+0.5) * boundSize_.y,  center.z)
                 this.view.moveOrthoCamera(this.viewport,  {boundSize: boundSize_, endPosition }, 0)
-                await this.render({i,j,index:1,cW,cH, infos,   /* maxLevels, */ notifyArea:[[progressStart, progressEnd],[0,0.4]], computeFinish })
+                let endPercent = this.computingObject.model ? 0.7 : 0.4
+                await this.render({i,j,index:1,cW,cH, infos,   /* maxLevels, */ notifyArea:[[progressStart, progressEnd],[0,endPercent]], computeFinish })
                  
                 
                 if(interrupt){
@@ -668,7 +716,7 @@ export default class VolumeComputer extends THREE.EventDispatcher{
                 
                   
                  
-                if(!model){ 
+                if(!this.computingObject.model){ 
                     //水平面朝下看,找填方
                     this.view.position.z = horizonZ + this.camera.near  
                     await this.render({i,j,index:2, cW,cH, infos,   /* maxLevels, */ notifyArea:[[progressStart, progressEnd], [0.4, 0.7]], computeFinish})   
@@ -895,20 +943,18 @@ export default class VolumeComputer extends THREE.EventDispatcher{
             Vupper += c.Vupper; Vlower += c.Vlower;
             fillVlower += c.fillVlower; fillVupper += c.fillVupper; 
         })
-        
-        prism && prism.setVolumeInfo({
-            highest,lowest,Vupper,Vlower, 
-        }) 
-        
-        let endTime = Date.now()
+      
+         
          
+        computeDone({
+            highest,lowest,Vupper,Vlower, 
+        }, deferred)
         
         
+        computeFinish('finish', true)
          
-        deferred && deferred.resolve(getResolveResult && getResolveResult())
         
-        computeFinish('finish', true)
-        console.log( {Vupper,Vlower,  oldVupper: Vupper - fillVupper, oldVlower:  Vlower - fillVlower, highest,lowest, horizonZ, wDelta}, results, this.viewport.resolution, {cW,cH}, 'cost:', endTime-startTime)//firefox用时是chrome两倍,edge和chrome差不多
+        console.log( {Vupper,Vlower,  oldVupper: Vupper - fillVupper, oldVlower:  Vlower - fillVlower, highest,lowest, horizonZ, wDelta}, results, this.viewport.resolution, {cW,cH}, 'cost:', Date.now()-timestamp, 'pxPerMetric', pxPerMetric, 'boundSize',boundSize )//firefox用时是chrome两倍,edge和chrome差不多
     }
    
     
@@ -1158,7 +1204,7 @@ export default class VolumeComputer extends THREE.EventDispatcher{
     
     getPointsize(maxLevel){//尽量铺满  size单位是米,需要和点云缝隙同宽
     
-        return 0.2
+        return 0.01       /* adaptive:0.2 */
          
         
         

+ 23 - 12
src/custom/objects/tool/Measure.js

@@ -620,12 +620,15 @@ export class Measure extends ctrlPolygon{
         marker.addEventListener('click',()=>{
             
             if(viewer.measuringTool.editMode == 'delPoint' ){
-                if(this.points.length == this.minMarkers){
+                /* if(this.points.length == this.minMarkers){//--前端去重绘
                     viewer.scene.removeMeasurement(this)
-                }else{
+                }else{ */
+                    viewer.measuringTool.history.beforeChange(this)
                     let index = this.markers.indexOf(marker)
                     this.removeMarker(index)
-                }
+                    viewer.measuringTool.history.afterChange(this)
+                    this.dispatchEvent('changed')
+                //}
                 
             }
         })
@@ -660,6 +663,7 @@ export class Measure extends ctrlPolygon{
                     
                     
                     if(viewer.measuringTool.editMode == 'addPoint' && this.points.length < this.maxMarkers){ 
+                        viewer.measuringTool.history.beforeChange(this)
                         let index = this.edges.indexOf(edge) + 1
                         let nextIndex = index % this.edges.length
                         let point = math.getFootPoint(e.hoveredElement.point, this.points[index-1], this.points[nextIndex] );
@@ -668,9 +672,11 @@ export class Measure extends ctrlPolygon{
                             index, 
                             point,
                             dataset_point: this.dataset_points && new THREE.Vector3 , //初始化
-                            points_dataset : this.points_datasets[index] //使用前一个的
+                            points_dataset : this.points_datasets[index-1] //使用前一个的
                         })  
                         this.updateDatasetBelong(index) //获取dataset_point
+                        viewer.measuringTool.history.afterChange(this)
+                        this.dispatchEvent('changed')
                         //this.update({})       
                     }else{ 
                         this.isNew || viewer.measuringTool.isAdding || viewer.focusOnObject(this, 'measure') //正在添加测量线时不要focus其他线(容易误触)
@@ -803,14 +809,18 @@ export class Measure extends ctrlPolygon{
     
     setSelected(state, hoverObject){//add
         //console.log('setSelected',state, hoverObject)
-        hoverObject && (this.selectStates[hoverObject] = state)
-        let absoluteState = false
-        for(var i in this.selectStates){
-            if(this.selectStates[i]){
-                absoluteState = true; break;
-            }
-        }
+       
+        let absoluteState = !!state 
         
+        if(hoverObject){//如果没有hoverObject且state为false 就强制取消选中态
+            this.selectStates[hoverObject] = state
+            for(var i in this.selectStates){
+                if(this.selectStates[i]){
+                    absoluteState = true; break;
+                }
+            }
+        } 
+         
         
         if(absoluteState){
             this.markers.forEach(e=>this.setMarkerSelected(e, 'hover', 'selectAll' ) )
@@ -886,6 +896,7 @@ export class Measure extends ctrlPolygon{
         this.areaLabel && labels.push(this.areaLabel)
         labels.forEach(e=>e.dispose())
         super.dispose()
+        this.dispatchEvent('disposed')
     }
     
      
@@ -948,7 +959,7 @@ export class Measure extends ctrlPolygon{
                 return total.add(currentValue)
             }, new THREE.Vector3 ) 
             
-            center.multiplyScalar(1/this.points.length)
+            this.points.length && center.multiplyScalar(1/this.points.length)
             return center //求不出重心呜呜
         } 
         

+ 2 - 2
src/custom/objects/tool/ctrlPolygon.js

@@ -753,14 +753,14 @@ export class ctrlPolygon extends THREE.Object3D {
         //console.log('update-time', measure.duration)
         
     } 
-    
+     
     
     
     createPrismLines(color){
         this.lineMesh = LineDraw.createLine([],{color})
         this.lineMesh.name = 'PrismLines' 
         this.add(this.lineMesh)  
-    }
+    }  
     
     updatePrismLines(){
         if(!this.lineMesh)return

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

@@ -315,7 +315,7 @@ Utils.getMousePointCloudIntersection = function(viewport, mouse, pointer, camera
     if(!pickParams.pickClipped){// 无视clipBoxes
         for(let pointcloud of pointclouds){  
             old_clipBoxes_in.set(pointcloud, pointcloud.clipBoxes_in)
-            old_clipBoxes_out.set(pointcloud, pointcloud.clipBoxes_in)
+            old_clipBoxes_out.set(pointcloud, pointcloud.clipBoxes_out)
             old_bigClipInBox.set(pointcloud, pointcloud.bigClipInBox)
             old_highlightBoxes.set(pointcloud, pointcloud.highlightBoxes)
             pointcloud.material.setClipBoxes(null, [],[],[])  
@@ -2089,7 +2089,7 @@ VolumeTool.prototype.startInsertion = function(args = {}){
     
     
     let drag = e => {
-        
+        if(e.hoverViewport.name == 'mapViewport')return
         let I = Utils.getMousePointCloudIntersection(
             viewer.mainViewport,
             viewer.inputHandler.mouse,

+ 79 - 42
src/custom/utils/DrawUtil.js

@@ -224,18 +224,55 @@ var LineDraw = {
 }
 
 var MeshDraw = { 
-    getShape:function(points, holes){
+
+    getShape: function(shapes, holes){  
+        //不一定闭合 暂时所有shapes共享holes。如果要单独的话, shapes改为[{shape:[],holes:[]},{}]的形式
+        if(shapes[0] && !(shapes[0] instanceof Array) ){//仅是一个shape的点
+            shapes = [shapes]
+        }
+        
+        let holesArr = []
+        if(holes){//挖空
+            holes.forEach((points)=>{
+                var holePath = new THREE.Path()
+                holePath.moveTo( points[0].x, points[0].y )
+                for(var i=1,len=points.length; i<len; i++){
+                    holePath.lineTo(points[i].x, points[i].y ) 
+                } 
+                holesArr.push( holePath );
+            })  
+        }
+        
+        let shapesArr = shapes.map(points=>{
+            var shape = new THREE.Shape();
+            shape.moveTo( points[0].x, points[0].y );
+            for(var i=1,len=points.length; i<len; i++){
+                shape.lineTo(points[i].x, points[i].y ) 
+            }
+            shape.holes.push(...holesArr)
+            shape.dontClose = points.dontClose //add 有的shape不需要闭合
+            return shape
+        })
+         
+        
+        return shapesArr        
+    },  
+
+
+    /* getShape:function(shapes, holes){
         var shape = new THREE.Shape();
-        shape.moveTo( points[0].x, points[0].y );
-        for(var i=1,len=points.length; i<len; i++){
-            shape.lineTo(points[i].x, points[i].y ) 
-        } 
         
-        /* var holePath = new THREE.Path()
-                .moveTo( 20, 10 )
-                .absarc( 10, 10, 10, 0, Math.PI * 2, true ) 
-            arcShape.holes.push( holePath );
-         */
+        if(shapes[0] && !(shapes[0] instanceof Array) ){//仅是一个shape的点
+            shapes = [shapes]
+        }
+        shapes.forEach((points)=>{
+            shape.moveTo( points[0].x, points[0].y );
+            for(var i=1,len=points.length; i<len; i++){
+                shape.lineTo(points[i].x, points[i].y ) 
+            } 
+        })
+        //多个points的数组绘制在一个shape中,缺点是这些数组之间可能绘制出来会连在一起。
+         
         if(holes){//挖空
             holes.forEach((points)=>{
                 var holePath = new THREE.Path()
@@ -247,11 +284,11 @@ var MeshDraw = {
             }) 
         }
         return shape        
-    },
-    getShapeGeo: function(points, holes){//获取任意形状(多边形或弧形)的形状面  //quadraticCurveTo() 这是弧形的含函数
+    },  */
+    getShapeGeo: function(shapes, holes){//获取任意形状(多边形或弧形)的形状面  //quadraticCurveTo() 这是弧形的含函数
 		
-		var geometry = new THREE.ShapeBufferGeometry( this.getShape(points, holes) );  //ShapeGeometry
-        
+		var geometry = new THREE.ShapeBufferGeometry( this.getShape(shapes, holes) );  //ShapeGeometry
+         
        /*  var matrix = new THREE.Matrix4();//将竖直的面变为水平
 		matrix.set(//z = y 
 			1, 0, 0, 0,
@@ -267,9 +304,9 @@ var MeshDraw = {
 		
 	},
     
-    
-    getExtrudeGeo:  function(points, holes, options={}){//获得挤出棱柱,可以选择传递height,或者extrudePath
-        var shape = this.getShape(points, holes) //points是横截面 [vector2,...]
+     
+    getExtrudeGeo:  function(shapes, holes, options={openEnded:false, shapeDontClose:false}){//获得挤出棱柱,可以选择传递height,或者extrudePath
+        var shape = this.getShape(shapes, holes) //points是横截面 [vector2,...]
         
         if(options.extrudePath ){// 路径 :[vector3,...]
              
@@ -282,7 +319,30 @@ var MeshDraw = {
                 options.tension = 0 ;//否则一端扭曲
                 options.steps = 1
             }
-            
+              
+            {//去掉重复的点 
+                let path = []
+                const minDis = options.dontSmooth ? 0 : 0.2 //CatmullRomCurve3 经常扭曲,如果两个点靠得很近可能会扭曲,这里去除靠的太近的点。但去除后依旧会出现一定扭曲.   
+                options.extrudePath.forEach((p,i)=>{
+                    if(i==0 || i== options.extrudePath.length-1)return path.push(p) //首尾直接加入
+                    let last = path[path.length-1]//和上一个比
+                    let dis = last.distanceTo(p)
+                    if(dis <= minDis){
+                        console.log(`第${i}个点(${p.toArray()})因为和上一个数据(${last.toArray()})太接近(dis:${dis})所以删除`)
+                    }else if(i == options.extrudePath.length - 2){//因为最后一个必定加入,所以倒数第二个还也不能太靠近最后一个
+                        last = options.extrudePath[options.extrudePath.length-1] //和下一个(最后一个比)
+                        if(dis <= minDis){
+                            console.log(`第${i}个点(${p.toArray()})因为和下一个数据(${last.toArray()})太接近(dis:${dis})所以删除`)
+                        }else{
+                            path.push(p)
+                        }
+                    }else{
+                        path.push(p)
+                    }
+                    
+                }) 
+                options.extrudePath = path               
+            }
             if(options.dontSmooth){
                 let curvePath = new THREE.CurvePath()//通用的曲线路径对象,它可以包含直线段和曲线段。在这里只做折线
                 for (let i = 0; i < options.extrudePath.length - 1; i++){ 
@@ -290,30 +350,7 @@ var MeshDraw = {
                     curvePath.add(curve3);
                 } 
                 options.extrudePath = curvePath
-            }else{
-                
-                /* CatmullRomCurve3 经常扭曲,如果两个点靠得很近可能会扭曲,这里去除靠的太近的点。但去除后依旧会出现一定扭曲
-                let vertices =  pathModel.children[0].geometry.vertices.slice(10,80)
-                let extrudePath = []
-                const minDis = 1
-                vertices.forEach((p,i)=>{
-                    if(i==0 || i== vertices.length-1)return extrudePath.push(p) //首尾直接加入
-                    let last = extrudePath[extrudePath.length-1]
-                    let dis = last.distanceTo(p)
-                    if(dis < minDis){
-                        console.log(`第${i}个点(${p.toArray()})因为和上一个数据(${last.toArray()})距离太短(${dis})所以删除`)
-                    }else if(i == vertices.length - 2){//因为最后一个必定加入,所以倒数第二个还也不能太靠近最后一个
-                        last = extrudePath[vertices.length-1]
-                        if(dis < minDis){
-                            console.log(`第${i}个点(${p.toArray()})因为和下一个数据(${last.toArray()})距离太短(${dis})所以删除`)
-                        }else{
-                            extrudePath.push(p)
-                        }
-                    }else{
-                        extrudePath.push(p)
-                    }
-                    
-                }) */
+            }else{ 
                 //平滑连续的曲线(但经常会有扭曲的问题,tension:0能缓解, 另外shape和path都最好在原点附近,也就是点需减去bound.min )
                 options.extrudePath = new THREE.CatmullRomCurve3(options.extrudePath, options.closed ,  'catmullrom'  /* 'centripetal' */  , options.tension)//tension:拐弯剧烈程度,但随着长度增长,该值需要减小,否则会扭曲
                                      

+ 38 - 23
src/custom/viewer/ViewerNew.js

@@ -2822,7 +2822,7 @@ export class Viewer extends ViewerBase{
 			}
 			
 			// Needed for .getInverse(), pre-empt a determinant of 0, see #815 / #816
-			let degenerate = (box) => box.matrixWorld.determinant() !== 0;
+			let degenerate = (box) => box.matrixWorld.determinant() !== 0 && box.clip;
 			
 			let clipBoxes = boxes.filter(degenerate).map( box => {
 				box.updateMatrixWorld();
@@ -2838,15 +2838,11 @@ export class Viewer extends ViewerBase{
             let clipBoxes_out = clipBoxes.filter(e=>e.box.clipTask == ClipTask.SHOW_OUTSIDE && !e.box.highlight)
             let highlightBoxes = clipBoxes.filter(e=>e.box.highlight )
 			//let prismPolygons = this.modules.volumeComputer && this.modules.volumeComputer.entered ? viewer.scene.measurements.filter(e=>(e.measureType == 'MulDistance Ring') && !e.isNew) : []
-			let prismPolygons = this.modules.volumeComputer ? this.modules.volumeComputer.prisms.filter(e=>!e.isNew && e.visible) : []
+			let prismPolygons = this.modules.volumeComputer ? this.modules.volumeComputer.prisms.filter(e=>!e.isNew && e.visible && !e.dontHighlight) : []
             
             // set clip volumes in material
 			for(let pointcloud of visiblePointClouds){
-                let clipBoxes_in2 = [], clipBoxes_out2 = [], highlightBoxes2 = []
-                if(pointcloud.dataset_id == Potree.settings.originDatasetId){ //实时裁剪只对初始数据集有效
-                    clipBoxes_in2 = clipBoxes_in,  clipBoxes_out2 = clipBoxes_out, highlightBoxes2 = highlightBoxes
-                }
-				pointcloud.material.setClipBoxes(bigClipInBox, clipBoxes_in2, clipBoxes_out2, highlightBoxes2, prismPolygons);  
+				pointcloud.material.setClipBoxes(bigClipInBox, clipBoxes_in, clipBoxes_out, highlightBoxes, prismPolygons);  
 			}
 		}  
 
@@ -3144,7 +3140,7 @@ export class Viewer extends ViewerBase{
 
 	}
 
-    clear(params={}){
+    clear(params={}){ 
         let background = params.background || this.background;
         let backgroundOpacity = params.backgroundOpacity == void 0 ? this.backgroundOpacity : params.backgroundOpacity//如果想完全透明,只需要backgroundOpacity为0
 		let renderer = this.renderer
@@ -3752,7 +3748,7 @@ export class Viewer extends ViewerBase{
                 this.backgroundOpacity = oldStates.bgOpacity;
                 this.background = oldStates.background;
                 this.pauseTestMaxLevel = false
-                
+                oldStates.displayMode && (Potree.settings.displayMode = oldStates.displayMode)
                 
                 if(info.type == 'measure' || info.type.includes('prism2d')){
                     this.modules.SiteModel.pauseUpdateEntity = false
@@ -3766,6 +3762,10 @@ export class Viewer extends ViewerBase{
                      
                     (info.prisms || [info.prism]).forEach(prism=>{
                         prism.changeStyleForScreenshot(false)
+                        if(info.type == 'prism2d-single'){ 
+                            prism.baseModel && (Potree.Utils.updateVisible(prism.baseModel, 'screenshot', false, 3, 'cancel'), Potree.Utils.setObjectLayers(prism.baseModel, 'model'))
+                            prism.setEditState(false)
+                        }
                     })  
                 }
                
@@ -3846,7 +3846,7 @@ export class Viewer extends ViewerBase{
             oldStates.viewports.push(mapViewport.clone())  
             oldStates.attachedToViewer = this.mapViewer.attachedToViewer
             oldStates.noPointcloud = mapViewport.noPointcloud
-             
+            oldStates.displayMode = Potree.settings.displayMode
              
             Potree.Utils.updateVisible(this.mapViewer.cursor, 'screenshot', false)//令mapCursor不可见
         }
@@ -3957,10 +3957,14 @@ export class Viewer extends ViewerBase{
             
             viewer.updateScreenSize({forceUpdateSize:true, width, height, forTarget:info.useRenderTarget}) //更新viewports相机透视 使focusOnObject在此窗口大小下
              
-            prisms.forEach(prism=>{
+            prisms.forEach(prism=>{ 
                 points.push(...prism.points) 
+                prism.setSelected(false)
                 prism.changeStyleForScreenshot(true, {hideLabel: info.type != 'prism2d-all',  showName: info.type == 'prism2d-all' })
-                   
+                if(info.type == 'prism2d-single') {
+                    prism.baseModel && (Potree.Utils.updateVisible(prism.baseModel, 'screenshot', true, 3, 'add'),  Potree.Utils.setObjectLayers(prism.baseModel, 'bothMapAndScene'))
+                    prism.setEditState(true) 
+                } 
             }) 
             this.scene.measurements.forEach(e=>Potree.Utils.updateVisible(e,'screenshot', prisms.includes(e))  )
             
@@ -3977,13 +3981,12 @@ export class Viewer extends ViewerBase{
                     this.mapViewer.waitLoadDone(screenshot.bind(this))//等待地图所有加载完
                 
                 }else{//single
-                    mapViewport.noPointcloud = false
+                    mapViewport.noPointcloud = false //显示点云,而非平面图
+                    Potree.settings.displayMode = 'showPointCloud'
                     Potree.Utils.updateVisible(viewer.mapViewer.mapLayer.sceneGroup, 'screenshot-prism', false)
                     
-                    this.waitPointLoad( screenshot)
-                }    
-             
-                 
+                    this.waitPointLoad(screenshot, 5000)
+                }   
             })
          
              
@@ -4257,6 +4260,10 @@ export class Viewer extends ViewerBase{
             return {promise: deferred.promise() }   
         }
         if (type == 'measure') {  
+            if(object.points.length == 0){ 
+                return {promise:deferred.resolve()}
+            }
+        
             target.copy(object.getCenter()) 
         
             //试试改变位置(方向),直视测量线。能避免倾斜角度造成的非常不居中、以及看不到面的情况 
@@ -5257,7 +5264,7 @@ export class Viewer extends ViewerBase{
                     } 
                     if(child.material instanceof THREE.MeshStandardMaterial){
                         child.material.roughness = 0.7
-                        child.material.metalness = 0.3 
+                        child.material.metalness = 0.5 
                     }
                 } 
             } );
@@ -5349,12 +5356,12 @@ export class Viewer extends ViewerBase{
             
                     loaders.objLoader.setMaterials( materials ).load(fileInfo.objurl, (object, total)=>{  
                         loadDone(object/* , total, fileInfo.objurl */)
-                    })
+                    }, onProgress,  onError )
                 } , onProgress,  onError  );  
             }else{
                 loaders.objLoader.load(fileInfo.objurl, (object, total)=>{  
                     loadDone(object)
-                })
+                }, onProgress,  onError)
             }
         }else if(fileInfo.fileType == 'glb'){
             loaders.glbLoader.unlitMat = true//!!fileInfo.unlit
@@ -5431,14 +5438,22 @@ export class Viewer extends ViewerBase{
         }else if(fileInfo.fileType == 'dxf'){
             loaders.dxfLoader.load(fileInfo.url,(object)=>{
                 loadDone(object)
-            }) 
+            },fileInfo) 
         }
         
          
     }
     
-    removeObj(object){
-        this.objs.remove(object);
+    removeModel(model){
+        this.objs.remove(model);
+        let dispose = (e)=>{
+            e.geometry && e.geometry.dispose() 
+            e.material && e.material.dispose()
+        } 
+        model.traverse(e=>{
+            dispose(e) 
+        })
+           
         if(Potree.settings.boundAddObjs){
             this.updateModelBound() 
         }

+ 124 - 88
src/loader/DxfLoader.js

@@ -18,13 +18,13 @@ export default class DxfLoader extends THREE.EventDispatcher{
     }
     
     
-    load(url,done){
+    load(url,done, options={}){
         Potree.loadFile(url, {returnText:true} , (data)=>{
              
             var dxfJson = this.parser.parseSync(data);
             
             console.log(dxfJson)
-            let model = this.createModel(dxfJson)
+            let model = this.createModel(dxfJson, options)
             
             done(model)
         })
@@ -32,7 +32,7 @@ export default class DxfLoader extends THREE.EventDispatcher{
     
     
     
-    createModel(data){
+    createModel(data, options={}){
         let root = new THREE.Object3D;
 
         
@@ -46,9 +46,9 @@ export default class DxfLoader extends THREE.EventDispatcher{
         
         for(i = 0; i < data.entities.length; i++) {
             entity = data.entities[i];
-            obj = this.drawEntity(entity, data);
- 
-            if (obj) {
+            obj = drawEntity(entity, data, options.unsupportTypes );
+             
+            if (obj) {  
                 var bbox = new THREE.Box3().setFromObject(obj);
                 /* if (bbox.min.x && ((dims.min.x === false) || (dims.min.x > bbox.min.x))) dims.min.x = bbox.min.x;
                 if (bbox.min.y && ((dims.min.y === false) || (dims.min.y > bbox.min.y))) dims.min.y = bbox.min.y;
@@ -63,66 +63,62 @@ export default class DxfLoader extends THREE.EventDispatcher{
         return root
      
     }
+     
     
-    
-    drawEntity(entity, data) {
-        var mesh;
-        if(entity.type === 'CIRCLE' || entity.type === 'ARC') {
-            mesh = drawArc(entity, data);
-        } else if(entity.type === 'LWPOLYLINE' || entity.type === 'LINE' || entity.type === 'POLYLINE') {
-            mesh = drawLine(entity, data);
-        } else if(entity.type === 'TEXT') {
-            mesh = drawText(entity, data);
-        } else if(entity.type === 'SOLID') {
-            mesh = drawSolid(entity, data);
-        } else if(entity.type === 'POINT') {
-            mesh = drawPoint(entity, data);
-        } else if(entity.type === 'INSERT') {
-            mesh = drawBlock(entity, data);
-        }  else if(entity.type === 'SPLINE') {
-            mesh = drawSpline(entity, data);
-        } else if(entity.type === 'MTEXT') {
-            mesh = drawMtext(entity, data);
-        } else if(entity.type === 'ELLIPSE') {
-            mesh = drawEllipse(entity, data);
-        } else if(entity.type === 'DIMENSION') {
-            var dimTypeEnum = entity.dimensionType & 7;
-            if(dimTypeEnum === 0) {
-                mesh = drawDimension(entity, data);
-            } else {
-                console.log("Unsupported Dimension type: " + dimTypeEnum);
-            }
+}
+
+function drawEntity(entity, data, unsupportTypes, group) {
+    var mesh;
+    if(unsupportTypes && unsupportTypes.includes(entity.type)){
+        console.warn('遇到一个dxf不会绘制的type:', entity.type)
+        return  //add 不绘制该项
+    } 
+    if(entity.type === 'CIRCLE' || entity.type === 'ARC') {
+        mesh = drawArc(entity, data, unsupportTypes, group );
+    } else if(entity.type === 'LWPOLYLINE' || entity.type === 'LINE' || entity.type === 'POLYLINE') {
+        mesh = drawLine(entity, data, unsupportTypes, group );
+    } else if(entity.type === 'TEXT') {//"MTEXT"  text: "{\fKaiTi|b0|i0|c134|p49;糕点制作台}"
+        mesh = drawText(entity, data, unsupportTypes, group);
+    } else if(entity.type === 'SOLID') {
+        mesh = drawSolid(entity, data);
+    } else if(entity.type === 'POINT') {
+        mesh = drawPoint(entity, data );
+    } else if(entity.type === 'INSERT') {//嵌套其他group
+        mesh = drawBlock(entity, data,  unsupportTypes, group );
+    }  else if(entity.type === 'SPLINE') {
+        mesh = drawSpline(entity, data);
+    } else if(entity.type === 'MTEXT') {
+        mesh = drawMtext(entity, data, unsupportTypes, group );
+    } else if(entity.type === 'ELLIPSE') {
+        mesh = drawEllipse(entity, data, unsupportTypes, group );
+    } else if(entity.type === 'DIMENSION') {
+        var dimTypeEnum = entity.dimensionType & 7;
+        if(dimTypeEnum === 0) {
+            mesh = drawDimension(entity, data);
+        } else {
+            console.log("Unsupported Dimension type: " + dimTypeEnum);
         }
-        else {
-            console.log("Unsupported Entity Type: " + entity.type);
-        }   
-         
-        if(entity.type === 'LWPOLYLINE' || entity.type === 'LINE' || entity.type === 'POLYLINE') {
-            mesh = drawLine(entity, data);
-        } 
-        
-        /* if(entity.type === 'INSERT') {
-            mesh = drawBlock(entity, data);     //group
-        }  */
-        /* 
-        
-            门都是arc
-            似乎墙壁都是不是insert类型,但窗户是
-         */
-        return mesh;
     }
+    else {
+        console.log("Unsupported Entity Type: " + entity.type);
+    }   
+     
+    if(entity.type === 'LWPOLYLINE' || entity.type === 'LINE' || entity.type === 'POLYLINE') {
+        mesh = drawLine(entity, data);
+    } 
     
+    /* if(entity.type === 'INSERT') {
+        mesh = drawBlock(entity, data);     //group
+    }  */
+    /* 
     
-    
-    
-    
-    
-    
-    
+        门都是arc
+        似乎墙壁都是不是insert类型,但窗户是
+     */
+    mesh && (mesh.dxfInfo = entity) //add
+    return mesh;
 }
 
-
-
 function drawEllipse(entity, data) {
         var color = getColor(entity, data);
 
@@ -150,10 +146,10 @@ function drawEllipse(entity, data) {
     function drawMtext(entity, data) {
         var color = getColor(entity, data);
 
-        if (!font) { return console.log('font parameter not set. Ignoring text entity.')}
+        //if (!font) { return console.log('font parameter not set. Ignoring text entity.')}
 
         var geometry = new THREE.TextGeometry( entity.text, {
-            font: font,
+            //font: font,
             size: entity.height * (4/5),
             height: 1
         });
@@ -384,11 +380,11 @@ function drawEllipse(entity, data) {
 
     function drawText(entity, data) {
         var geometry, material, text;
-
-        if(!font)
+        //必须要font才能画出文字
+        /* if(!font)
             return console.warn('Text is not supported without a Three.js font loaded with THREE.FontLoader! Load a font of your choice and pass this into the constructor. See the sample for this repository or Three.js examples at http://threejs.org/examples/?q=text#webgl_geometry_text for more details.');
-        
-        geometry = new THREE.TextGeometry(entity.text, { font: font, height: 0, size: entity.textHeight || 12 });
+         */
+        geometry = new THREE.TextGeometry(entity.text, {/*  font: font, */ height: 0, size: entity.textHeight || 12 });
 
         if (entity.rotation) {
             var zRotation = entity.rotation * Math.PI / 180;
@@ -427,11 +423,16 @@ function drawEllipse(entity, data) {
 
         material = new THREE.PointsMaterial( { size: 0.05, vertexColors: THREE.VertexColors } );
         point = new THREE.Points(geometry, material);
-        scene.add(point);
+        //scene.add(point);
+        return point
     }
 
-    function drawDimension(entity, data) {
-        var block = data.blocks[entity.block];
+    function drawDimension(entity, data, unsupportTypes, parentGroup) {
+        
+        return drawBlock(entity, data, unsupportTypes, parentGroup, true)
+        //改
+        
+        /* var block = data.blocks[entity.block];
 
         if (!block || !block.entities) return null;
 
@@ -441,40 +442,75 @@ function drawEllipse(entity, data) {
         //     group.position.y = entity.anchorPoint.y;
         //     group.position.z = entity.anchorPoint.z;
         // }
-
+        
         for(var i = 0; i < block.entities.length; i++) {
             var childEntity = drawEntity(block.entities[i], data, group);
-            if(childEntity) group.add(childEntity);
+            if(childEntity && !group.children.includes(childEntity)) group.add(childEntity);
         }
 
-        return group;
+        return group; */
     }
 
-    function drawBlock(entity, data) {
+    function drawBlock(entity, data, unsupportTypes, parentGroup, isDimension) {
         var block = data.blocks[entity.name];
         
         if (!block.entities) return null;
 
         var group = new THREE.Object3D()
+        parentGroup && parentGroup.add(group)//提前添加  为了获得matrixWorld
         
-        if(entity.xScale) group.scale.x = entity.xScale;
-        if(entity.yScale) group.scale.y = entity.yScale;
-
-        if(entity.rotation) {
-            group.rotation.z = entity.rotation * Math.PI / 180;
-        }
-
-        if(entity.position) {
-            group.position.x = entity.position.x;
-            group.position.y = entity.position.y;
-            group.position.z = entity.position.z;
-        }
         
-        for(var i = 0; i < block.entities.length; i++) {
-            var childEntity = drawEntity(block.entities[i], data, group);
-            if(childEntity) group.add(childEntity);
+        if(!isDimension){
+            if(entity.position) {
+                group.position.x = entity.position.x;
+                group.position.y = entity.position.y;
+                group.position.z = entity.position.z;
+            }
+            
+            
+            
+            if(entity.xScale){ 
+                group.scale.x = entity.xScale;  
+            }
+            if(entity.yScale){
+                group.scale.y = entity.yScale; 
+            }
+            if(entity.rotation) {
+                group.rotation.z = entity.rotation * Math.PI / 180;
+            }
+            
+            //add:  经常看到有的会脱离主区域很远 add zScale
+            var flag;
+            if(entity.zScale != void 0 && entity.extrusionDirection){//see (005.dxf、 others/01.dxf)   extrusionDirection ={x:0,y:0,z:-1} 
+                group.position.x *= Math.sign(entity.zScale)
+                group.scale.x *= Math.sign(entity.zScale);
+                group.rotation.z *= Math.sign(entity.zScale) 
+                flag = 1;
+                //检查下其他的extrusionDirection 
+            }
+            
+        }else{
+            /* if(entity.anchorPoint) {
+                group.position.x = entity.anchorPoint.x;
+                group.position.y = entity.anchorPoint.y;
+                group.position.z = entity.anchorPoint.z;
+            } */
+        }    
+          
+         
+        //add:
+        
+        group.updateMatrixWorld()
+        
+        var visiEntities = block.entities.filter(e=>e.visible !== false)
+        //console.log("block的可见children个数"+block.entities.length)
+         
+        for(var i = 0; i < visiEntities.length; i++) {
+            var childEntity = drawEntity(visiEntities[i], data, unsupportTypes, group  );
+            if(childEntity && !group.children.includes(childEntity)) group.add(childEntity);
         }
-
+        
+        
         return group;
     }
 

+ 8 - 8
src/materials/shaders/pointcloud_new.vs

@@ -1090,17 +1090,17 @@ void doClipping(vec4 world){
                         vColor = percentToByte(diff); 
                         */ 
                         vColor = percentToByte(currentHeight);
-                         
+                        //vColor = color.rgb;
                         vOpacity = 1.0;
                         
                     #else
-                        vColor = color.rgb;
-                        //float baseHeight = byteToFloat(color.rgb);
-                        //if(currentHeight > baseHeight){
-                        //    vColor.g += 0.5; 
-                        //}else{
-                        //    vColor.r += 0.5; 
-                        //}
+                        //vColor = color.rgb;
+                        float baseHeight = byteToFloat(color.rgb);
+                        if(currentHeight > baseHeight){
+                            vColor.g += 0.5; 
+                        }else{
+                            vColor.r += 0.5; 
+                        }
                     #endif
                     
                     inside = true;

+ 2 - 1
src/navigation/InputHandlerNew.js

@@ -330,7 +330,8 @@ export class InputHandler extends THREE.EventDispatcher {
 
 	onKeyDown (e) {
 		if (this.logMessages) console.log(this.constructor.name + ': onKeyDown');
-        
+        if(e.target.nodeName == 'INPUT' || e.target.nodeName == 'TEXTAREA') return //正在输入文字     或e.srcElement
+
         if(!this.containsMouse)return //在别的ui上无效
         
         

+ 22 - 15
src/utils/TransformationToolNew.js

@@ -158,7 +158,8 @@ 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 );
-                        viewer.dispatchEvent('content_changed')
+                        this.dispatchEvent('changeByHistory')
+                        viewer.dispatchEvent('content_changed') 
                         return true
                     } 
                 } ,
@@ -750,6 +751,7 @@ export class TransformationTool extends THREE.EventDispatcher{
 			let normal = new THREE.Vector3(...handle.alignment);
 			for (let selection of this.selection) {
 				selection.rotateOnAxis(normal, angle);
+                selection.updateMatrixWorld();//xzw add 保险起见立即update
 				selection.dispatchEvent({
 					type: "orientation_changed",
 					object: selection
@@ -859,14 +861,14 @@ export class TransformationTool extends THREE.EventDispatcher{
                         
                         
                         for (let selection of this.selection) {
-                             
+                            selection.updateMatrixWorld();//xzw add 保险起见立即update
                             selection.dispatchEvent({
                                 type: "position_changed",
                                 object: selection
                             });
                         }
                         this.dispatchEvent({type:'transformed', changeType: ['position'], matrixBefore})//add
-                           
+                         
                     }  
                 }
             }
@@ -948,14 +950,17 @@ export class TransformationTool extends THREE.EventDispatcher{
                 let matrixBefore = this.selection[0].matrix.clone()
 				for (let selection of this.selection) {
                     //xzw 改:否则不跟手
-                    let diffScale_ = diffScale.clone().divide(selection.boundingBox.getSize(new THREE.Vector3))
-					selection.scale.add(diffScale_);
-                    //selection.scale.add(diffScale);
-					selection.scale.x = Math.max(0.1, selection.scale.x);
-					selection.scale.y = Math.max(0.1, selection.scale.y);
-					selection.scale.z = Math.max(0.1, selection.scale.z);
-					selection.position.add(diffPosition);
+                    let size = selection.boundingBox.getSize(new THREE.Vector3) 
+                    let diffScale_ = diffScale.clone().divide(size)
                     
+                    size.x == 0 && (diffScale_.x = 0)    //add 若为0,不改此轴大小
+                    size.y == 0 && (diffScale_.y = 0)
+                    size.z == 0 && (diffScale_.z = 0)
+                     
+					selection.scale.add(diffScale_); 
+                    selection.scale.max(new THREE.Vector3(0.1,0.1,0.1))  
+					selection.position.add(diffPosition);
+                    selection.updateMatrixWorld();//xzw add 保险起见立即update
                     
 					selection.dispatchEvent({
 						type: "position_changed",
@@ -966,9 +971,9 @@ export class TransformationTool extends THREE.EventDispatcher{
 						object: selection
 					});
                     
-                    this.dispatchEvent({type:'transformed', changeType: ['position','scale'], matrixBefore})//add
 				}
-
+                
+                this.dispatchEvent({type:'transformed', changeType: ['position','scale'], matrixBefore})//add
 				drag.pivot.copy(iOnLine);
 				//Utils.debugSphere(viewer.scene.scene, drag.pivot, 0.05);
 			}
@@ -1076,7 +1081,7 @@ export class TransformationTool extends THREE.EventDispatcher{
 
                  
 			let selected = this.selection[0]; 
-            selected.updateMatrixWorld();//add 否则scale的sphere抖动
+            //selected.updateMatrixWorld();//add 否则scale的sphere抖动
             
 			let world = selected.matrixWorld;
 			let camera = this.viewer.mainViewport.camera//this.viewer.scene.getActiveCamera();
@@ -1085,8 +1090,10 @@ export class TransformationTool extends THREE.EventDispatcher{
             
         
 			let center = selected.boundingBox.getCenter(new THREE.Vector3()).clone().applyMatrix4(selected.matrixWorld);
-
-			this.scene.scale.copy(selected.boundingBox.getSize(new THREE.Vector3()).multiply(selected.scale));
+            let scale = selected.boundingBox.getSize(new THREE.Vector3()).multiply(selected.scale)
+            scale.max(new THREE.Vector3(.1,.1,.1)) //xzw add 如果是plane,没有厚度,会导致该tool消失
+            
+			this.scene.scale.copy(scale);
 			this.scene.position.copy(center);
 			this.scene.rotation.copy(selected.rotation);    //这里只考虑当前子级的scale rotation