import {Measure} from "../../objects/tool/Measure.js"; import math from "../../utils/math.js"; import * as THREE from "../../../../libs/three.js/build/three.module.js"; let areaPlaneMats = { } export class Prism extends Measure{ constructor(args){ super(args) this.isPrism = true this.volumeInfo = {} this.needsCompute = true /*this.createPrismLines(new THREE.Color('#FFF') ) this.lineMesh.material.transparent = true this.lineMesh.material.opacity = 0.5 Potree.Utils.setObjectLayers(this.lineMesh, 'measure' ) */ this.setClipBox() this.setTopOrBtm('zMin') this.setTopOrBtm('zMax') this.setHorizonHeight('btm') let update =()=>{ this.setHorizonHeight(this.horizonType, true)//更新 this.needsCompute = true this.getBound() this.dispatchEvent('updated') } this.addEventListener('marker_dropped'/* 'marker_moved' */,update) this.addEventListener('changeByHistory',update) this.addEventListener('changed',update) /* this.addEventListener('createDone',()=>{ this.setHorizonHeight()//更新 this.updateAreaPlane() }) */ this.updateAreaPlane() 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 if(typeof v == 'number'){ this.horizonType = 'number' this.horizonZ = v }else{ if(v){ this.horizonType = v } if(!this.horizonType) this.horizonType = 'btm' if(this.horizonType == 'number')return let zs = this.points.map(p=>p.z).sort((a,b)=>a-b) this.horizonZ = this.horizonType == 'btm' ? zs[0] : zs[this.points.length-1] } //this.horizonZ = THREE.Math.clamp(this.horizonZ, this.zMin, this.zMax ) if(this.horizonZ != old ){ this.needsCompute = true this.update() //update areaPlane and areaLabel pos this.dispatchEvent('horizonZChanged') } //console.log(this.horizonZ) } setBaseModel(model, modelHaventLoad){//三种状态:使用model、使用基准高度、 什么都没有(不允许计算、不高亮、等待模型上传) this.baseModel = model this.modelHaventLoad = modelHaventLoad Potree.Utils.updateVisible(this.areaPlane,'unuseHorizonH',!model && !modelHaventLoad) } setClipBox(boxes){//clipBoxes_out this.clipBoxes = boxes || [] } setTopOrBtm(name,v){ if(v != void 0 ){ this[name] = v this.updatePrismLines() }else{ this[name] = viewer.bound.boundingBox[name == 'zMin' ? 'min' : 'max'].z } this.getBound() this.needsCompute = true } getBound(){ let bound = Potree.math.getBound(this.points) bound.min.z = this.zMin bound.max.z = this.zMax this.prismBound = bound } setVolumeInfo(volumeInfo){ this.volumeInfo = volumeInfo this.getVolumeString() this.needsCompute = false //但得到的不一定是对的可能 检查下 } getVolumeString(){ if(!this.volumeInfo || this.volumeInfo.Vupper == void 0)return; this.VupperString = this.getConvertString(this.volumeInfo.Vupper, 'volume', true) this.VlowerString = this.getConvertString(this.volumeInfo.Vlower, 'volume', true) this.highestString = this.getConvertString(this.volumeInfo.highest, 'distance', true) this.lowestString = this.getConvertString(this.volumeInfo.lowest, 'distance', true) } getConvertString(num, type, restrictUnit){ if(!restrictUnit)return super.getConvertString(num, type) return viewer.unitConvert.convert(num, type, Potree.settings.precision, this.unitSystem, null , {//在pdf里的高度要统一单位 'imperial': {restrictUnit: 'Foot'}, //ft 'metric': {restrictUnit: 'Meter'} } ) } setUnitSystem(unitSystem){ let old = this.unitSystem super.setUnitSystem(unitSystem) if(unitSystem != old){ this.getVolumeString() } } getCenter(type){ if(type == 'areaPlaneCenter'){//areaPlane中心 return this.areaPlaneCenter } return super.getCenter() //点的中心 } update(){ super.update.apply(this, arguments) this.updatePrismLines() } getTransformationMatrix(pointcloud) {//剪裁矩阵 let invMatrix = new THREE.Matrix4; //把当前z移动到-0.5 ~ 0.5所需要的变换 let minZ = this.zMin//viewer.bound.boundingBox.min.z let maxZ = this.zMax//viewer.bound.boundingBox.max.z let s = 1/(maxZ-minZ) let pos = new THREE.Vector3(0,0, -0.5 - minZ * s ), scale = new THREE.Vector3(1,1,s); invMatrix.compose( pos, new THREE.Quaternion, scale ); //先缩放后位移 return (new THREE.Matrix4).multiplyMatrices(invMatrix, pointcloud.transformMatrix).transpose() } changeStyleForScreenshot(state, {hideLabel,showName}={}){//截图前变一下外观。根据高度变化颜色 let config = Potree.settings.prismHeightColor let color//, lineWidth = this.edges[0].material.lineWidth if(this.volumeInfo.Vupper > 0.01 && this.volumeInfo.Vlower > 0.01){ color = config.every.color }else if(this.volumeInfo.Vupper > this.volumeInfo.Vlower){ for(let i = config.dig.length-1; i>=0; i--){ if(this.volumeInfo.Vupper >= config.dig[i].min){ color = config.dig[i].color break } } }else{ for(let i = config.fill.length-1; i>=0; i--){ if(this.volumeInfo.Vlower >= config.fill[i].min){ color = config.fill[i].color break } } } color = new THREE.Color(color[0]/255,color[1]/255,color[2]/255) 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.6, side:THREE.DoubleSide, }) areaPlaneMats[name] = mat } this.oldAreaPlaneMat = this.areaPlane.material this.areaPlane.material = mat if(hideLabel){ Potree.Utils.updateVisible(this.areaLabel, 'screenshot-single',false) } if(showName){ this.areaLabel.setText([this.name, this.area.string]) /* let btm = this.areaPlaneCenter.clone().setY(this.prismBound.min.y) //置于土方2d块底部 this.areaLabel.setPos(btm) this.areaLabel.sprite.position.y = -0.25 */ } 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) this.styleRecover = ()=>{ this.areaPlane.material = this.oldAreaPlaneMat if(hideLabel){ Potree.Utils.updateVisible(this.areaLabel, 'screenshot-single', true) } if(showName){ this.areaLabel.setText(this.area.string) /* this.areaLabel.setPos(this.areaPlaneCenter) this.areaLabel.sprite.position.y = 0 */ } 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) this.styleRecover = null } }else{ 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}, {color: [223, 118, 21, 1], min: 5, max: 10}, // 没有min表示大于 {color: [186, 57, 57, 1], min: 10} ], dig: [ {color: [144, 193, 190, 1], min: 0, max: 5}, {color: [76, 155, 211, 1], min: 5, max: 10}, // 没有min表示大于 {color: [79, 76, 211, 1], min: 10} ], // 填挖并存 every: { color: [49, 200, 181, 1] } } */ }