|
@@ -1,108 +1,331 @@
|
|
|
|
|
|
import * as THREE from "../../../libs/three.js/build/three.module.js";
|
|
import * as THREE from "../../../libs/three.js/build/three.module.js";
|
|
import {ctrlPolygon} from '../../utils/ctrlPolygon'
|
|
import {ctrlPolygon} from '../../utils/ctrlPolygon'
|
|
-import {LineDraw, MeshDraw } from "../../utils/DrawUtil";
|
|
|
|
|
|
+import {LineDraw, MeshDraw } from "../../utils/DrawUtil";
|
|
|
|
+import math from "../../utils/math";
|
|
import Sprite from '../../viewer/Sprite'
|
|
import Sprite from '../../viewer/Sprite'
|
|
/* import {config} from '../settings' */
|
|
/* import {config} from '../settings' */
|
|
-
|
|
|
|
|
|
+import searchRings from "../../utils/searchRings.js";
|
|
|
|
|
|
let texLoader = new THREE.TextureLoader()
|
|
let texLoader = new THREE.TextureLoader()
|
|
|
|
|
|
|
|
|
|
let markerMats
|
|
let markerMats
|
|
-let markerSizeInfo = {width2d:30}
|
|
|
|
|
|
+let markerSizeInfo = {width2d:35}
|
|
let color = new THREE.Color('#FFF')
|
|
let color = new THREE.Color('#FFF')
|
|
-
|
|
|
|
-
|
|
|
|
-let faceMats = {
|
|
|
|
- building: new THREE.MeshPhongMaterial({
|
|
|
|
- color:"#00bbff",
|
|
|
|
- side:THREE.DoubleSide,
|
|
|
|
- opacity:0.1,
|
|
|
|
- transparent:true,
|
|
|
|
- depthTest:false
|
|
|
|
- }),
|
|
|
|
- floor: new THREE.MeshPhongMaterial({
|
|
|
|
- color:"#eeee00",
|
|
|
|
- side:THREE.DoubleSide,//BackSide,
|
|
|
|
- opacity:0.06,
|
|
|
|
- transparent:true,
|
|
|
|
- depthTest:false
|
|
|
|
- }),
|
|
|
|
- floorSelect: new THREE.MeshPhongMaterial({
|
|
|
|
- color:"#eeee00",
|
|
|
|
- side:THREE.DoubleSide,
|
|
|
|
- opacity:0.15,
|
|
|
|
- transparent:true,
|
|
|
|
- depthTest:false
|
|
|
|
- }),
|
|
|
|
- room: new THREE.MeshPhongMaterial({
|
|
|
|
- color:"#ff44ee",
|
|
|
|
- side:THREE.DoubleSide,//BackSide,
|
|
|
|
- opacity:0.06,
|
|
|
|
- transparent:true,
|
|
|
|
- depthTest:false
|
|
|
|
- }),
|
|
|
|
- roomSelect: new THREE.MeshPhongMaterial({
|
|
|
|
- color:"#ff44ee",
|
|
|
|
- side:THREE.DoubleSide,//BackSide,
|
|
|
|
- opacity:0.15,
|
|
|
|
- transparent:true,
|
|
|
|
- depthTest:false
|
|
|
|
- }),
|
|
|
|
-
|
|
|
|
|
|
+let faceMats
|
|
|
|
+let getFaceMat = (name)=>{
|
|
|
|
+ if(!faceMats){ //navvis材质可以搜gridTexture
|
|
|
|
+ let gridTex = texLoader.load( Potree.resourcePath+'/textures/gridmap.png' )
|
|
|
|
+ gridTex.wrapS = gridTex.wrapT = THREE.RepeatWrapping
|
|
|
|
+ gridTex.repeat.set(0.5,0.5)//放大一些
|
|
|
|
+ faceMats = {
|
|
|
|
+ dataset: new THREE.MeshStandardMaterial({
|
|
|
|
+ color:812922,
|
|
|
|
+ side:THREE.DoubleSide,
|
|
|
|
+ opacity:0.2,
|
|
|
|
+ transparent:true,
|
|
|
|
+ depthTest:false,
|
|
|
|
+ wireframe:true
|
|
|
|
+ }),
|
|
|
|
+ building: new THREE.MeshStandardMaterial({
|
|
|
|
+ color:812922, metalness: 0.2, roughness:0.8,
|
|
|
|
+ side:THREE.DoubleSide,
|
|
|
|
+ opacity:0.1,
|
|
|
|
+ transparent:true,
|
|
|
|
+ depthTest:false
|
|
|
|
+ }),
|
|
|
|
+ buildingSelect: new THREE.MeshStandardMaterial({
|
|
|
|
+ color:36582, metalness: 0, roughness:1,
|
|
|
|
+ side:THREE.DoubleSide,
|
|
|
|
+ opacity:0.1,
|
|
|
|
+ transparent:true,
|
|
|
|
+ depthTest:false
|
|
|
|
+ }),
|
|
|
|
+ floor: new THREE.MeshStandardMaterial({
|
|
|
|
+ color:11708469, metalness: 0.1, roughness:1,
|
|
|
|
+ side:THREE.DoubleSide,//BackSide,
|
|
|
|
+ opacity:0.05,
|
|
|
|
+ transparent:true,
|
|
|
|
+ depthTest:false
|
|
|
|
+ }),
|
|
|
|
+ /* floorSelect: new THREE.MeshStandardMaterial({
|
|
|
|
+ color:"#eeee00", metalness: 0, roughness:1,
|
|
|
|
+ side:THREE.DoubleSide,
|
|
|
|
+ opacity:0.12,
|
|
|
|
+ transparent:true,
|
|
|
|
+ depthTest:false
|
|
|
|
+ }), */
|
|
|
|
+
|
|
|
|
+ floorSelect: new THREE.MeshStandardMaterial({
|
|
|
|
+ color:16707151, metalness: 0, roughness:1,
|
|
|
|
+ side:THREE.DoubleSide,
|
|
|
|
+ opacity:1,
|
|
|
|
+ transparent:true,
|
|
|
|
+ depthTest:false,
|
|
|
|
+ map: gridTex,
|
|
|
|
+ }),
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ room: new THREE.MeshStandardMaterial({
|
|
|
|
+ color:"#ff44ee", metalness: 0, roughness:1,
|
|
|
|
+ side:THREE.DoubleSide,//BackSide,
|
|
|
|
+ opacity:0.08,
|
|
|
|
+ transparent:true,
|
|
|
|
+ depthTest:false
|
|
|
|
+ }),
|
|
|
|
+ roomSelect: new THREE.MeshStandardMaterial({
|
|
|
|
+ color:"#ff44ee", metalness: 0.3, roughness:1,
|
|
|
|
+ side:THREE.DoubleSide,//BackSide,
|
|
|
|
+ opacity:1,
|
|
|
|
+ transparent:true,
|
|
|
|
+ depthTest:false,
|
|
|
|
+ map: gridTex,
|
|
|
|
+ }),
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return faceMats[name]
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
+
|
|
export class BuildingBox extends ctrlPolygon{//建筑实体,包括building, floor, room
|
|
export class BuildingBox extends ctrlPolygon{//建筑实体,包括building, floor, room
|
|
constructor(prop) {
|
|
constructor(prop) {
|
|
prop.dimension = '3d'
|
|
prop.dimension = '3d'
|
|
- super('siteModel_'+prop.type_, prop);
|
|
|
|
|
|
+ //prop.name = Potree.config.siteModel.names[prop.buildType] +
|
|
|
|
+
|
|
|
|
+ super('siteModel_'+prop.buildType, prop);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
this.midMarkers = []
|
|
this.midMarkers = []
|
|
|
|
+ this.buildChildren = []//子实体
|
|
|
|
+ this.holes = [] //在这创建的hole
|
|
|
|
+ this.parentHoles = [];//floor从building那得到的当层holes
|
|
|
|
+ this.mats = {} //材质
|
|
|
|
+
|
|
|
|
+ this.panos = this.panos || [];
|
|
|
|
+ this.center //中心点
|
|
|
|
|
|
- if(this.type_=='floor'){//一旦添加了楼层,建筑原本的faceMesh lineMesh就隐藏
|
|
|
|
- /* this.buildParent.box.visible = false
|
|
|
|
- this.buildParent.lineMesh.visible = false */
|
|
|
|
|
|
+ if(this.buildType=='floor'){
|
|
|
|
|
|
this.points = this.buildParent.points;//完全等于建筑的点
|
|
this.points = this.buildParent.points;//完全等于建筑的点
|
|
|
|
+ this.buildParent.holes.forEach(hole=>{//从building获取holes
|
|
|
|
+ let floorHole = new BuildingBox({
|
|
|
|
+ buildType : 'hole',
|
|
|
|
+ buildParent:this,
|
|
|
|
+ originHole : hole, //整栋大楼在当层的hole
|
|
|
|
+ ifDraw: this.ifDraw || Potree.settings.drawEntityData
|
|
|
|
+ });
|
|
|
|
+ this.parentHoles.push(floorHole)
|
|
|
|
+ this.add(floorHole)
|
|
|
|
+
|
|
|
|
+ floorHole.points = hole.points//完全等于建筑的点
|
|
|
|
+ })
|
|
}
|
|
}
|
|
|
|
+ if(this.buildType == 'room' || this.buildType == 'hole'){
|
|
|
|
+ this.restrictArea = this.buildParent //不能超出的区域
|
|
|
|
+ }
|
|
|
|
|
|
- this.box = this.createBox()
|
|
|
|
- this.add(this.box)
|
|
|
|
|
|
+ if(this.ifDraw){ //只存储空间模型信息,不绘制
|
|
|
|
+ if(this.buildType != 'hole'){
|
|
|
|
+ this.box = this.createBox()
|
|
|
|
+ this.add(this.box)
|
|
|
|
+ }
|
|
|
|
+ {
|
|
|
|
+ this.lineMesh = LineDraw.createLine([],{color})
|
|
|
|
+ this.lineMesh.name = 'buildingLines'
|
|
|
|
+ this.lineMesh.visible = false
|
|
|
|
+ this.add(this.lineMesh)
|
|
|
|
+ viewer.setObjectLayers(this.lineMesh, 'sceneObjects' )
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ this.addEventListener('dragChange',(e)=>{ //修改中点
|
|
|
|
+ this.isNew || this.updateTwoMidMarker(e.index)
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
- this.lineMesh = LineDraw.createLine([],{color})
|
|
|
|
- this.lineMesh.name = 'buildingLines'
|
|
|
|
- this.add(this.lineMesh)
|
|
|
|
- viewer.setObjectLayers(this.lineMesh, 'sceneObjects' )
|
|
|
|
|
|
+ this.initData(prop)
|
|
|
|
|
|
- this.buildChildren = []//子实体
|
|
|
|
|
|
|
|
- this.addEventListener('dragChange',(e)=>{ //修改中点
|
|
|
|
- this.isNew || this.updateTwoMidMarker(e.index)
|
|
|
|
- })
|
|
|
|
-
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ initData(prop){
|
|
|
|
+ if(prop.ifDraw){
|
|
|
|
+ super.initData(prop)
|
|
|
|
+ }else{
|
|
|
|
+ if(prop.points){
|
|
|
|
+ this.points = prop.points
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ intersectPointcloudVolume(pointcloud){//和pointcloud的重叠体积
|
|
|
|
+ var bound = this.getBound()
|
|
|
|
+ let bound2 = pointcloud.bound;
|
|
|
|
+ if(!bound.intersectsBox(bound2)) return 0;
|
|
|
|
+
|
|
|
|
+ let min = Math.min(this.zMin, bound2.min.z);
|
|
|
|
+ let max = Math.max(this.zMax, bound2.max.z);
|
|
|
|
+ let height1 = this.zMax - this.zMin
|
|
|
|
+ let height2 = bound2.max.z-bound2.min.z
|
|
|
|
+ let coverHeight = height1 + height2 - (max-min)//重叠高度
|
|
|
|
+
|
|
|
|
+ let boxPoints = pointcloud.getUnrotBoundPoint() //获取tightBound的四个点。 如果是有旋转角度的点云,这个和pointcloud.bound的四个点是不一致的,覆盖面积小于pointcloud.bound
|
|
|
|
+
|
|
|
|
+ let areaWhole = 0
|
|
|
|
+ let area1 = this.getArea()
|
|
|
|
+ let area2 = Math.abs(math.getArea(boxPoints))
|
|
|
|
+
|
|
|
|
+ {//计算points与点云总面积 (但是把hole也加入了面积)(并集,重叠部分只算一次)
|
|
|
|
+ let rings = math.getPolygonsMixedRings([this.points, boxPoints] )
|
|
|
|
+
|
|
|
|
+ rings.forEach(e=>{
|
|
|
|
+ areaWhole+=e.area
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ let coverHoleArea = 0 //holes与数据集重叠的部分
|
|
|
|
+ let holes = this.holes.concat(this.parentHoles)
|
|
|
|
+ let holesArea = 0 //所有holes面积相加
|
|
|
|
+ let areaHoleWithPointcloud = 0 //hole和点云的面积并集
|
|
|
|
+
|
|
|
|
+ if(holes.length>0){//还要再扣除holes与数据集重叠的部分。其中holes为mix轮廓
|
|
|
|
+ let outHoles = []//没有重合的holes的外轮廓
|
|
|
|
+ if(holes.length>=2){//合并holes。如果能在绘制时直接合并holes就好啦,这步就转移到那去,但是要删除hole好麻烦
|
|
|
|
+
|
|
|
|
+ let holes_ = holes.map(e=>e.points)
|
|
|
|
+
|
|
|
|
+ outHoles = math.getPolygonsMixedRings(holes_, true)
|
|
|
|
+ outHoles.forEach(e=>{
|
|
|
|
+ holesArea+=e.area
|
|
|
|
+ })
|
|
|
|
+ outHoles = outHoles.map(e=>e.points)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ }else{
|
|
|
|
+ outHoles = holes.map(e=>e.points)
|
|
|
|
+ outHoles.forEach(e=> holesArea += Math.abs(math.getArea(e)))
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //holes与数据集重叠的部分
|
|
|
|
+
|
|
|
|
+ {
|
|
|
|
+ let polygons = outHoles.concat([boxPoints])
|
|
|
|
+ let rings = math.getPolygonsMixedRings(polygons)
|
|
|
|
+ rings.forEach(e=>{
|
|
|
|
+ areaHoleWithPointcloud+=e.area
|
|
|
|
+ })
|
|
|
|
+ coverHoleArea = holesArea + area2 - areaHoleWithPointcloud//hole和点云的交集
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ let coverArea = area1 + area2 - areaWhole - coverHoleArea; //重叠面积
|
|
|
|
+
|
|
|
|
+ return coverArea * coverHeight
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ addHole(points=[]){
|
|
|
|
+ let prop = {
|
|
|
|
+ buildType : 'hole',
|
|
|
|
+ zMin : this.zMin,
|
|
|
|
+ zMax : this.zMax,
|
|
|
|
+ points,
|
|
|
|
+ buildParent:this,
|
|
|
|
+ ifDraw: this.ifDraw || Potree.settings.drawEntityData
|
|
|
|
+ }
|
|
|
|
+ //hole的zMin zMax跟随buildParent
|
|
|
|
+ var hole = new BuildingBox(prop);
|
|
|
|
+ this.holes.push(hole)
|
|
|
|
+
|
|
|
|
+ if(this.buildType == 'building'){//为每一层添加对应的hole
|
|
|
|
+ this.buildChildren.forEach(floor=>{
|
|
|
|
+ let floorHole = new BuildingBox({
|
|
|
|
+ buildType : 'hole',
|
|
|
|
+ zMin : this.zMin,
|
|
|
|
+ zMax : this.zMax,
|
|
|
|
+ buildParent:floor,
|
|
|
|
+ originHole : hole, //整栋大楼在当层的hole
|
|
|
|
+ ifDraw: this.ifDraw || Potree.settings.drawEntityData
|
|
|
|
+ });
|
|
|
|
+ floor.parentHoles.push(floorHole)
|
|
|
|
+ floor.add(floorHole)
|
|
|
|
+ floorHole.points = hole.points//完全等于建筑的点
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.add(hole);//直接加在这,不加meshGroup了
|
|
|
|
+ this.update() //update box mesh
|
|
|
|
+ return hole
|
|
|
|
+
|
|
|
|
+ //hole不创建box,只有它的buildParent需要更新box。 但有线条和marker. hole不在buildChildren里,但有buildParent
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ removeHole(hole){// 这个hole不会是parentHoles里的。
|
|
|
|
+ hole.dispose()
|
|
|
|
+
|
|
|
|
+ if(this.buildType == 'building'){ //若是整栋大楼的hole,在每层去除它的对应hole
|
|
|
|
+ this.buildChildren.forEach(floor=>{
|
|
|
|
+ let holeAtFloor = floor.parentHoles.find(e=>e.originHole == this )
|
|
|
|
+ let index = floor.parentHoles.indexOf(holeAtFloor)
|
|
|
|
+ index > -1 && floor.parentHoles.splice(index, 1)
|
|
|
|
+ holeAtFloor.dispose()
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ let index = this.holes.indexOf(hole)
|
|
|
|
+ if(index>-1){
|
|
|
|
+ this.holes.splice(index, 1)
|
|
|
|
+ }
|
|
|
|
+ this.remove(hole)
|
|
|
|
+ this.update()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
|
|
|
|
|
|
createBox(){
|
|
createBox(){
|
|
var geometry = new THREE.Geometry();
|
|
var geometry = new THREE.Geometry();
|
|
- var mesh = new THREE.Mesh(geometry, faceMats[this.type_])
|
|
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ this.mats.boxDefault = getFaceMat(this.buildType)
|
|
|
|
+ this.mats.boxSelected = getFaceMat(this.buildType+'Select')
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ var mesh = new THREE.Mesh(geometry, this.mats.boxDefault)
|
|
mesh.name = 'buildingBox';
|
|
mesh.name = 'buildingBox';
|
|
- if(this.type_ == 'floor'){
|
|
|
|
- viewer.setObjectLayers(mesh, 'siteModelMapUnvisi' )
|
|
|
|
|
|
+ if(this.buildType == 'floor'){
|
|
|
|
+ viewer.setObjectLayers(mesh, 'siteModelMapUnvisi' ) //楼层默认在地图不显示,为了不会叠加透明度
|
|
}else{
|
|
}else{
|
|
viewer.setObjectLayers(mesh, 'sceneObjects' )
|
|
viewer.setObjectLayers(mesh, 'sceneObjects' )
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ //mesh.frustumCulled = false;
|
|
return mesh
|
|
return mesh
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
addMarker(o={} ){
|
|
addMarker(o={} ){
|
|
- if(this.type_=='floor')return; //楼层不需要marker
|
|
|
|
|
|
+ if(this.buildType=='floor')return; //楼层不需要marker
|
|
|
|
|
|
let marker = new Sprite({mat:this.getMarkerMaterial('default'), sizeInfo: markerSizeInfo, dontFixOrient: true, name:"building_marker"} )
|
|
let marker = new Sprite({mat:this.getMarkerMaterial('default'), sizeInfo: markerSizeInfo, dontFixOrient: true, name:"building_marker"} )
|
|
|
|
|
|
@@ -113,14 +336,30 @@ export class BuildingBox extends ctrlPolygon{//建筑实体,包括building, fl
|
|
o.marker = marker
|
|
o.marker = marker
|
|
super.addMarker(o)
|
|
super.addMarker(o)
|
|
|
|
|
|
|
|
+ if(!this.selected)viewer.updateVisible(marker,'select',false)
|
|
|
|
|
|
return marker
|
|
return marker
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
|
|
+ removeMarker(index){
|
|
|
|
+ super.removeMarker(index);
|
|
|
|
+ if(!this.isNew){
|
|
|
|
+ //重新添加midMarkers
|
|
|
|
+ this.midMarkers.forEach(e=>this.remove(e));
|
|
|
|
+ this.midMarkers = []
|
|
|
|
+ this.addMidMarkers()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.update();
|
|
|
|
+ if(this.points.length == 2 && this.box){//清除原先length>=3时候的
|
|
|
|
+ this.box.geometry = new THREE.Geometry();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
addMidMarker(index, point){
|
|
addMidMarker(index, point){
|
|
- if(this.type_=='floor')return; //楼层不需要marker
|
|
|
|
|
|
+ if(this.buildType=='floor')return; //楼层不需要marker
|
|
let marker = new Sprite({mat:this.getMarkerMaterial('midPrepare'), sizeInfo: markerSizeInfo, dontFixOrient: true, name:"building_midMarker"} )
|
|
let marker = new Sprite({mat:this.getMarkerMaterial('midPrepare'), sizeInfo: markerSizeInfo, dontFixOrient: true, name:"building_midMarker"} )
|
|
this.midMarkers = [...this.midMarkers.slice(0,index), marker, ...this.midMarkers.slice(index,this.midMarkers.length)]
|
|
this.midMarkers = [...this.midMarkers.slice(0,index), marker, ...this.midMarkers.slice(index,this.midMarkers.length)]
|
|
|
|
|
|
@@ -155,11 +394,14 @@ export class BuildingBox extends ctrlPolygon{//建筑实体,包括building, fl
|
|
}
|
|
}
|
|
this.add(marker)
|
|
this.add(marker)
|
|
this.updateMarker(marker, point)
|
|
this.updateMarker(marker, point)
|
|
|
|
+ if(!this.selected)viewer.updateVisible(marker,'select',false)
|
|
return marker
|
|
return marker
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
+
|
|
addMidMarkers(){//第一次画好所有marker后,一次性为线段增加中点marker
|
|
addMidMarkers(){//第一次画好所有marker后,一次性为线段增加中点marker
|
|
let length = this.points.length
|
|
let length = this.points.length
|
|
this.points.forEach((point,index)=>{
|
|
this.points.forEach((point,index)=>{
|
|
@@ -182,35 +424,78 @@ export class BuildingBox extends ctrlPolygon{//建筑实体,包括building, fl
|
|
this.updateMarker(nextMidMarker, nextMid)
|
|
this.updateMarker(nextMidMarker, nextMid)
|
|
}
|
|
}
|
|
|
|
|
|
- dispose(){
|
|
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ dispose(){//销毁geo、remove from parent
|
|
super.dispose()
|
|
super.dispose()
|
|
- this.box.geometry.dispose();
|
|
|
|
- this.lineMesh.geometry.dispose();
|
|
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+ this.box && this.box.geometry.dispose();
|
|
|
|
+ this.lineMesh && this.lineMesh.geometry.dispose();
|
|
|
|
+ this.holes.forEach(e=>e.dispose())
|
|
|
|
+ this.parentHoles.forEach(e=>e.dispose())
|
|
this.buildChildren.forEach(e=>e.dispose())
|
|
this.buildChildren.forEach(e=>e.dispose())
|
|
}
|
|
}
|
|
|
|
|
|
- update(ifUpdateMarkers, dontUpdateChildren){
|
|
|
|
- super.update(ifUpdateMarkers)
|
|
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ updateBox(){
|
|
|
|
+ if(!this.box)return
|
|
this.box.geometry.dispose()
|
|
this.box.geometry.dispose()
|
|
- let length = this.points.length
|
|
|
|
- if(length >= 3){
|
|
|
|
- this.box.geometry = MeshDraw.getExtrudeGeo(this.points, this.zMax-this.zMin)
|
|
|
|
|
|
+
|
|
|
|
+ if(this.points.length >= 3){
|
|
|
|
+ let holes = this.holes.concat(this.parentHoles)
|
|
|
|
+ let holesPoints = holes.filter(e=>e.points.length>2).map(e=>e.points)
|
|
|
|
+ this.box.geometry = MeshDraw.getExtrudeGeo(this.points, holesPoints, {
|
|
|
|
+ depth:this.zMax-this.zMin,
|
|
|
|
+ UVGenerator: new MetricUVGenerator()
|
|
|
|
+ })
|
|
this.box.position.z = this.zMin
|
|
this.box.position.z = this.zMin
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ update(options={}){
|
|
|
|
+ super.update(this.buildType != 'floor' && options.ifUpdateMarkers)
|
|
|
|
+ let length = this.points.length
|
|
|
|
|
|
- /* if(!this.isNew){
|
|
|
|
- this.midMarkers
|
|
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ {//确保一下一样
|
|
|
|
+ if(this.originHole){
|
|
|
|
+ this.points = this.originHole.points //完全等于building的hole
|
|
|
|
+ }
|
|
|
|
+ if(this.buildType == 'hole'){
|
|
|
|
+ this.zMin = this.buildParent.zMin;
|
|
|
|
+ this.zMax = this.buildParent.zMax;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- */
|
|
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if(!options.dontUpdateBox){
|
|
|
|
+ let boxOwner
|
|
|
|
+ if(this.buildType == 'hole'){
|
|
|
|
+ if(this.buildParent.buildType == 'building'){ //若是整栋大楼的hole,在每层都要更新下它的对应hole
|
|
|
|
+ this.buildParent.buildChildren.forEach(floor=>{
|
|
|
|
+ let holeAtFloor = floor.parentHoles.find(e=>e.originHole == this )
|
|
|
|
+ holeAtFloor && holeAtFloor.update() //刚开始创建时还没创建对应的 holeAtFloor会为null
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ boxOwner = this.buildParent
|
|
|
|
+ }else{
|
|
|
|
+ boxOwner = this
|
|
|
|
+ }
|
|
|
|
+ boxOwner.updateBox()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
|
|
{//update lines
|
|
{//update lines
|
|
- //let zMin = 0, zMax = 1
|
|
|
|
- let positions = [];
|
|
|
|
|
|
|
|
|
|
+ let positions = [];
|
|
|
|
+
|
|
this.points.forEach((point, index)=>{
|
|
this.points.forEach((point, index)=>{
|
|
|
|
|
|
//竖线:
|
|
//竖线:
|
|
@@ -218,41 +503,105 @@ export class BuildingBox extends ctrlPolygon{//建筑实体,包括building, fl
|
|
|
|
|
|
//横线
|
|
//横线
|
|
let nextPoint = this.points[(index+1)%length];
|
|
let nextPoint = this.points[(index+1)%length];
|
|
- if(point == nextPoint)return;//when length==1
|
|
|
|
|
|
+ if(!nextPoint)return;//when length==1
|
|
|
|
|
|
positions.push(point.clone().setZ(this.zMax), nextPoint.clone().setZ(this.zMax))//上横线
|
|
positions.push(point.clone().setZ(this.zMax), nextPoint.clone().setZ(this.zMax))//上横线
|
|
positions.push(point.clone().setZ(this.zMin), nextPoint.clone().setZ(this.zMin))//下横线
|
|
positions.push(point.clone().setZ(this.zMin), nextPoint.clone().setZ(this.zMin))//下横线
|
|
- })
|
|
|
|
|
|
+ })
|
|
|
|
|
|
LineDraw.moveLine(this.lineMesh,positions)
|
|
LineDraw.moveLine(this.lineMesh,positions)
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- if(this.type_ == 'building' && !dontUpdateChildren){
|
|
|
|
- this.buildChildren.forEach(e=>{
|
|
|
|
- e.points = this.points
|
|
|
|
- e.update()
|
|
|
|
- })
|
|
|
|
|
|
+ if(!options.dontUpdateChildren){
|
|
|
|
+ if(this.buildType == 'building' ){
|
|
|
|
+ this.buildChildren.forEach(floor=>{
|
|
|
|
+ floor.points = this.points
|
|
|
|
+ floor.update()
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+ {
|
|
|
|
+ let holes = this.holes.concat(this.parentHoles)
|
|
|
|
+ holes.forEach(hole=> {
|
|
|
|
+
|
|
|
|
+ hole.update({dontUpdateBox:true})//父级更新了box,hole就不需要更新box了
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
- removeMarker(index ){
|
|
|
|
- super.removeMarker(index)
|
|
|
|
- this.update();
|
|
|
|
- if(this.points.length == 2){//清除原先length>=3时候的
|
|
|
|
- this.box.geometry = new THREE.Geometry();
|
|
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ getArea(){//面积
|
|
|
|
+ //不排除hole
|
|
|
|
+ return Math.abs(math.getArea(this.points))
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ getVolume(){//体积
|
|
|
|
+ let {zMin , zMax} = this.getRealZ()
|
|
|
|
+ let height = zMax - zMin;
|
|
|
|
+ if(isNaN(height))height = 0
|
|
|
|
+ return this.getArea() * height
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ getRealZ(){//求真实高度时用到的
|
|
|
|
+ let zMin , zMax
|
|
|
|
+ if (this.buildType == 'building') {
|
|
|
|
+ //building的zMax和zMin一样的所以要算
|
|
|
|
+ let top = this.buildChildren[this.buildChildren.length - 1]
|
|
|
|
+ let btm = this.buildChildren[0]
|
|
|
|
+ if(btm) zMin = btm.zMin
|
|
|
|
+ if(top)zMax = top.zMax
|
|
|
|
+ }else if(this.buildType == 'hole'){
|
|
|
|
+ return this.buildParent.getRealZ()
|
|
|
|
+ }else{
|
|
|
|
+ zMin = this.zMin, zMax = this.zMax
|
|
}
|
|
}
|
|
- //this.dispatchEvent({type: 'marker_removed', measurement: this});
|
|
|
|
|
|
+ return {zMin,zMax}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+ /* getDrawZ(){ //画线和box时用到的z
|
|
|
|
+ let zMin , zMax
|
|
|
|
+ if(this.buildType == 'hole'){
|
|
|
|
+ if(this.buildParent.buildType == 'building' && atFloor){
|
|
|
|
+ zMin = atFloor.zMin, zMax = atFloor.zMax
|
|
|
|
+ }else{
|
|
|
|
+ zMin = this.buildParent.zMin, zMax = this.buildParent.zMax
|
|
|
|
+ }
|
|
|
|
+ }else{
|
|
|
|
+ zMin = this.zMin, zMax = this.zMax
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return {zMin, zMax}
|
|
|
|
+
|
|
|
|
+ } */
|
|
|
|
+
|
|
|
|
|
|
|
|
|
|
|
|
+ getBound(){
|
|
|
|
+ let bound = new THREE.Box3
|
|
|
|
+
|
|
|
|
+ let {zMin , zMax} = this.getRealZ()
|
|
|
|
+
|
|
|
|
+ this.points.forEach(p=>{
|
|
|
|
+ bound.expandByPoint(p.clone().setZ(zMin))
|
|
|
|
+ bound.expandByPoint(p.clone().setZ(zMax))
|
|
|
|
+ })
|
|
|
|
+ return bound
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
getMarkerMaterial(type) {
|
|
getMarkerMaterial(type) {
|
|
if(!markerMats){
|
|
if(!markerMats){
|
|
markerMats = {
|
|
markerMats = {
|
|
@@ -302,50 +651,134 @@ export class BuildingBox extends ctrlPolygon{//建筑实体,包括building, fl
|
|
|
|
|
|
|
|
|
|
select(){
|
|
select(){
|
|
|
|
+ //最多再显示一层子级的线,如building不会显示room中的hole的线
|
|
|
|
+ //box是一直显示的,但会切换材质
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ 选中 box 线
|
|
|
|
+
|
|
|
|
+ building 自己(底盘)选中 自己, floor不带hole
|
|
|
|
+
|
|
|
|
+ floor 自己选中 自己, room不带hole
|
|
|
|
+
|
|
|
|
+ room 自己选中 自己
|
|
|
|
+
|
|
|
|
+ */ //注:自己的就代表定包括hole,如果有parentHoles的也(building上的hole的对应)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
if(this.selected)return
|
|
if(this.selected)return
|
|
|
|
|
|
|
|
+ if(this.box){
|
|
|
|
+ this.box.material = this.mats.boxSelected;
|
|
|
|
+ }
|
|
|
|
|
|
- if(this.type_ == 'building'){
|
|
|
|
|
|
+ if(this.buildType == 'building'|| this.buildType == 'floor'){
|
|
this.buildChildren.forEach(e=>{
|
|
this.buildChildren.forEach(e=>{
|
|
e.lineMesh.visible = true
|
|
e.lineMesh.visible = true
|
|
})
|
|
})
|
|
-
|
|
|
|
- }else if(this.type_ == 'floor'){
|
|
|
|
-
|
|
|
|
- this.box.material = faceMats.floorSelect
|
|
|
|
- viewer.setObjectLayers(this.box, 'sceneObjects' )
|
|
|
|
-
|
|
|
|
- }else if(this.type_ == 'room'){
|
|
|
|
- this.box.material = faceMats.roomSelect
|
|
|
|
|
|
+
|
|
|
|
+ if(this.buildType == 'floor'){
|
|
|
|
+ viewer.setObjectLayers(this.box, 'sceneObjects' )
|
|
|
|
+ viewer.setObjectLayers(this.buildParent.box, 'siteModelMapUnvisi' ) //当选中floor或room时,building在地图不可见
|
|
|
|
+ }
|
|
|
|
+ }else if(this.buildType == 'room'){
|
|
|
|
+ viewer.setObjectLayers(this.buildParent.box, 'sceneObjects' )
|
|
|
|
+ viewer.setObjectLayers(this.buildParent.buildParent.box, 'siteModelMapUnvisi' )
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
this.lineMesh.visible = true
|
|
this.lineMesh.visible = true
|
|
this.markers && this.markers.forEach(e=>viewer.updateVisible(e,'select',true) )
|
|
this.markers && this.markers.forEach(e=>viewer.updateVisible(e,'select',true) )
|
|
this.midMarkers && this.midMarkers.forEach(e=>e.visible = true)
|
|
this.midMarkers && this.midMarkers.forEach(e=>e.visible = true)
|
|
|
|
|
|
- this.selected = true
|
|
|
|
|
|
+ let holes = this.holes.concat(this.parentHoles)
|
|
|
|
+ holes.forEach(e=>e.select())
|
|
|
|
|
|
|
|
+ this.selected = true
|
|
|
|
+ this.dispatchEvent({type:'select'})
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
unselect(){
|
|
unselect(){
|
|
|
|
+ if(this.box){
|
|
|
|
+ this.box.material = this.mats.boxDefault;
|
|
|
|
+ }
|
|
|
|
|
|
- if(this.type_ == 'building'){
|
|
|
|
|
|
+ if(this.buildType == 'building' || this.buildType == 'floor'){
|
|
this.buildChildren.forEach(e=>{
|
|
this.buildChildren.forEach(e=>{
|
|
e.lineMesh.visible = false
|
|
e.lineMesh.visible = false
|
|
})
|
|
})
|
|
- }else if(this.type_ == 'floor'){
|
|
|
|
- viewer.setObjectLayers(this.box, 'siteModelMapUnvisi' )
|
|
|
|
- this.box.material = faceMats.floor
|
|
|
|
- }else if(this.type_ == 'room'){
|
|
|
|
- this.box.material = faceMats.room
|
|
|
|
|
|
+
|
|
|
|
+ if(this.buildType == 'floor'){
|
|
|
|
+ viewer.setObjectLayers(this.box, 'siteModelMapUnvisi' )
|
|
|
|
+ viewer.setObjectLayers(this.buildParent.box, 'sceneObjects' )
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }else if(this.buildType == 'room'){
|
|
|
|
+ viewer.setObjectLayers(this.buildParent.box, 'siteModelMapUnvisi' )
|
|
|
|
+ viewer.setObjectLayers(this.buildParent.buildParent.box, 'sceneObjects' )
|
|
}
|
|
}
|
|
|
|
+
|
|
this.lineMesh.visible = false
|
|
this.lineMesh.visible = false
|
|
this.markers && this.markers.forEach(e=>viewer.updateVisible(e,'select',false) )
|
|
this.markers && this.markers.forEach(e=>viewer.updateVisible(e,'select',false) )
|
|
this.midMarkers && this.midMarkers.forEach(e=>e.visible = false)
|
|
this.midMarkers && this.midMarkers.forEach(e=>e.visible = false)
|
|
|
|
|
|
|
|
+ let holes = this.holes.concat(this.parentHoles)
|
|
|
|
+ holes.forEach(e=>e.unselect())
|
|
|
|
+
|
|
this.selected = false
|
|
this.selected = false
|
|
|
|
+ this.dispatchEvent({type:'unselect'})
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ ifContainsPoint(position){//看它所定义的空间是否包含某个坐标(要排除hole)
|
|
|
|
|
|
|
|
+ let {zMin , zMax} = this.getRealZ()
|
|
|
|
+ if(position.z < zMin || position.z > zMax ) return
|
|
|
|
+
|
|
|
|
+ let holes = this.holes.concat(this.parentHoles)
|
|
|
|
+ let holesPoints = holes.filter(e=>e!=this && e.points.length>2).map(e=>e.points)
|
|
|
|
+ let inShape = math.isPointInArea(this.points, holesPoints, position)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ return !!inShape
|
|
|
|
+ }
|
|
|
|
|
|
-}
|
|
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+class MetricUVGenerator{
|
|
|
|
+ constructor(){
|
|
|
|
+ this.a = new THREE.Vector3,
|
|
|
|
+ this.b = new THREE.Vector3,
|
|
|
|
+ this.c = new THREE.Vector3,
|
|
|
|
+ this.d = new THREE.Vector3
|
|
|
|
+ }
|
|
|
|
+ generateTopUV(t, e, n, r, o) {
|
|
|
|
+ return [new THREE.Vector2(e[3 * n],e[3 * n + 1]), new THREE.Vector2(e[3 * r],e[3 * r + 1]), new THREE.Vector2(e[3 * o],e[3 * o + 1])]
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ generateSideWallUV(t, e, n, r, o, a) {
|
|
|
|
+ var s = e;
|
|
|
|
+ this.a.set(s[3 * n], s[3 * n + 1], s[3 * n + 2]),
|
|
|
|
+ this.b.set(s[3 * r], s[3 * r + 1], s[3 * r + 2]),
|
|
|
|
+ this.c.set(s[3 * o], s[3 * o + 1], s[3 * o + 2]),
|
|
|
|
+ this.d.set(s[3 * a], s[3 * a + 1], s[3 * a + 2]);
|
|
|
|
+ var c = this.a.x !== this.b.x
|
|
|
|
+ , l = c ? this.b : this.d
|
|
|
|
+ , u = this.a.distanceTo(l)
|
|
|
|
+ , d = l.distanceTo(this.c);
|
|
|
|
+ return [new THREE.Vector2(this.a.x,0), c ? new THREE.Vector2(this.a.x + u,0) : new THREE.Vector2(this.a.x,d), new THREE.Vector2(this.a.x + u,d), c ? new THREE.Vector2(this.a.x,d) : new THREE.Vector2(this.a.x + u,0)]
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|