|
@@ -84,7 +84,7 @@ export class Viewer extends ViewerBase{
|
|
|
CamAniEditor
|
|
|
}
|
|
|
|
|
|
- this.testingMaxLevel = true
|
|
|
+ //this.testingMaxLevel = true
|
|
|
|
|
|
|
|
|
console.log('create viewer')
|
|
@@ -95,6 +95,9 @@ export class Viewer extends ViewerBase{
|
|
|
this.unitConvert = new UoMService();
|
|
|
mapArea = mapArea_
|
|
|
this.visible = true
|
|
|
+ this.fpVisiDatasets = []
|
|
|
+ this.atDatasets = []
|
|
|
+
|
|
|
//-------------
|
|
|
|
|
|
var supportExtFragDepth = !!Features.EXT_DEPTH.isSupported() ;//iphoneX居然不支持
|
|
@@ -487,7 +490,7 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
pointDensity = density
|
|
|
|
|
|
- this.setPointLevel()
|
|
|
+ this.setPointLevels()
|
|
|
|
|
|
|
|
|
}
|
|
@@ -508,35 +511,7 @@ export class Viewer extends ViewerBase{
|
|
|
}
|
|
|
}
|
|
|
})
|
|
|
-
|
|
|
- this.addEventListener('updateNodeMaxLevel',(e)=>{
|
|
|
-
|
|
|
- if(!viewer.testNodeLevelTimer && viewer.testingMaxLevel ){
|
|
|
- viewer.testNodeLevelTimer = setTimeout(()=>{//先加载一段时间最高level的点云。但希望不会刚好附近的点云都没有达到最高的level,否则就要走一段才能了。
|
|
|
- viewer.testingMaxLevel = false
|
|
|
- console.log('结束testingMaxLevel')
|
|
|
-
|
|
|
- this.setPointLevel()//重新计算
|
|
|
- },3000)
|
|
|
- viewer.beginTestTime = Date.now()
|
|
|
- }
|
|
|
- console.log('updateNodeMaxLevel ' + e.pointcloud.dataset_id + " : "+ e.nodeMaxLevel)
|
|
|
- if(e.nodeMaxLevel >= 10 && viewer.testingMaxLevel){//10的时候差不多能加载到11和12了。假设最高只有12的话,就到10就可以。不过大多数场景都到不了10,也不知有没有大于10的,如果没有,这里可以写5. 见过最小是1
|
|
|
- viewer.testingMaxLevel = false
|
|
|
- console.log('提前结束testingMaxLevel,用时:'+(Date.now()-viewer.beginTestTime))
|
|
|
- //我的电脑用时大概1500
|
|
|
- }
|
|
|
-
|
|
|
- this.setPointLevel()//重新计算
|
|
|
-
|
|
|
-
|
|
|
- if(!Potree.settings.sizeFitToLevel){
|
|
|
- e.pointcloud.changePointSize()
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- //见过最小加载到的nodeMaxLevel是4
|
|
|
- })
|
|
|
+
|
|
|
|
|
|
}
|
|
|
{
|
|
@@ -560,38 +535,222 @@ export class Viewer extends ViewerBase{
|
|
|
}
|
|
|
|
|
|
|
|
|
+ this.addEventListener('allLoaded', this.testPointcloudsMaxLevel.bind(this))
|
|
|
+
|
|
|
+ {
|
|
|
+
|
|
|
+ //更新所在数据集
|
|
|
+ var lastPos = new THREE.Vector3(Infinity,Infinity,Infinity)
|
|
|
+ this.addEventListener('camera_changed', e => {
|
|
|
+ Common.intervalTool.isWaiting('atWhichDataset', ()=>{ //延时update,防止卡顿
|
|
|
+ let currPos = viewer.scene.getActiveCamera().position
|
|
|
+
|
|
|
+ if(!currPos.equals(lastPos)){
|
|
|
+ lastPos.copy(currPos)
|
|
|
+
|
|
|
+ var at = this.scene.pointclouds.filter(e=>e.ifContainsPoint(currPos))
|
|
|
+
|
|
|
+ if(Common.getDifferenceSet(at, this.atDatasets).length){
|
|
|
+ //console.log('atDatasets', at)
|
|
|
+ this.atDatasets = at
|
|
|
+ this.updateFpVisiDatasets()
|
|
|
+ this.dispatchEvent({type:'pointcloudAtChange',pointclouds:at})
|
|
|
+ }
|
|
|
+
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ }, 500)
|
|
|
+
|
|
|
+ })
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
+ this.addEventListener('switchFloorplanSelect',(e)=>{//进入平面图设置后 切换选中的数据集
|
|
|
+ this.selectedFloorplan = e.pointcloud; //绝对显示
|
|
|
+ this.updateFpVisiDatasets()
|
|
|
+ let pointclouds;
|
|
|
+ if(e.pointcloud){
|
|
|
+ pointclouds = [e.pointcloud]
|
|
|
+ }else if(this.fpVisiDatasets.length){
|
|
|
+ pointclouds = this.fpVisiDatasets
|
|
|
+ }
|
|
|
+
|
|
|
+ pointclouds && this.mapViewer.fitToDatasets(pointclouds)
|
|
|
+
|
|
|
+ })
|
|
|
|
|
|
+
|
|
|
+ this.modules.SiteModel.bus.addEventListener('FloorChange',()=>{
|
|
|
+ this.updateFpVisiDatasets()
|
|
|
+ })
|
|
|
+
|
|
|
+
|
|
|
+ /* this.modules.Clip.bus.addEventListener('updateSelectedDatasets',()=>{
|
|
|
+ this.updateFpVisiDatasets()
|
|
|
+ }) */
|
|
|
+
|
|
|
+ this.mapViewer.mapLayer.addEventListener('floorplanLoaded',()=>{
|
|
|
+ this.updateCadVisibles(this.fpVisiDatasets, true) //加载完成后重新更新下
|
|
|
+ })
|
|
|
+
|
|
|
|
|
|
}
|
|
|
|
|
|
+
|
|
|
|
|
|
|
|
|
+
|
|
|
+ updatePanosVisibles(currentFloor, pointclouds){//显示数据集和当前楼层的所有panos(为了显示出平面图中所有漫游点。漫游点个数>=平面图中包含的)
|
|
|
+ viewer.images360.panos.forEach(pano=>{
|
|
|
+ let visible = currentFloor && currentFloor.panos.includes(pano) || pointclouds.some(e=>e.panos.includes(pano));
|
|
|
+ viewer.updateVisible(pano, 'buildingChange', visible, 2)
|
|
|
+ })
|
|
|
+ }
|
|
|
|
|
|
|
|
|
- setPointLevel(){
|
|
|
- var pointDensity = Potree.settings.pointDensity
|
|
|
- var config = Potree.config.pointDensity[pointDensity];
|
|
|
- if(!config)return
|
|
|
- this.scene.pointclouds.forEach(e=>{
|
|
|
- if(this.testingMaxLevel){
|
|
|
- e.maxLevel = 12;//先加载到最大的直到测试完毕。由于5个level为一组来加载,所以如果写4最高能加载到5,如果写5最高能加载到下一个级别的最高也就是10
|
|
|
- //console.log('maxLevel: '+e.maxLevel + ' testingMaxLevel中 ' )
|
|
|
- }else{
|
|
|
- let percent = config.percentByUser && Potree.settings.UserDensityPercent != void 0 ? Potree.settings.UserDensityPercent : config.maxLevelPercent
|
|
|
- e.maxLevel = Math.round( percent * e.nodeMaxLevel);
|
|
|
- //console.log('maxLevel: '+e.maxLevel + ', density : '+Potree.settings.pointDensity, ", percent :"+percent);
|
|
|
+ updateFpVisiDatasets(){
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ let Clip = this.modules.Clip
|
|
|
+ let SiteModel = this.modules.SiteModel
|
|
|
+ let Alignment = this.modules.Alignment
|
|
|
+ var currentFloor = SiteModel.currentFloor;
|
|
|
+
|
|
|
+ /* if(Clip.editing){
|
|
|
+
|
|
|
+ this.updateCadVisibles(Clip.selectedDatasets)
|
|
|
+
|
|
|
+
|
|
|
+ }else */if(this.selectedFloorplan){//平面图设置中
|
|
|
+ let pointclouds = [this.selectedFloorplan]
|
|
|
+ this.updateCadVisibles(pointclouds)
|
|
|
+ }else if(SiteModel.editing || Alignment.editing){//只显示勾选的,也就是显示的点云的
|
|
|
+ let pointclouds = this.scene.pointclouds.filter(p => this.getObjVisiByReason(p,'datasetSelection') );
|
|
|
+ this.updateCadVisibles(pointclouds)
|
|
|
+ this.updatePanosVisibles(currentFloor, pointclouds)
|
|
|
+ }else{
|
|
|
+ let pointclouds = currentFloor ? this.findPointcloudsAtFloor(currentFloor) : []
|
|
|
+
|
|
|
+ if(pointclouds == 0){//如果当前不在任何楼层或楼层中无数据集,就用当前所在数据集
|
|
|
+ pointclouds = this.atDatasets
|
|
|
+ }
|
|
|
+
|
|
|
+ this.updateCadVisibles(pointclouds)
|
|
|
+ this.updatePanosVisibles(currentFloor, pointclouds)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ findPointcloudsAtFloor(entity){//找当前楼层需要显示哪些数据集。
|
|
|
+ //必要条件:数据集的belongToEntity 在这个entity内(否则会出现点击数据集飞过去平面图却不显示)。or 如果数据集有漫游点的话,需要包含>20%的漫游点。 (防止重叠体积很大但其实一个漫游点都不包含)
|
|
|
+ //充分条件(在符合必要条件之后还应该满足至少一个充分条件): 重叠体积>50% 或 包含>50%的漫游点
|
|
|
+
|
|
|
+
|
|
|
+ const ratio1 = 0.2, ratio2 = 0.5, ratio3 = 0.5
|
|
|
+ var pointclouds = viewer.scene.pointclouds.filter(e=>{
|
|
|
+
|
|
|
+
|
|
|
+ if(e.belongToEntity && (e.belongToEntity == entity || e.belongToEntity.buildParent == entity)){//必要条件1
|
|
|
+ return true
|
|
|
+ }
|
|
|
+
|
|
|
+ if(e.panos.length){//必要条件2
|
|
|
+ var insidePanos = e.panos.filter(a=>entity.ifContainsPoint(a.position));
|
|
|
+ let panoCountRatio = insidePanos.length / e.panos.length
|
|
|
+ if(panoCountRatio < ratio1){
|
|
|
+ return false
|
|
|
+ }
|
|
|
|
|
|
- if(Potree.settings.sizeFitToLevel){
|
|
|
- e.changePointSize()
|
|
|
+ if(panoCountRatio > ratio2)return true
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ let volume = entity.intersectPointcloudVolume(e);
|
|
|
+ let volumeRatio = volume / entity.getVolume(true) //注:hole加入计算
|
|
|
+ if(volumeRatio > ratio3){
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return pointclouds
|
|
|
+ }
|
|
|
+
|
|
|
+ updateCadVisibles(visiClouds, force){
|
|
|
+ let oldVisi = this.fpVisiDatasets
|
|
|
+ var visiClouds = this.fpVisiDatasets = visiClouds
|
|
|
+
|
|
|
+ if(!force){
|
|
|
+ var difference = Common.getDifferenceSet(oldVisi , visiClouds)
|
|
|
+ if(difference.length == 0)return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ viewer.scene.pointclouds.forEach(pointcloud=>{
|
|
|
+ var floorplan = viewer.mapViewer.mapLayer.getFloorplan(pointcloud.dataset_id)
|
|
|
+ var visi = visiClouds.includes(pointcloud)
|
|
|
+ if(floorplan){
|
|
|
+ viewer.updateVisible(floorplan.objectGroup, 'buildingChange', visi)
|
|
|
+ }/* else if(!visi){
|
|
|
+ let changeVisi = (e)=>{
|
|
|
+ viewer.updateVisible(e.floorplan.objectGroup, 'buildingChange', this.fpVisiDatasets.includes(pointcloud))
|
|
|
+ viewer.mapViewer.mapLayer.removeEventListener('floorplanLoaded', changeVisi)
|
|
|
+ console.log('updateCadVisibles加载后更改显示',e)
|
|
|
}
|
|
|
- e.changePointOpacity()
|
|
|
- }
|
|
|
+ viewer.mapViewer.mapLayer.addEventListener('floorplanLoaded', changeVisi)
|
|
|
+ } */
|
|
|
+ //已经添加了全局的 floorplanLoaded后会updateCadVisibles,这段就删了
|
|
|
+ })
|
|
|
+ viewer.mapViewer.mapLayer.needUpdate = true //可能需要更新加载的level程度
|
|
|
+ viewer.mapViewer.needRender = true //若上句不触发加载也要立即重新绘制
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //更新所在数据集
|
|
|
+
|
|
|
+ testPointcloudsMaxLevel(){ //所有点云都无需testMaxNodeLevel 就停止
|
|
|
+ let camera_changed, count = 0
|
|
|
+ let test = ()=>{
|
|
|
+ camera_changed = true
|
|
|
+
|
|
|
+
|
|
|
+ Common.intervalTool.isWaiting('testPointcloudsMaxLevel', ()=>{
|
|
|
+ if(!camera_changed && count>10 )return //只有当camera_changed后才继续循环, 除了最开始几次需要连续加载下
|
|
|
+ camera_changed = false
|
|
|
+ count ++;
|
|
|
+ //console.log('testPointcloudsMaxLevel中')
|
|
|
+
|
|
|
+ var success = true
|
|
|
+ viewer.scene.pointclouds.forEach(e=>{
|
|
|
+ var wait = e.testMaxNodeLevel()
|
|
|
+ if(wait){
|
|
|
+ success = false;
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ if(!success)return true //没有全部加载完,继续循环
|
|
|
+ else {
|
|
|
+ this.removeEventListener('camera_changed',test)
|
|
|
+ console.log('testPointcloudsMaxLevel结束')
|
|
|
+ }
|
|
|
+
|
|
|
+ }, count<5 ? 150 : 500)
|
|
|
+ }
|
|
|
+ this.addEventListener('camera_changed',test)
|
|
|
+ test()
|
|
|
+
|
|
|
+ /* 检验:
|
|
|
+ viewer.scene.pointclouds.sort((a,b)=>a.nodeMaxLevelPredict.min - b.nodeMaxLevelPredict.min).forEach(e=>console.log(e.nodeMaxLevel, e.nodeMaxLevelPredict.min))
|
|
|
+
|
|
|
+ */
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ setPointLevels(){
|
|
|
+ this.scene.pointclouds.forEach(e=>{
|
|
|
+ e.setPointLevel()
|
|
|
})
|
|
|
- /* if(!viewer.testingMaxLevel && Potree.sdk){
|
|
|
- Potree.sdk.scene.changePointSize()
|
|
|
- Potree.sdk.scene.changePointOpacity()
|
|
|
- } */
|
|
|
}
|
|
|
|
|
|
|
|
@@ -2857,7 +3016,7 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
|
|
|
|
|
|
- var screenshot = ()=>{
|
|
|
+ var screenshot = ()=>{
|
|
|
|
|
|
useMap && (viewer.mapViewer.needRender = true)
|
|
|
|
|
@@ -3203,7 +3362,7 @@ export class Viewer extends ViewerBase{
|
|
|
} else if (type == 'tag' || type == 'point') {
|
|
|
//dimension = 1
|
|
|
target.copy(object.position)
|
|
|
- let bestDistance = o.distance || 2
|
|
|
+ let bestDistance = o.distance || 3
|
|
|
|
|
|
if(!o.dontMoveMap){
|
|
|
//console.log('mapFocusOn: '+target.toArray())
|
|
@@ -3295,16 +3454,14 @@ export class Viewer extends ViewerBase{
|
|
|
})
|
|
|
}else return false
|
|
|
}else{
|
|
|
-
|
|
|
- if(this.controls == this.orbitControls){
|
|
|
- let dis = 2
|
|
|
- let target = center
|
|
|
- position = new THREE.Vector3().subVectors(target, this.scene.view.direction)
|
|
|
- viewer.scene.view.setView({position, duration, target})
|
|
|
+ if(this.modules.Clip.editing){
|
|
|
+ this.modules.Clip.bus.dispatchEvent({type:'flyToPos', position:center})
|
|
|
}else{
|
|
|
if(math.closeTo(center, this.images360.position)) return 'posNoChange'
|
|
|
position = center
|
|
|
viewer.scene.view.setView({position, duration })
|
|
|
+
|
|
|
+ viewer.mapViewer.moveTo(position.clone(), null/* boundSizeMap */, duration)
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -3568,36 +3725,63 @@ export class Viewer extends ViewerBase{
|
|
|
|
|
|
|
|
|
//设置点云为标准模式
|
|
|
- setPointStandardMat(state, pointDensity){
|
|
|
- //console.log('setPointStandardMat',state)
|
|
|
+ setPointStandardMat(state, pointDensity, fitPointsize){
|
|
|
+ console.log('setPointStandardMat',state)
|
|
|
if(state){
|
|
|
if(this.pointStatesBefore){
|
|
|
return console.error('已设置过pointStatesBefore!')
|
|
|
}
|
|
|
- this.pointStatesBefore = {opacity : new Map(), density:Potree.settings.pointDensity }
|
|
|
+ this.pointStatesBefore = {
|
|
|
+ opacity : new Map(),
|
|
|
+ size: new Map(),
|
|
|
+ density:Potree.settings.pointDensity,
|
|
|
+ useEDL:this.getEDLEnabled(),
|
|
|
+ shape: viewer.scene.pointclouds[0].material.shape
|
|
|
+ }
|
|
|
+
|
|
|
viewer.scene.pointclouds.forEach(e=>{
|
|
|
this.pointStatesBefore.opacity.set(e, e.temp.pointOpacity) //因为更改pointDensity时会自动变opacity,所以这项最先获取
|
|
|
- this.pointStatesBefore.colorType = e.material.activeAttributeName;
|
|
|
+ this.pointStatesBefore.colorType = e.material.activeAttributeName;
|
|
|
+ fitPointsize && this.pointStatesBefore.size.set(e,e.temp.pointSize) //这项不一定有用,因为会被后期覆盖
|
|
|
})
|
|
|
|
|
|
if(pointDensity)Potree.settings.pointDensity = pointDensity //万一之后切换到全景模式怎么办
|
|
|
+ if(fitPointsize)Potree.settings.sizeFitToLevel = true
|
|
|
|
|
|
viewer.scene.pointclouds.forEach(e=>{
|
|
|
e.material.activeAttributeName = 'rgba';
|
|
|
- e.changePointOpacity(1)
|
|
|
+ e.material.shape = Potree.PointShape['SQUARE']
|
|
|
+ fitPointsize && e.changePointSize(Potree.config.material.pointSize, true)
|
|
|
+ e.changePointOpacity(1)
|
|
|
})
|
|
|
+
|
|
|
+ viewer.setEDLEnabled(false)
|
|
|
+
|
|
|
}else{
|
|
|
if(!this.pointStatesBefore){
|
|
|
return console.error('未设置过pointStatesBefore!')
|
|
|
}
|
|
|
+ Potree.settings.sizeFitToLevel = false
|
|
|
if(pointDensity)Potree.settings.pointDensity = this.pointStatesBefore.pointDensity
|
|
|
|
|
|
+
|
|
|
viewer.scene.pointclouds.forEach(e=>{
|
|
|
e.material.activeAttributeName = this.pointStatesBefore.colorType
|
|
|
e.changePointOpacity(this.pointStatesBefore.opacity.get(e))
|
|
|
+ e.material.shape = this.pointStatesBefore.shape
|
|
|
+
|
|
|
+ let size = this.pointStatesBefore.size.get(e)
|
|
|
+ if(size) e.changePointSize(size)
|
|
|
+
|
|
|
+
|
|
|
})
|
|
|
+ viewer.setEDLEnabled(this.pointStatesBefore.useEDL)
|
|
|
|
|
|
this.pointStatesBefore = null
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
|
|
@@ -3625,7 +3809,7 @@ export class Viewer extends ViewerBase{
|
|
|
(pointcloud)=>{
|
|
|
var size = pointcloud.pcoGeometry.tightBoundingBox.getSize(new THREE.Vector3)
|
|
|
var center = pointcloud.bound.getCenter(new THREE.Vector3)
|
|
|
- var length = size.length()
|
|
|
+ var length = size.length() / 2
|
|
|
var dis = pos.distanceTo(center);
|
|
|
return length / dis //到数据集中心的距离占数据集大小越小越好
|
|
|
}
|
|
@@ -4044,7 +4228,7 @@ export class Viewer extends ViewerBase{
|
|
|
info.plane = plane
|
|
|
plane.boundingBox = new THREE.Box3(new THREE.Vector3(0,-0.5,0),new THREE.Vector3(1,-0.4,0.2))
|
|
|
video.addEventListener('loadeddata', function(e) {
|
|
|
- video.play()
|
|
|
+ video.play()
|
|
|
if(!info.visibles/* ||!viewer.images360.currentPano || info.visibles.includes(viewer.images360.currentPano.id) */){
|
|
|
plane.material.opacity = 1
|
|
|
}
|
|
@@ -4060,9 +4244,15 @@ export class Viewer extends ViewerBase{
|
|
|
if(info.visibles.includes(e.toPano.pano.id)){ //出现
|
|
|
setTimeout(()=>{
|
|
|
plane.visible = true;
|
|
|
-
|
|
|
+ video.currentTime = 0
|
|
|
video.play();
|
|
|
- video.currentTime = 0
|
|
|
+ if(video.paused){
|
|
|
+ var startPlay = ()=>{
|
|
|
+ plane.visible && video.play()
|
|
|
+ this.removeEventListener('global_mousedown', startPlay)
|
|
|
+ }
|
|
|
+ this.addEventListener('global_mousedown', startPlay)
|
|
|
+ }
|
|
|
Potree.settings.zoom.enabled = false
|
|
|
|
|
|
transitions.start(lerp.property(plane.material, "opacity", 1 ) , e.toPano.duration*0.4 , ()=>{
|