123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 |
- import * as THREE from "../../../../libs/three.js/build/three.module.js";
- import {BoxVolume} from '../../../utils/VolumeNew.js'
- import { ClipTask, ClipMethod} from "../../../defines.js"
- import {mapClipBox} from '../../objects/tool/mapClipBox.js'
- import Common from '../../utils/Common.js'
- import math from '../../utils/math.js'
- import {Images360} from '../panos/Images360.js'
- const defaultBoxWidth = 16; //navvis: 10
- //navvis position: si {x: 0, y: 0, z: 0}
-
- var Clip = {
- bus : new THREE.EventDispatcher,
- selectedDatasets : [],
- changeCallback(force){
- viewer.controls.setTarget(this.box.position)//绕其旋转
-
- if(Potree.settings.isOfficial){
- Common.intervalTool.isWaiting('clipSelectedDatasets', ()=>{ //延时update,防止卡顿
- let pointclouds = this.getIntersectPointcloud()
- if(force || Common.getDifferenceSet(pointclouds,this.selectedDatasets).length){
- this.selectedDatasets = pointclouds
- //console.error('clipSelectedDatasets',selectedDatasets)
- this.bus.dispatchEvent({type:'updateSelectedDatasets', selectedDatasets:pointclouds.map(e=>e.dataset_id) })
- force = false
- return true
- }
- }, 300)
- }
- },
- enter:function(){
- this.previousView = {
- position: viewer.images360.position,
- target: viewer.scene.view.getPivot(),
- displayMode : Potree.settings.displayMode,
- //---
- ifShowMarker : Potree.settings.ifShowMarker,
-
- }
- let pointcloud = this.getPointcloud()
- let bound = pointcloud.bound //只选取其中一个数据集的bound,而非整体,是因为担心两个数据集中间有空隙,于是刚好落在没有点云的地方。
- let boundSize = bound.getSize(new THREE.Vector3())
- let target = this.getTarget(bound.getCenter(new THREE.Vector3())); //navvis的位置xy是用相机位置 this.ViewService.mainView.getCamera().position 我觉得也可以用第一个漫游点的,或者最接近bound中心的漫游点
- let scale = new THREE.Vector3(defaultBoxWidth,defaultBoxWidth, boundSize.z)//z和navvis一样
-
- let eyeDir = viewer.scene.view.direction.clone().setZ(0/* -boundSize.z/3 */).multiplyScalar(-defaultBoxWidth) //为了使所在楼层不变,不修改z
- //let eyeDir = scale.clone().setZ(boundSize.z/3).multiplyScalar(1.3)
- let position = new THREE.Vector3().addVectors(target, eyeDir)
-
- Potree.settings.displayMode = 'showPointCloud'
- viewer.setView({
- position ,
- target,
- duration:300,
- callback:function(){
- }
- })
- //viewer.setControls(viewer.orbitControls);
- viewer.setLimitFar(false)
- //viewer.setClipState(false) //暂时关闭旧的clipping
-
-
- {
- this.box = new BoxVolume({
- clip:true
- })
- this.box.clipTask = ClipTask['SHOW_INSIDE_Big' /* "SHOW_INSIDE" */]
- this.box.showBox = false
- this.box.name = "ClipBox";
- this.box.position.copy(target)
- this.box.scale.copy(scale)
- //带动mapBox
- this.box.addEventListener('position_changed',e=>{
- this.mapBox.center.setX(this.box.position.x)
- this.mapBox.center.setY(this.box.position.y)
- this.mapBox.updatePoints()
- this.changeCallback()
- })
- this.box.addEventListener('scale_changed',e=>{
- var scale = this.box.scale
- this.mapBox.updatePoints(scale)
- this.changeCallback()
- })
- this.box.addEventListener('orientation_changed',e=>{
- this.mapBox.angle = this.box.rotation.z
- this.mapBox.rotateBar.rotation.z = this.mapBox.angle
- this.mapBox.updatePoints()
- this.changeCallback()
- })
- viewer.scene.addVolume(this.box);
-
- }
-
- {//map
- let boxRotateBack = ()=>{//不知道是不是这么写。 因为可能z的旋转不一定都在z
- this.box.rotation.x = 0;
- this.box.rotation.y = 0;
- }
- this.mapBox = new mapClipBox(target, scale)
- viewer.mapViewer.scene.add(this.mapBox)
- //带动box
- this.mapBox.addEventListener('repos',e=>{
- this.box.position.setX(this.mapBox.center.x)
- this.box.position.setY(this.mapBox.center.y)
- boxRotateBack()
- this.changeCallback()
- })
- this.mapBox.addEventListener('dragChange',e=>{
- var scale = this.mapBox.getScale()
- this.box.scale.setX(scale.x)
- this.box.scale.setY(scale.y)
- this.box.position.setX(this.mapBox.center.x)
- this.box.position.setY(this.mapBox.center.y)
- boxRotateBack()
- this.changeCallback()
- })
- this.mapBox.addEventListener('rotate',e=>{
- this.box.rotation.z = this.mapBox.angle
- boxRotateBack()
- this.changeCallback()
- })
- }
-
-
-
-
- {
- //viewer.setClipTask(ClipTask["SHOW_INSIDE"])
-
- }
-
- Potree.settings.unableNavigate = true
- Potree.settings.ifShowMarker = false
- viewer.updateVisible(viewer.measuringTool.scene, 'clipModel', false)
- //viewer.updateVisible(viewer.mapViewer.cursor, 'clipModel', false)//隐藏地图游标
- viewer.inputHandler.toggleSelection(this.box);
- viewer.inputHandler.fixSelection = true
- viewer.transformationTool.frame.material.color.set(Potree.config.clip.color)//navvis 15899953
- viewer.setPointStandardMat(true)
-
- {
- let mapVisi = false
- this.events = {
- flyToPos : (e)=>{
- let dis = 2
- let target = e.position
- //position = new THREE.Vector3().subVectors(target, this.scene.view.direction)
-
- //永远朝向框的中心
- /* let dir = new THREE.Vector3().subVectors(this.box.position, e.position).normalize()
- position = new THREE.Vector3().subVectors(target, dir) */
-
-
- target = this.box.position
- position = e.position
- //为了方便缩放操作,直接使用box中心作为target
-
-
- let duration = 1000
- viewer.scene.view.setView({position, duration, target})
-
- },
- mapVisiChange(e){
- mapVisi = e.visible
- let delay = 100 //因resize了camera需要时间更新projectionMatrix
- setTimeout(()=>{
- let boundingBox = Clip.box.boundingBox.clone().applyMatrix4(Clip.box.matrixWorld)
- if(mapVisi){//切换地图
- if(Clip.switchMapCount == 0 || !Potree.Utils.isInsideFrustum(boundingBox, viewer.mapViewer.camera)){
- let size = boundingBox.getSize(new THREE.Vector3)
- let margin = viewer.mainViewport.resolution.clone().multiplyScalar(0.3)
- viewer.mapViewer.moveTo(Clip.box.position, size, 100, margin)
- }
- Clip.switchMapCount++
- //关于究竟是focus box还是dataset有点纠结,又或是两个的union。box和数据集可能离得很远,且无法确定当前想选择的数据集,且数据集可能无floorplan, 即使有可能也不展示……
- }else{//切换3d
- if(!Potree.Utils.isInsideFrustum(boundingBox, viewer.scene.getActiveCamera())){//屏幕上没有box的话
- viewer.focusOnObject({boundingBox}, 'boundingBox', 100 )
- }
- }
- },delay)
-
- }
- }
- this.switchMapCount = 0
- this.bus.addEventListener('flyToPos',this.events.flyToPos)
- viewer.mapViewer.addEventListener('forceVisible',this.events.mapVisiChange)
- }
- this.editing = true
-
- setTimeout(()=>{this.changeCallback(true)},1)
- },
-
- leave:function(){
- viewer.inputHandler.fixSelection = false
- viewer.scene.removeVolume(this.box);
-
- this.mapBox.dispose()
- //viewer.setControls(viewer.fpControls);
-
- Potree.settings.unableNavigate = false
- Potree.settings.ifShowMarker = this.previousView.ifShowMarker
- viewer.updateVisible(viewer.measuringTool.scene, 'clipModel', true)
- //viewer.updateVisible(viewer.mapViewer.cursor, 'clipModel', true)
- viewer.setView(this.previousView)
- viewer.setLimitFar(true)
- viewer.setPointStandardMat(false)
- //viewer.setClipState(true)
- viewer.controls.setTarget(null)
- {
- this.bus.removeEventListener('flyToPos',this.events.flyToPos)
- viewer.mapViewer.removeEventListener('forceVisible',this.events.mapVisiChange)
-
- this.events = null
- }
- this.editing = false
- },
-
- getPointcloud:function(){ //找一个离当前最近的点云,且最好有漫游点
- let pointclouds = viewer.scene.pointclouds.filter(e=>e.panos.length>0)
- if(pointclouds.length == 0)pointclouds = viewer.scene.pointclouds;
- let result = Common.sortByScore(pointclouds,[],[e=>{
- let center = e.bound.getCenter(new THREE.Vector3)
- let size = e.bound.getSize(new THREE.Vector3).length() / 2
- let posToCenter = viewer.images360.position.distanceTo(center)
- return size / posToCenter
- }])
-
- return result[0].item
- },
-
- getTarget:function(boundCenter){//box位置。要找一个有点云的地方。方案1相机位置, 方案2接近相机的漫游点, 方案3接近中心的漫游点。选择方案2,因最大概率有点云
- var target = new THREE.Vector3()
- var cameraPos = viewer.images360.position;
- var pano = Common.find(viewer.images360.panos , [], [Images360.sortFunctions.floorDisSquaredToPoint(cameraPos)]);
- if(pano){
- target.copy(pano.position)
- target.setZ(boundCenter.z)
- }else{
- target.copy(boundCenter)
- }
-
- return target
- },
- /* switchMap:function(state){
-
-
- }, */
-
- download:function( ){
-
- if(this.getIntersectPointcloud().length == 0){
- return null
- }
-
-
- var visiPointclouds = viewer.scene.pointclouds.filter(e=> viewer.getObjVisiByReason(e, 'datasetSelection'))
- let data = {
- transformation_matrix: visiPointclouds.map((cloud)=>{
- let data = {
- id: cloud.dataset_id,
- matrix : this.getTransformationMatrix(cloud).elements, //剪裁大框
- VisiMatrixes: cloud.material.clipBoxes_in.map(e=>this.getTransformationMatrix(cloud, e.inverse).elements), //若干个可见型小框(虽然现在用不到了,因为普通界面不展示这些剪裁区域)
- UnVisiMatrixes: cloud.material.clipBoxes_out.map(e=>this.getTransformationMatrix(cloud, e.inverse).elements), //若干个不可见型小框
- modelMatrix:(new THREE.Matrix4).copy(cloud.transformMatrix).transpose().elements
- }
- return data
- }) ,
- aabb: "b-0.5 -0.5 -0.5 0.5 0.5 0.5" //剪裁空间( 所有点在乘上这个矩阵后, 还能落在 1 * 1 * 1的box内的点就是所裁剪的
-
- }
-
- return data
- //https://testlaser.4dkankan.com/indoor/t-ia44BhY/api/pointcloud/crop
- },
-
-
-
- downloadNoCrop(){//不剪裁 下载整个点云
-
- var visiPointclouds = viewer.scene.pointclouds.filter(e=> viewer.getObjVisiByReason(e, 'datasetSelection'))
- let data = {
- transformation_matrix: visiPointclouds.map((cloud)=>{
- let data = {
- id: cloud.dataset_id,
- matrix : new THREE.Matrix4().elements, //固定值
- modelMatrix:(new THREE.Matrix4).copy(cloud.transformMatrix).transpose().elements
- }
- return data
- }) ,
- aabb: "b-12742000 -12742000 -12742000 12742000 12742000 12742000" //固定剪裁空间
-
- }
- console.log(data)
- return data
-
-
-
- },
-
-
- getTransformationMatrix:function(pointcloud, invMatrix) {//剪裁矩阵
- var invMatrix = invMatrix || this.box.matrixWorld.clone().invert()
- return (new THREE.Matrix4).multiplyMatrices(invMatrix, pointcloud.transformMatrix).transpose()
- },
- /* getIntersectPointcloud(){
- var boxBound = new THREE.Box3(
- new THREE.Vector3(-0.5,-0.5,-0.5), new THREE.Vector3(0.5,0.5,0.5),
- ).applyMatrix4(this.box.matrixWorld) //large boundingbox
-
- let boxMatrixInverse = new THREE.Matrix4().copy(this.box.matrixWorld).invert();
- let boxPoints = [
- new THREE.Vector3(boxBound.min.x, boxBound.min.y,0),
- new THREE.Vector3(boxBound.max.x, boxBound.min.y,0),
- new THREE.Vector3(boxBound.max.x, boxBound.max.y,0),
- new THREE.Vector3(boxBound.min.x, boxBound.max.y,0)
- ]
- var intersect = (pointcloud)=>{
-
- if(!pointcloud.bound.intersectsBox(boxBound))return false
- //判断box和点云的tight bound是否相交(因为box可以任意旋转,且实在找不到三维中的立方体相交的函数,所以直接用boxBound)
- var points = pointcloud.getUnrotBoundPoint('all')
- let rings = math.getPolygonsMixedRings([points.slice(0,4), boxPoints] , true)
- //console.log(pointcloud.dataset_id, pointcloud.name, rings.length)
- if(rings.length > 1 )return false
- {//再用frustum和数据集的sphere相交试试,能排除一些错误
- let a = Potree.Utils.isIntersectBox(points, this.box.matrixWorld)
- if(!a){
- console.log('没能经过isInsideBox测试')
- }
- return a
- }
- return true
-
- }
- return viewer.scene.pointclouds.filter(e=>intersect(e))
-
- } */
-
-
- getIntersectPointcloud(){
-
- var intersect = (pointcloud)=>{
- if(pointcloud.intersectBox(this.box.matrixWorld))return true
- }
- return viewer.scene.pointclouds.filter(e=>intersect(e))
- }
-
-
-
- }
- export {Clip}
- /*
- 裁剪点云时,2D界面显示全部平面图,按楼层切换显示。
- */
|