|
@@ -3,19 +3,24 @@ import SplitScreen from "../../utils/SplitScreen"
|
|
|
import {BuildingBox} from "./BuildingBox"
|
|
|
import Common from "../../utils/Common.js";
|
|
|
import {Images360} from '../Images360/Images360'
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+import {KeyCodes} from '../../KeyCodes'
|
|
|
+import {config } from "../../settings.js";
|
|
|
+import math from "../../utils/math.js";
|
|
|
const minFloorHeight = 0.5
|
|
|
const ifDrawDatasetBound = true //显示一下数据集的tightBound线框
|
|
|
+const minMarkers = 3
|
|
|
+
|
|
|
+
|
|
|
+const Limit = {zMin:-config.map.cameraHeight, zMax:config.map.cameraHeight,} //不能超过camera的高度,为了对称所以也限制了最低
|
|
|
|
|
|
var SiteModel = {
|
|
|
-
|
|
|
+ bus: new THREE.EventDispatcher(),
|
|
|
entities:[], //所有实体
|
|
|
buildings:[], //所有建筑父集
|
|
|
meshGroup: new THREE.Object3D,
|
|
|
-
|
|
|
+ inEntity : null,
|
|
|
+ lastPos: new THREE.Vector3(Infinity,Infinity,Infinity),
|
|
|
+
|
|
|
|
|
|
init: function(){
|
|
|
|
|
@@ -26,9 +31,9 @@ var SiteModel = {
|
|
|
|
|
|
this.createHeightPull();
|
|
|
|
|
|
-
|
|
|
if(Potree.settings.isTest && ifDrawDatasetBound){
|
|
|
- viewer.on('allLoaded',()=>{
|
|
|
+ viewer.addEventListener('allLoaded',()=>{
|
|
|
+
|
|
|
viewer.scene.pointclouds.forEach(pointcloud=>{
|
|
|
let boxPoints = pointcloud.getUnrotBoundPoint();
|
|
|
|
|
@@ -46,44 +51,111 @@ var SiteModel = {
|
|
|
})
|
|
|
})
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
if(Potree.settings.isOfficial){
|
|
|
- let lastPos = new THREE.Vector3
|
|
|
- let lastEntity
|
|
|
+
|
|
|
viewer.addEventListener('camera_changed', e => {
|
|
|
- if(!this.entities.length || this.editing) return
|
|
|
- Common.intervalTool.isWaiting('sitemodelCameraInterval', ()=>{ //延时update,防止卡顿
|
|
|
- let currPos = viewer.scene.getActiveCamera().position
|
|
|
-
|
|
|
- if(!currPos.equals(lastPos)){
|
|
|
- lastPos.copy(currPos)
|
|
|
- let entity;
|
|
|
- if(Potree.settings.displayMode == 'showPanos'){
|
|
|
- entity = this.entities.find(e=>e.panos.includes(viewer.images360.currentPano))
|
|
|
- if(!entity)console.log('没找到entity')
|
|
|
- }
|
|
|
- if(!entity){
|
|
|
- entity = this.pointInWhichEntity(currPos, 'room');
|
|
|
- }
|
|
|
+ this.updateEntityAt()
|
|
|
+ })
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /* viewer.addEventListener('allLoaded',()=>{
|
|
|
+ viewer.images360.panos.forEach(pano=>{//初始化为不可见
|
|
|
+ viewer.updateVisible(pano, 'buildingChange', false)
|
|
|
+ })
|
|
|
+ }) */
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ {
|
|
|
+ let pressDelete = (e)=>{
|
|
|
+ if(e.keyCode == KeyCodes.BACKSPACE || e.keyCode == KeyCodes.DELETE){
|
|
|
+ if(this.selectedMarker){
|
|
|
+ let entity = this.selectedMarker.parent
|
|
|
+ let index = entity.markers.indexOf(this.selectedMarker)
|
|
|
+ entity.removeMarker(index)
|
|
|
|
|
|
- if(lastEntity != entity ){
|
|
|
- console.log('buildingChange', entity)
|
|
|
- entity && Potree.sdk.scene.emit('buildingChange', entity.polygon)
|
|
|
- lastEntity = entity
|
|
|
+ if(entity.points.length<2){//删到只剩一个点时重新画(如果是hole的点,直接删除hole吧?)
|
|
|
+ this.startInsertion('resume',entity)
|
|
|
}
|
|
|
- return true
|
|
|
}
|
|
|
- }, 1000)
|
|
|
- })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ viewer.inputHandler.addEventListener('keydown', pressDelete)
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
- },
|
|
|
+
|
|
|
+ },
|
|
|
|
|
|
+ updateEntityAt(force){
|
|
|
+ if(!this.entities.length || this.editing) return
|
|
|
+ Common.intervalTool.isWaiting('sitemodelCameraInterval', ()=>{ //延时update,防止卡顿
|
|
|
+ let currPos = viewer.scene.getActiveCamera().position
|
|
|
+
|
|
|
+ if(force || !currPos.equals(this.lastPos)){
|
|
|
+ this.lastPos.copy(currPos)
|
|
|
+ let entity;
|
|
|
+
|
|
|
+ let searchPos = Potree.settings.displayMode == 'showPanos' ? viewer.images360.currentPano : currPos
|
|
|
+ entity = this.pointInWhichEntity(searchPos, 'room');
|
|
|
+
|
|
|
+ if(force || this.inEntity != entity ){
|
|
|
+ console.log('buildingChange', entity)
|
|
|
+ this.bus.dispatchEvent({type:'buildingChange',entity})
|
|
|
+
|
|
|
+ this.updatePanosVisible(this.inEntity, entity)
|
|
|
+ this.inEntity = entity
|
|
|
+ }
|
|
|
+ force = false
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ }, 500)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ updatePanosVisible(lastEntity, entity, force){//根据所在楼层更新marker可见性。当在楼层中时,只显示当前楼层的marker。
|
|
|
+ if(!entity ){//暂定:不在任何一个实体中时显示全部漫游点
|
|
|
+ viewer.images360.panos.forEach(pano=>{
|
|
|
+ viewer.updateVisible(pano, 'buildingChange', true)
|
|
|
+ })
|
|
|
+ }else{
|
|
|
+ let lastFloor = lastEntity ? lastEntity.buildType == 'floor' ? lastEntity : lastEntity.buildType == 'room' ? lastEntity.buildParent : null : null; //基本只会是floor或room
|
|
|
+ let currentFloor = entity ? entity.buildType == 'floor' ? entity : entity.buildType == 'room' ? entity.buildParent : null : null; //基本只会是floor或room
|
|
|
+ if(currentFloor != lastFloor || force){
|
|
|
+ console.log('改变了floor',lastFloor,currentFloor)
|
|
|
+ if(lastFloor){
|
|
|
+ lastFloor.panos.forEach(pano=>{
|
|
|
+ viewer.updateVisible(pano, 'buildingChange', false)
|
|
|
+ })
|
|
|
+ }else{//重置为全部不可见
|
|
|
+ viewer.images360.panos.forEach(pano=>{
|
|
|
+ viewer.updateVisible(pano, 'buildingChange', false)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if(currentFloor){
|
|
|
+ currentFloor.panos.forEach(pano=>{
|
|
|
+ viewer.updateVisible(pano, 'buildingChange', true)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
enter:function(){
|
|
|
|
|
|
Potree.Log('sitemodel enter')
|
|
|
this.clear() //确保全部清空
|
|
|
this.editing = true
|
|
|
-
|
|
|
+ this.updatePanosVisible(null, null, true)//show all
|
|
|
|
|
|
let mapViewport = viewer.mapViewer.viewports[0]
|
|
|
SplitScreen.splitScreen4Views({siteModel:true/* , viewports:[{name:'Top',viewport : mapViewport }] */})
|
|
@@ -117,9 +189,18 @@ var SiteModel = {
|
|
|
|
|
|
let mapViewport = viewer.mapViewer.viewports[0]
|
|
|
SplitScreen.recoverFrom4Views()
|
|
|
-
|
|
|
+
|
|
|
+ viewer.viewports.forEach(e=>{
|
|
|
+ if(e.name != 'mapViewport'){
|
|
|
+ e.layersRemove('siteModelMapUnvisi')
|
|
|
+ }
|
|
|
+ if(e.name == 'Right' || e.name == 'Back'){
|
|
|
+ e.layersRemove('siteModeSideVisi')
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
viewer.images360.panos.forEach(pano=>{
|
|
|
- viewer.setObjectLayers(pano.marker, 'mapObjects' )
|
|
|
+ viewer.setObjectLayers(pano.marker, 'sceneObjects' )
|
|
|
})
|
|
|
|
|
|
mapViewport.layersRemove('siteModeOnlyMapVisi')
|
|
@@ -172,10 +253,12 @@ var SiteModel = {
|
|
|
this.entities.push(floor) */
|
|
|
floor.update()
|
|
|
this.addEntity(floor,parent)
|
|
|
- this.selectEntity(floor)
|
|
|
-
|
|
|
- this.updateBuildingZ(parent)
|
|
|
-
|
|
|
+ //this.selectEntity(floor)
|
|
|
+ if(this.selected == parent){//重新选择下,为了显示新楼层线框
|
|
|
+ parent.unselect()
|
|
|
+ parent.select()
|
|
|
+ }
|
|
|
+
|
|
|
return floor
|
|
|
},
|
|
|
|
|
@@ -183,43 +266,64 @@ var SiteModel = {
|
|
|
|
|
|
startInsertion:function(buildType, parent, sid, name, callback, cancelFun){
|
|
|
|
|
|
- let zMin, zMax
|
|
|
-
|
|
|
- if(buildType == 'hole' || buildType == 'room'){
|
|
|
- zMin = parent.zMin
|
|
|
- zMax = parent.zMax
|
|
|
- }else if(buildType == 'building'){
|
|
|
- parent = null
|
|
|
- zMin = viewer.bound.boundingBox.min.z
|
|
|
- zMax = viewer.bound.boundingBox.min.z
|
|
|
- }
|
|
|
- let minMarkers = 3
|
|
|
+ let zMin, zMax, entity, resume
|
|
|
let mapViewport = viewer.mapViewer.viewports[0]
|
|
|
-
|
|
|
- let entity
|
|
|
- if(buildType == 'hole'){
|
|
|
- entity = parent.addHole()
|
|
|
- this.selectEntity(parent)
|
|
|
- entity.select()
|
|
|
- console.log('挖洞 ',entity.uuid)
|
|
|
- }else{
|
|
|
+
|
|
|
+ if(buildType == 'resume'){//继续画(使用最后一个点或者新加的点)
|
|
|
+ resume = true
|
|
|
+ entity = parent
|
|
|
+ buildType = parent.buildType
|
|
|
+
|
|
|
+ //删除原先所有的点,因为它们已经添加了事件,会很麻烦:
|
|
|
+ entity.reDraw(0)
|
|
|
+ entity.isNew = true //当作新的来画
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!resume){
|
|
|
+ if(buildType == 'hole' || buildType == 'room'){
|
|
|
+ zMin = parent.zMin
|
|
|
+ zMax = parent.zMax
|
|
|
+ }else if(buildType == 'building'){
|
|
|
+ parent = null
|
|
|
+ zMin = viewer.bound.boundingBox.min.z
|
|
|
+ zMax = viewer.bound.boundingBox.min.z
|
|
|
+ }
|
|
|
|
|
|
- let prop = {
|
|
|
- buildType,
|
|
|
- //name : Potree.config.siteModel.names[buildType],//'building',
|
|
|
- zMin,
|
|
|
- zMax,
|
|
|
- buildParent:parent,
|
|
|
- sid, name,
|
|
|
- ifDraw:true
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if(buildType == 'hole'){
|
|
|
+ entity = parent.addHole()
|
|
|
+ entity.isNew = true
|
|
|
+ this.selectEntity(parent)
|
|
|
+ entity.select()
|
|
|
+ console.log('挖洞 ',entity.uuid)
|
|
|
+ }else{
|
|
|
+
|
|
|
+ let prop = {
|
|
|
+ buildType,
|
|
|
+ //name : Potree.config.siteModel.names[buildType],//'building',
|
|
|
+ zMin,
|
|
|
+ zMax,
|
|
|
+ buildParent:parent,
|
|
|
+ sid, name,
|
|
|
+ ifDraw:true
|
|
|
+ }
|
|
|
+
|
|
|
+ entity = new BuildingBox(prop);
|
|
|
+ entity.isNew = true
|
|
|
+ this.selectEntity(entity)
|
|
|
}
|
|
|
-
|
|
|
- entity = new BuildingBox(prop);
|
|
|
- this.selectEntity(entity)
|
|
|
- }
|
|
|
|
|
|
|
|
|
- entity.isNew = true
|
|
|
+
|
|
|
+ this.addEntity(entity, parent)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
|
|
|
|
|
@@ -229,7 +333,7 @@ var SiteModel = {
|
|
|
let endDragFun = (e) => {
|
|
|
if (e.button == THREE.MOUSE.LEFT ) {
|
|
|
var marker = entity.addMarker({point:entity.points[entity.points.length - 1].clone()})
|
|
|
-
|
|
|
+
|
|
|
//entity.editStateChange(true) //重新激活reticule状态
|
|
|
entity.continueDrag(marker, e)
|
|
|
} else if (e.button === THREE.MOUSE.RIGHT ) {
|
|
@@ -239,10 +343,33 @@ var SiteModel = {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- let end = (e={}) => {//确定、结束
|
|
|
-
|
|
|
- if(!e.finish && entity.markers.length<=minMarkers){//右键 当个数不够时取消
|
|
|
-
|
|
|
+
|
|
|
+ let finish = ()=>{//结束绘画
|
|
|
+ viewer.removeEventListener('cancel_insertions', Exit);
|
|
|
+ entity.removeEventListener('unselect', Exit);
|
|
|
+ clearTimeout(timer)
|
|
|
+ entity.editStateChange(false)
|
|
|
+ //pressExit && viewer.inputHandler.removeEventListener('keydown', pressExit);
|
|
|
+ callback && callback(entity)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ let end = (e={}) => {//尝试结束
|
|
|
+ /* 退出的三种形式:
|
|
|
+ 1 普通:如果大于三个marker,结束且保留;否则重新画。()
|
|
|
+ 2 删除:直接结束且删除。(remove)
|
|
|
+ 3 结束:如果大于三个marker,结束且保留;否则结束且删除。 (finish)
|
|
|
+ 4 保留:无论几个marker,都保留着,结束。(remain)
|
|
|
+ */
|
|
|
+
|
|
|
+ if(e.remove){
|
|
|
+ finish()
|
|
|
+ return this.removeEntity(entity)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if(!e.remain && !e.finish && !e.remove && entity.markers.length<=minMarkers){//右键 当个数不够时取消
|
|
|
//重新开始画
|
|
|
entity.reDraw(1)
|
|
|
|
|
@@ -253,30 +380,22 @@ var SiteModel = {
|
|
|
}
|
|
|
entity.addEventListener('dragChange',f)
|
|
|
|
|
|
- console.log('waitcontinue')
|
|
|
+ //console.log('waitcontinue')
|
|
|
entity.continueDrag(entity.markers[0], e)
|
|
|
- return
|
|
|
-
|
|
|
-
|
|
|
+ return
|
|
|
}
|
|
|
- viewer.removeEventListener('cancel_insertions', Exit);
|
|
|
- //entity.removeEventListener('unselect', Exit);
|
|
|
- clearTimeout(timer)
|
|
|
- entity.editStateChange(false)
|
|
|
|
|
|
-
|
|
|
- if (!e.finish && entity.markers.length > 3) {
|
|
|
+ finish()
|
|
|
+
|
|
|
+ if (e.remain || !e.remove && entity.markers.length > 3) {//保留
|
|
|
entity.removeMarker(entity.points.length - 1);
|
|
|
- entity.addHoverEvent()
|
|
|
+ entity.markers.forEach(marker=>{marker.dispatchEvent('addHoverEvent') })
|
|
|
if(buildType == 'room'){
|
|
|
this.fitPullBox()
|
|
|
}
|
|
|
entity.isNew = false
|
|
|
- entity.addMidMarkers()
|
|
|
-
|
|
|
+ entity.addMidMarkers()
|
|
|
|
|
|
- pressExit && viewer.inputHandler.removeEventListener('keydown', pressExit);
|
|
|
- callback && callback(entity)
|
|
|
}else{
|
|
|
this.removeEntity(entity) //直接删除没画好的,比较简单。这样就不用担心旧的continueDrag仍旧触发了
|
|
|
|
|
@@ -286,8 +405,9 @@ var SiteModel = {
|
|
|
};
|
|
|
|
|
|
|
|
|
- let Exit = (e)=>{
|
|
|
- //entity.removeEventListener('unselect', Exit);
|
|
|
+ let Exit = (e)=>{ //强制结束
|
|
|
+
|
|
|
+ entity.removeEventListener('unselect', Exit);
|
|
|
|
|
|
if(viewer.inputHandler.drag){//还未触发drop的话
|
|
|
viewer.inputHandler.drag.object.dispatchEvent({
|
|
@@ -299,47 +419,31 @@ var SiteModel = {
|
|
|
});
|
|
|
viewer.inputHandler.drag = null
|
|
|
}else{
|
|
|
- end({finish:true, remove:e.remove}) //未结束时添加新的polygon时会触发
|
|
|
+ end({remain:true})
|
|
|
}
|
|
|
viewer.inputHandler.drag = null
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
+
|
|
|
|
|
|
- viewer.dispatchEvent({
|
|
|
- type: 'cancel_insertions' //取消之前的
|
|
|
- });
|
|
|
+ viewer.dispatchEvent( 'cancel_insertions' );//取消之前的
|
|
|
viewer.addEventListener('cancel_insertions', Exit);
|
|
|
- //entity.addEventListener('unselect', Exit); //这个太难了,创建时也会被取消选中的
|
|
|
+ entity.addEventListener('unselect', Exit);
|
|
|
+
|
|
|
+
|
|
|
|
|
|
- let pressExit
|
|
|
- if(!Potree.settings.isOfficial){
|
|
|
- pressExit = (e)=>{
|
|
|
- if(e.keyCode == 27){//Esc
|
|
|
- Exit()
|
|
|
- }
|
|
|
- }
|
|
|
- viewer.inputHandler.addEventListener('keydown', pressExit)
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
var marker = entity.addMarker({point:new THREE.Vector3(0, 0, 0)})
|
|
|
- viewer.inputHandler.startDragging(marker , {dragViewport:mapViewport, endDragFun, notPressMouse:true} ); //notPressMouse代表不是通过按下鼠标来拖拽. dragViewport指定了只能在地图上拖拽
|
|
|
viewer.updateVisible(marker,'unMove',false);//这时候的位置是假的(0,0,0)所以先不可见
|
|
|
-
|
|
|
var f = ()=>{
|
|
|
viewer.updateVisible(marker,'unMove',true);
|
|
|
entity.removeEventListener('dragChange',f)
|
|
|
}
|
|
|
entity.addEventListener('dragChange',f)
|
|
|
-
|
|
|
-
|
|
|
- if(buildType!='hole'){
|
|
|
- this.addEntity(entity, parent)
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
+
|
|
|
+ marker.isDragging = true
|
|
|
+ viewer.inputHandler.startDragging(marker , {dragViewport:mapViewport, endDragFun, notPressMouse:true} ); //notPressMouse代表不是通过按下鼠标来拖拽. dragViewport指定了只能在地图上拖拽
|
|
|
|
|
|
+
|
|
|
return entity;
|
|
|
|
|
|
|
|
@@ -347,36 +451,88 @@ var SiteModel = {
|
|
|
|
|
|
},
|
|
|
|
|
|
-
|
|
|
- createFromData:function( buildType, parent ,sid, name, points=[], holes=[], zMin, zMax, initial,panos,flagPano){
|
|
|
- if(buildType != 'building' && buildType != 'floor' && buildType != 'room' ) return
|
|
|
+
|
|
|
+
|
|
|
+ getPreDealData(points, zMin, zMax, initial, buildType, parent){
|
|
|
+ /* if( buildType == 'building' ){
|
|
|
+ zMax = zMin //强制变得一样,作为基底。如果有必要,保存时再算真实的zMax。目前zMin没有保存所以数据是错的,会直接根据floor计算
|
|
|
+ } */
|
|
|
|
|
|
- {
|
|
|
- if(initial){//初始数据错的,要自己建(只有一个building和floor) 原posIsLonlat
|
|
|
- var bound = viewer.bound.boundingBox
|
|
|
- points = [
|
|
|
- new THREE.Vector3(bound.min.x, bound.min.y,0),
|
|
|
- new THREE.Vector3(bound.max.x, bound.min.y,0),
|
|
|
- new THREE.Vector3(bound.max.x, bound.max.y,0),
|
|
|
- new THREE.Vector3(bound.min.x, bound.max.y,0),
|
|
|
- ]
|
|
|
+ var bound = viewer.bound.boundingBox
|
|
|
+
|
|
|
+ if(buildType == 'building' && initial){//初始数据错的,要自己建(只有一个building和floor) 原posIsLonlat
|
|
|
+ console.log('空间模型未编辑过, 初始化了一个')
|
|
|
+
|
|
|
+ points = [
|
|
|
+ new THREE.Vector3(bound.min.x, bound.min.y,0),
|
|
|
+ new THREE.Vector3(bound.max.x, bound.min.y,0),
|
|
|
+ new THREE.Vector3(bound.max.x, bound.max.y,0),
|
|
|
+ new THREE.Vector3(bound.min.x, bound.max.y,0),
|
|
|
+ ]
|
|
|
+ zMin = bound.min.z
|
|
|
+ zMax = bound.max.z
|
|
|
+ /* points = points.map(e=>{
|
|
|
+ return viewer.transform.lonlatToLocal.forward(e)
|
|
|
+ }) */
|
|
|
+
|
|
|
+ }else{//相对于初始数据集的模型内坐标
|
|
|
+ points = points.map(e=> this.transform(e, 'fromDataset'))
|
|
|
+ if(buildType == 'floor' && initial){
|
|
|
zMin = bound.min.z
|
|
|
zMax = bound.max.z
|
|
|
- /* points = points.map(e=>{
|
|
|
- return viewer.transform.lonlatToLocal.forward(e)
|
|
|
- }) */
|
|
|
- }else{//相对于初始数据集的模型内坐标
|
|
|
- points = points.map(e=> this.transform(e, 'fromDataset'))
|
|
|
-
|
|
|
- }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return {points, zMax, zMin }
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ resetFromData:function(entity, points=[], holes=[], zMin, zMax ){
|
|
|
+
|
|
|
+
|
|
|
+ var {points, zMax, zMin} = this.getPreDealData(points, zMin, zMax , this.autoBuild , entity.buildType, entity.buildParent )
|
|
|
+
|
|
|
+ if(entity.buildType != 'floor' )entity.points = points
|
|
|
+
|
|
|
+
|
|
|
+ if(entity.buildType == 'room'){
|
|
|
+ entity.zMin = zMin
|
|
|
+ entity.zMax = zMax
|
|
|
+ }else if(entity.buildType == 'floor'){//改楼高
|
|
|
+ let height = zMax - zMin
|
|
|
+ let zMax2 = entity.zMin + height
|
|
|
+ SiteModel.changeZ(entity, 'zMax', zMax2)
|
|
|
}
|
|
|
|
|
|
+ {
|
|
|
+ //删除旧的holes重新添加
|
|
|
+ let holesOld = entity.holes
|
|
|
+ holesOld.forEach(e=>{
|
|
|
+ entity.removeHole(e)
|
|
|
+ })
|
|
|
+
|
|
|
+ holes.forEach(points =>{
|
|
|
+ let ps = points.map(e=> this.transform(e, 'fromDataset'))
|
|
|
+ let hole = entity.addHole(ps)
|
|
|
+ hole.addMidMarkers()
|
|
|
+ })
|
|
|
+ }
|
|
|
|
|
|
- if(buildType == 'building' ){
|
|
|
- zMax = zMin //强制变得一样,作为基底。如果有必要,保存时再算真实的zMax。目前zMin没有保存所以数据是错的,会直接根据floor计算
|
|
|
- }
|
|
|
|
|
|
|
|
|
+ entity.update()
|
|
|
+ return entity
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ ,
|
|
|
+
|
|
|
+ createFromData:function( buildType, parent ,sid, name, points=[], holes=[], zMin, zMax, initial,panos,flagPano){
|
|
|
+ if(buildType != 'building' && buildType != 'floor' && buildType != 'room' ) return
|
|
|
+
|
|
|
+
|
|
|
+ var {points, zMax, zMin} = this.getPreDealData(points, zMin, zMax , initial, buildType, parent )
|
|
|
+
|
|
|
|
|
|
|
|
|
{
|
|
@@ -407,7 +563,8 @@ var SiteModel = {
|
|
|
zMax,
|
|
|
buildParent:parent,
|
|
|
ifDraw:this.editing || Potree.settings.drawEntityData,
|
|
|
- panos,flagPano
|
|
|
+ panos, flagPano,
|
|
|
+ autoBuild : initial
|
|
|
}
|
|
|
|
|
|
let entity = new BuildingBox(prop)
|
|
@@ -426,9 +583,9 @@ var SiteModel = {
|
|
|
})
|
|
|
|
|
|
|
|
|
- if(buildType == 'floor'){
|
|
|
+ /* if(buildType == 'floor'){
|
|
|
this.updateBuildingZ(parent)
|
|
|
- }
|
|
|
+ } */
|
|
|
|
|
|
|
|
|
return entity
|
|
@@ -436,12 +593,12 @@ var SiteModel = {
|
|
|
|
|
|
transform:function(pos, type){
|
|
|
if(type == 'toDataset'){
|
|
|
- let point = Potree.Utils.datasetPosTransform({ toDataset: true, position: pos.clone(), datasetId: Potree.datasetData[0].id })
|
|
|
+ let point = Potree.Utils.datasetPosTransform({ toDataset: true, position: pos.clone(), datasetId: Potree.settings.originDatasetId })
|
|
|
return new THREE.Vector2().copy(point)
|
|
|
|
|
|
}else{
|
|
|
let position = new THREE.Vector3().copy(pos).setZ(0)
|
|
|
- return Potree.Utils.datasetPosTransform({ fromDataset: true, position, datasetId: Potree.datasetData[0].id })
|
|
|
+ return Potree.Utils.datasetPosTransform({ fromDataset: true, position, datasetId: Potree.settings.originDatasetId })
|
|
|
|
|
|
}
|
|
|
},
|
|
@@ -466,17 +623,48 @@ var SiteModel = {
|
|
|
this.fitPullBox()
|
|
|
})
|
|
|
}else if(entity.buildType == 'floor'){
|
|
|
+ this.updateBuildingZ(parent)
|
|
|
parent.dispatchEvent({type:'addFloor'})
|
|
|
}
|
|
|
|
|
|
- console.log('添加实体:', entity.buildType, entity.sid, entity.uuid)
|
|
|
+ {//仅能存在一个marker被选中。选中的点可以被删除
|
|
|
+ entity.addEventListener('clickMarker', (e)=>{
|
|
|
+ if(this.selectedMarker == e.marker){
|
|
|
+ this.selectedMarker.dispatchEvent({type:'clickSelect',state:false})
|
|
|
+ this.selectedMarker = null
|
|
|
+ }else{
|
|
|
+ if(this.selectedMarker){
|
|
|
+ this.selectedMarker.dispatchEvent({type:'clickSelect',state:false})
|
|
|
+ }
|
|
|
+ this.selectedMarker = e.marker
|
|
|
+ this.selectedMarker.dispatchEvent({type:'clickSelect',state:true})
|
|
|
+ }
|
|
|
+ })
|
|
|
+ entity.addEventListener('removeMarker', (e)=>{
|
|
|
+ if(this.selectedMarker == e.marker){
|
|
|
+ this.selectedMarker = null
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ let unselect = (e)=>{//取消选中实体或删除后
|
|
|
+ if(this.selectedMarker && entity.markers.includes(this.selectedMarker)){
|
|
|
+ this.selectedMarker.dispatchEvent({type:'clickSelect',state:false})
|
|
|
+ this.selectedMarker = null
|
|
|
+ }
|
|
|
+ }
|
|
|
+ entity.addEventListener('dispose', unselect)
|
|
|
+ entity.addEventListener('unselect', unselect)
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ //console.log('添加实体:', entity.buildType, entity.sid, entity.uuid)
|
|
|
|
|
|
},
|
|
|
|
|
|
removeEntity : function(entity){
|
|
|
if(!this.entities.includes(entity))return
|
|
|
|
|
|
-
|
|
|
+ console.log('删除实体:', entity.buildType, entity.sid)
|
|
|
|
|
|
if(this.selected == entity){
|
|
|
this.height_pull_box.visible = false
|
|
@@ -496,6 +684,8 @@ var SiteModel = {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
var index = this.entities.indexOf(entity);
|
|
|
if(index>-1){
|
|
|
this.entities.splice(index,1)
|
|
@@ -503,10 +693,10 @@ var SiteModel = {
|
|
|
|
|
|
|
|
|
entity.dispose()
|
|
|
- entity.dispatchEvent({type:'delete'})
|
|
|
-
|
|
|
- console.log('删除实体:', entity.buildType, entity.sid)
|
|
|
+ let buildChildren = entity.buildChildren.slice()
|
|
|
+ buildChildren.forEach(e=>this.removeEntity(e))
|
|
|
|
|
|
+
|
|
|
},
|
|
|
|
|
|
|
|
@@ -516,11 +706,19 @@ var SiteModel = {
|
|
|
building.zMin = building.zMax = building.buildChildren[0].zMin //基底高度
|
|
|
//building.zMax = building.buildChildren[building.buildChildren.length-1].zMax
|
|
|
if(this.editing) building.update({dontUpdateChildren:true})
|
|
|
+ building.dispatchEvent('updateBuildingZ')
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
- selectEntity : function(entity){
|
|
|
+ selectEntity : function(entity, state=true){
|
|
|
+ if(state === false){
|
|
|
+ entity.unselect()
|
|
|
+ if(this.selected == entity)this.selected = null
|
|
|
+
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
if(this.selected == entity || entity && entity.buildType == 'hole')return
|
|
|
//this.buildings.forEach(e=>e.unselect())
|
|
|
this.selected && this.selected.unselect()
|
|
@@ -540,8 +738,10 @@ var SiteModel = {
|
|
|
this.height_pull_box.visible = true
|
|
|
this.fitPullBox()
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
+ if(entity && !entity.isNew && (entity.buildType == 'building' || entity.buildType == 'room' ) && entity.points.length<2){
|
|
|
+ this.startInsertion('resume',entity) //继续画
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
|
|
@@ -567,6 +767,7 @@ var SiteModel = {
|
|
|
|
|
|
|
|
|
fitPullBox: function(){ //自适应拖拽楼层的pullMesh
|
|
|
+ if(!this.selected || this.selected.buildType!= 'floor' && this.selected.buildType!= 'room')return
|
|
|
let bound = new THREE.Box3();
|
|
|
bound.expandByObject(this.selected.box)
|
|
|
let center = bound.getCenter(new THREE.Vector3() )
|
|
@@ -583,10 +784,10 @@ var SiteModel = {
|
|
|
let max, min //limit
|
|
|
|
|
|
if(entity.buildType == 'floor'){//楼层
|
|
|
- let index = entity.buildParent.buildChildren.indexOf(this.selected)
|
|
|
+ let index = entity.buildParent.buildChildren.indexOf(entity)
|
|
|
if(dirType == 'zMax'){
|
|
|
let upper = entity.buildParent.buildChildren[index+1];
|
|
|
- entity.zMax = value
|
|
|
+ entity.zMax = Math.min(Limit.zMax, value)
|
|
|
min = entity.zMin + minFloorHeight
|
|
|
if(entity.zMax < min){
|
|
|
entity.zMax = min
|
|
@@ -606,7 +807,7 @@ var SiteModel = {
|
|
|
}else{
|
|
|
let lower = entity.buildParent.buildChildren[index-1];
|
|
|
|
|
|
- entity.zMin = value
|
|
|
+ entity.zMin = Math.max(Limit.zMin, value)
|
|
|
max = entity.zMax - minFloorHeight
|
|
|
if(entity.zMin > max){
|
|
|
entity.zMin = max
|
|
@@ -623,7 +824,7 @@ var SiteModel = {
|
|
|
lower.update()
|
|
|
lower.dispatchEvent({type:'changeHeight'})
|
|
|
}
|
|
|
- if(index == 0)this.updateBuildingZ(this.selected.buildParent)
|
|
|
+ if(index == 0)this.updateBuildingZ(entity.buildParent)
|
|
|
}
|
|
|
}else if(entity.buildType == 'room'){//房间
|
|
|
//按照navvis的是不一定限制在当前楼层,只要高度不超过当前楼层即可。
|
|
@@ -652,9 +853,10 @@ var SiteModel = {
|
|
|
let boxGeo = new THREE.BoxBufferGeometry( 1, 1, 1/4 )
|
|
|
let boxMat = new THREE.MeshBasicMaterial({
|
|
|
color:"#F00",
|
|
|
- opacity:0 ,
|
|
|
+ opacity:0,
|
|
|
transparent:true,
|
|
|
- depthTest:false
|
|
|
+ depthTest:false,
|
|
|
+ side:2
|
|
|
})
|
|
|
|
|
|
let height_pull_box_up = new THREE.Mesh(boxGeo,boxMat)
|
|
@@ -667,8 +869,8 @@ var SiteModel = {
|
|
|
this.height_pull_box.add(height_pull_box_down)
|
|
|
this.height_pull_box.visible = false
|
|
|
this.meshGroup.add(this.height_pull_box)
|
|
|
- height_pull_box_up.position.set(0,0,3/8)
|
|
|
- height_pull_box_down.position.set(0,0,-3/8)
|
|
|
+ height_pull_box_up.position.set(0,0,1/2/* 3/8 */)
|
|
|
+ height_pull_box_down.position.set(0,0,-1/2/* -3/8 */)
|
|
|
viewer.setObjectLayers(this.height_pull_box, 'siteModeSideVisi' )
|
|
|
|
|
|
|
|
@@ -731,16 +933,22 @@ var SiteModel = {
|
|
|
},
|
|
|
|
|
|
|
|
|
- pointInWhichEntity(position, buildType, ifIgnoreHole){//返回第一个符合标准的实体,buildType是要找的建筑类型
|
|
|
-
|
|
|
+ pointInWhichEntity(location, buildType, ifIgnoreHole){//返回第一个符合标准的实体,buildType是要找的建筑类型
|
|
|
+ //location 可以是pano或者坐标
|
|
|
//由于房间可能在building外,所以房间要另外单独识别。
|
|
|
|
|
|
let lastResult; //最接近的上一层结果,如果没有result返回这个
|
|
|
let result
|
|
|
-
|
|
|
+
|
|
|
|
|
|
let traverse = (parent)=>{
|
|
|
- if(parent.ifContainsPoint(position)){
|
|
|
+ let contains;
|
|
|
+ if(location instanceof THREE.Vector3){
|
|
|
+ contains = parent.ifContainsPoint(location)
|
|
|
+ }else{//is pano
|
|
|
+ contains = parent.panos.includes(location)
|
|
|
+ }
|
|
|
+ if(contains){
|
|
|
lastResult = parent
|
|
|
if(parent.buildType == buildType){
|
|
|
return parent
|
|
@@ -779,15 +987,22 @@ var SiteModel = {
|
|
|
|
|
|
findPanos: function(){
|
|
|
|
|
|
- {//清空:
|
|
|
+ {
|
|
|
this.entities.forEach(entity=>{
|
|
|
- entity.panos = []
|
|
|
+ //清空:
|
|
|
+ entity.panos = []
|
|
|
entity.flagPano = null
|
|
|
+
|
|
|
+ viewer.images360.panos.forEach(pano=>{
|
|
|
+ if(entity.ifContainsPoint(pano.position)){
|
|
|
+ entity.panos.push(pano)
|
|
|
+ }
|
|
|
+ })
|
|
|
})
|
|
|
}
|
|
|
|
|
|
|
|
|
- viewer.images360.panos.forEach(pano=>{
|
|
|
+ /* viewer.images360.panos.forEach(pano=>{ //一个漫游点只对应一个实体的话
|
|
|
let result = this.pointInWhichEntity(pano.position, 'room');
|
|
|
|
|
|
{//get panos for every entities
|
|
@@ -797,18 +1012,25 @@ var SiteModel = {
|
|
|
entity = entity.buildParent
|
|
|
}
|
|
|
}
|
|
|
- })
|
|
|
+ }) */
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
{//search center pano
|
|
|
this.entities.forEach(entity=>{
|
|
|
+ let panos = entity.panos
|
|
|
+ if(panos.length == 0)return
|
|
|
let bound = entity.getBound();
|
|
|
let center = bound.getCenter(new THREE.Vector3)
|
|
|
let request = []
|
|
|
let rank = [
|
|
|
Images360.scoreFunctions.distanceSquared({position: center})
|
|
|
]
|
|
|
- let panos = entity.panos && entity.panos.length ? entity.panos : viewer.images360.panos
|
|
|
- let r = Common.sortByScore(panos, request, rank);//entity没有panos的话,就扩大到所有panos
|
|
|
+ //let panos = entity.panos && entity.panos.length ? entity.panos : viewer.images360.panos //entity没有panos的话,就扩大到所有panos
|
|
|
+
|
|
|
+ let r = Common.sortByScore(panos, request, rank);
|
|
|
|
|
|
if(r && r.length){
|
|
|
entity.flagPano = r[0].item
|
|
@@ -825,7 +1047,7 @@ var SiteModel = {
|
|
|
,
|
|
|
findEntityForDataset:function(){
|
|
|
var entities = this.entities.filter(e=>e.buildType == 'room' || e.buildType == 'floor' && e.buildChildren.length == 0)
|
|
|
- entities.length && viewer.scene.pointclouds.forEach(pointcloud=>{
|
|
|
+ viewer.scene.pointclouds.forEach(pointcloud=>{
|
|
|
|
|
|
let volumes = []
|
|
|
entities.forEach(entity=>{
|
|
@@ -833,8 +1055,13 @@ var SiteModel = {
|
|
|
volumes.push({entity, volume})
|
|
|
})
|
|
|
volumes.sort((a,b)=>{ return b.volume-a.volume })
|
|
|
- console.log(volumes)
|
|
|
- pointcloud.belongToEntity = volumes[0].entity; //如果约等于0怎么办???
|
|
|
+ //console.log(volumes)
|
|
|
+ if(volumes.length == 0 || volumes[0].volume < 10e-4){//如果约等于0
|
|
|
+ pointcloud.belongToEntity = null
|
|
|
+ }else{
|
|
|
+ pointcloud.belongToEntity = volumes[0].entity;
|
|
|
+ }
|
|
|
+
|
|
|
})
|
|
|
|
|
|
/*
|
|
@@ -858,14 +1085,14 @@ var SiteModel = {
|
|
|
meshGroup: new THREE.Object3D, */
|
|
|
this.selectEntity(null)
|
|
|
|
|
|
- let length = this.buildings.length;
|
|
|
+ let length = this.entities.length;
|
|
|
for(let i=0;i<length;i++){
|
|
|
- this.buildings[i].dispose()
|
|
|
+ this.entities[i].dispose()
|
|
|
}
|
|
|
|
|
|
this.entities = []
|
|
|
this.buildings = []
|
|
|
-
|
|
|
+ this.inEntity = null
|
|
|
|
|
|
|
|
|
}
|
|
@@ -876,22 +1103,49 @@ var SiteModel = {
|
|
|
if (!entity) {
|
|
|
return console.error('没找到entity ')
|
|
|
}
|
|
|
+
|
|
|
+ if(Potree.settings.displayMode == 'showPanos'){
|
|
|
+ if (isNearBy && entity.panos.length) {
|
|
|
+ if(entity.panos.includes(viewer.images360.currentPano)) return 'posNoChange' //已在当前实体中
|
|
|
|
|
|
- if (isNearBy && entity.panos.length) {
|
|
|
- let position = viewer.scene.getActiveCamera().position
|
|
|
- let request = []
|
|
|
- let rank = [Images360.scoreFunctions.distanceSquared({ position })]
|
|
|
- let r = Common.sortByScore(entity.panos, request, rank)
|
|
|
+ let position = viewer.scene.getActiveCamera().position
|
|
|
+ let request = []
|
|
|
+ let rank = [Images360.scoreFunctions.distanceSquared({ position })]
|
|
|
+ let r = Common.sortByScore(entity.panos, request, rank)
|
|
|
|
|
|
- aimPano = r[0].item
|
|
|
- } else {
|
|
|
- if (!entity.flagPano) {
|
|
|
- return console.error('没找到flagPano')
|
|
|
+ aimPano = r[0].item
|
|
|
+ } else {
|
|
|
+ if (!entity.flagPano) {
|
|
|
+ return console.log('没有flagPano')
|
|
|
+ }
|
|
|
+ aimPano = entity.flagPano
|
|
|
}
|
|
|
- aimPano = entity.flagPano
|
|
|
- }
|
|
|
+ if(aimPano == viewer.images360.currentPano) return 'posNoChange'
|
|
|
+ viewer.images360.flyToPano(aimPano)
|
|
|
+ }else{
|
|
|
+ if(isNearBy && entity.ifContainsPoint(viewer.images360.position) ){
|
|
|
+ return 'posNoChange' //已在当前实体中
|
|
|
+ }
|
|
|
+
|
|
|
+ let boundingBox = entity.getBound()
|
|
|
+ let position = boundingBox.getCenter(new THREE.Vector3())
|
|
|
+
|
|
|
+ if(viewer.controls == viewer.orbitControls){
|
|
|
+ let dis = 2
|
|
|
+ let target = position
|
|
|
+ position = new THREE.Vector3().subVectors(target, viewer.scene.view.direction)
|
|
|
+ viewer.scene.view.setView({position, duration: 1000, target})
|
|
|
+ }else{
|
|
|
+ if(math.closeTo(position, viewer.images360.position)) return 'posNoChange'
|
|
|
|
|
|
- viewer.images360.flyToPano(aimPano)
|
|
|
+ viewer.scene.view.setView({position, duration: 1000})
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ return true
|
|
|
},
|
|
|
|
|
|
focusEntity(id){
|
|
@@ -901,6 +1155,19 @@ var SiteModel = {
|
|
|
let center = boundingBox.getCenter(new THREE.Vector3())
|
|
|
this.SplitScreen.focusOnObject(boundSize, center)
|
|
|
},
|
|
|
+
|
|
|
+ removeIlligalArchi(){//删除marker数量小于3个的建筑,当保存时
|
|
|
+ let needDelete = []
|
|
|
+
|
|
|
+ this.entities.forEach(e=>{
|
|
|
+ if(e.points.length<3){
|
|
|
+ needDelete.push(e)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ needDelete.forEach(e=>this.removeEntity(e))
|
|
|
+
|
|
|
+ },
|
|
|
}
|
|
|
|
|
|
/*
|