import * as THREE from "../libs/three.js/build/three.module.js"; import {settings, config} from './settings.js' import math from './utils/math.js' import browser from './utils/browser.js' import './extensions/three.shim.js' import {Utils} from "./utils.js" var start = function(dom, mapDom, number, fileServer, webSite){ //t-Zvd3w0m /* { let obj = JSON.parse(localStorage.getItem('setting')) for(let i in obj){ console.log(i + ': ' + obj[i]) } } */ Potree.settings.number = number || 't-o5YMR13'// 't-iksBApb'// 写在viewer前 Potree.fileServer = fileServer webSite && (Potree.settings.webSite = webSite) let viewer = new Potree.Viewer(dom , mapDom); let Alignment = viewer.modules.Alignment //let pointDensity = config.pointDensity.middle viewer.setEDLEnabled(false); viewer.setFOV(config.view.fov); //viewer.setPointBudget(pointDensity.pointBudget); viewer.loadSettingsFromURL(); if(!Potree.settings.isOfficial){ viewer.loadGUI(() => { viewer.setLanguage('en'); //$("#menu_appearance").next().show(); $("#menu_tools").next().show(); $("#menu_scene").next().show(); $("#siteModel").show(); //$("#alignment").show(); viewer.toggleSidebar(); }); Potree.settings.sizeFitToLevel = true//当type为衰减模式时自动根据level调节大小。每长一级,大小就除以2 } Potree.loadDatasetsCallback = function(data, ifReload){ if(!data || data.length == 0)return console.error('getDataSet加载的数据为空') Potree.datasetData = data viewer.transform = null var datasetLength = data.length var pointcloudLoaded = 0 var panosLoaded = 0 var pointcloudLoadDone = function(){//点云cloud.js加载完毕后 viewer.updateModelBound() let {boundSize, center} = viewer.bound Potree.Log(`中心点: ${math.toPrecision(center.toArray(),2)}, boundSize: ${math.toPrecision(boundSize.toArray(),2)} ` , null, 12) if(!Potree.settings.isOfficial){ Potree.loadMapEntity('all') //加载floorplan } if(!ifReload){ viewer.scene.view.setView({ position: center.clone().add(new THREE.Vector3(10,5,10)), target: center }) viewer.dispatchEvent({type:'loadPointCloudDone'}) if(!Potree.settings.UserPointDensity){ Potree.settings.UserPointDensity = 'high'//'middle' } Potree.Log('loadPointCloudDone 点云加载完毕', null, 10) } } var panosLoadDone = function(){ viewer.images360.loadDone() viewer.scene.add360Images(viewer.images360); viewer.mapViewer.addListener(viewer.images360) {//初始位置 var urlFirstView = false var panoId = browser.urlHasValue('pano',true); if(panoId !== ''){ var pos var pano = viewer.images360.panos.find(e=>e.id==panoId); if(pano){ viewer.images360.focusPano({ pano, duration:0, callback:()=>{/* Potree.settings.displayMode = 'showPanos' */} }) } }else{//考虑到多数据集距离很远,或者像隧道那种场景,要使视野范围内一定能看到点云,最好初始点设置在漫游点上 let {boundSize, center} = viewer.bound let pano = viewer.images360.findNearestPano(center) /* pano && viewer.scene.view.setView({ position: pano.position.clone().add(new THREE.Vector3(10,10,10)), target: pano.position }) */ pano && viewer.images360.flyToPano({ pano, duration:0, target : viewer.images360.bound.center }) } } viewer.addVideo()//addFire() console.log('allLoaded') viewer.dispatchEvent('allLoaded') } var transformPointcloud = (pointcloud, dataset)=>{ var locationLonLat = dataset.location.slice(0,2) //当只有一个dataset时,无论如何transform 点云和漫游点都能对应上。 var location = viewer.transform.lonlatToLocal.forward(locationLonLat) //transform.inverse() //初始化位置 viewer.sidebar && viewer.sidebar.addAlignmentButton(pointcloud) //dataset.orientation = 0 Alignment.rotate(pointcloud, null, dataset.orientation) Alignment.translate(pointcloud, new THREE.Vector3(location[0], location[1], dataset.location[2])) pointcloud.updateMatrixWorld() Potree.Log(`点云${pointcloud.dataset_id}旋转值:${pointcloud.orientationUser}, 位置${math.toPrecision(pointcloud.translateUser.toArray(),3)}, 经纬度 ${locationLonLat}, spacing ${pointcloud.material.spacing}`, null, 17 ) //------------------- //viewer.mapView.showSources(false); } if(!Potree.settings.originDatasetId)Potree.settings.originDatasetId = data[0].id var originDataset = data.find(e=>e.id == Potree.settings.originDatasetId) {//拿初始数据集作为基准。它的位置是000 var locationLonLat = originDataset.location.slice(0,2) proj4.defs("NAVVIS:TMERC", "+proj=tmerc +ellps=WGS84 +lon_0=" + locationLonLat[0].toPrecision(15) + " +lat_0=" + locationLonLat[1].toPrecision(15)); proj4.defs("WGS84", "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"); let transform1 = proj4("WGS84", "NAVVIS:TMERC"); //这个ok TMERC是展开的平面投影 let transform2 = proj4("+proj=tmerc +lat_0=0 +lon_0=123 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs;"); viewer.transform = { lonlatToLocal : transform1, lonlatTo4550 : transform2 // 转大地坐标EPSG:4550 } viewer.mapViewer && viewer.mapViewer.mapLayer.maps[0].updateProjection() } data.forEach((dataset,index)=>{ if(!ifReload){ var datasetCode = dataset.sceneCode || dataset.name //对应4dkk的场景码 var cloudPath = `${Potree.settings.urls.prefix}/${Potree.settings.webSite}/${datasetCode}/data/${datasetCode}/webcloud/cloud.js` var timeStamp = dataset.createTime ? dataset.createTime.replace(/[^0-9]/ig,'') : ''; //每重算一次后缀随createTime更新一次 //console.warn(dataset.name, 'timeStamp', timeStamp) Potree.loadPointCloud(cloudPath, dataset.name ,datasetCode, timeStamp, e => { let scene = viewer.scene; let pointcloud = e.pointcloud; let config = Potree.config.material let material = pointcloud.material; pointcloud.hasDepthTex = Potree.settings.hasDepthTex && (!!dataset.has_depth || Potree.settings.isLocalhost && Potree.settings.number == 'SS-t-7DUfWAUZ3V') //test material.minSize = config.minSize material.maxSize = config.maxSize material.pointSizeType = config.pointSizeType //Potree.PointSizeType[config.pointSizeType]//Potree.PointSizeType.ADAPTIVE;//FIXED pointcloud.changePointSize(config.realPointSize) //material.size = config.pointSize; pointcloud.changePointOpacity(1) material.shape = Potree.PointShape.SQUARE; pointcloud.color = pointcloud.material.color = dataset.color pointcloud.dataset_id = dataset.id;//供漫游点找到属于的dataset点云 pointcloud.timeStamp = timeStamp transformPointcloud(pointcloud,dataset) scene.addPointCloud(pointcloud); pointcloudLoaded ++; if(pointcloudLoaded == datasetLength)pointcloudLoadDone() Potree.loadPanos(dataset.id, (data) => { //console.log('loadPanos',dataset.sceneCode, dataset.id, data) viewer.images360.addPanoData(data, dataset.id ) panosLoaded ++; if(panosLoaded == datasetLength){ panosLoadDone() } }) }) }else{ let pointcloud = viewer.scene.pointclouds.find(p => p.dataset_id == dataset.id) if(!pointcloud){ Potree.Log('数据集id变了,自动使用第一个','#500') pointcloud = viewer.scene.pointclouds[0] } //先归零 Alignment.translate(pointcloud, pointcloud.translateUser.clone().negate()) Alignment.rotate(pointcloud, null, - pointcloud.orientationUser) transformPointcloud(pointcloud, dataset) } }) if(ifReload){ //loadDone() } } Potree.loadDatasets(Potree.loadDatasetsCallback) window.testTransform = function(locationLonLat, location1, location2){ proj4.defs("NAVVIS:test", "+proj=tmerc +ellps=WGS84 +lon_0=" + locationLonLat[0].toPrecision(15) + " +lat_0=" + locationLonLat[1].toPrecision(15)); let transform = proj4("WGS84", "NAVVIS:test"); //这个ok navvis里也是这两种转换 见proj4Factory if(location1){//经纬度 return transform.forward(location1) }else{ return transform.inverse(location2) } } window.THREE = THREE window.buttonFunction = function(){ viewer.scene.pointclouds.forEach(e=>e.predictNodeMaxLevel()) /* viewer.startScreenshot({type:'measure', measurement:viewer.scene.measurements[0]}) viewer.modules.RouteGuider.routeStart = new THREE.Vector3(0,0,-1.3) viewer.modules.RouteGuider.routeEnd = new THREE.Vector3(-10,0,-1.3) */ } if(Potree.settings.isLocalhost){ let before = {} viewer.inputHandler.addEventListener('keydown',e=>{ //测试的代码 if(e.event.key == 't'){ viewer.images360.cube.visible = true viewer.images360.cube.material.wireframe = true }else if(e.event.key == 'y'){ viewer.images360.cube.material.wireframe = false viewer.images360.cube.visible = Potree.settings.displayMode == 'showPanos' } }) } } //======================================================================= /* 漫游点编辑 */ //======================================================================= var panoEditStart = function(dom, number, fileServer, webSite){ Potree.settings.editType = 'pano' Potree.settings.number = number Potree.settings.unableNavigate = true let viewer = new Potree.Viewer(dom); let Alignment = viewer.modules.Alignment viewer.setEDLEnabled(false); viewer.setFOV(config.view.fov); viewer.loadSettingsFromURL(); let datasetLoaded = 0; if(!Potree.settings.isOfficial){ viewer.loadGUI(() => { viewer.setLanguage('en'); $("#menu_tools").next().show(); $("#panos").show(); $("#alignment").show(); viewer.toggleSidebar(); }); Potree.settings.sizeFitToLevel = true } var pointcloudLoadDone = function( ){//所有点云cloud.js加载完毕后 viewer.scene.pointclouds.forEach(c=>{ transformPointcloud(c) }) viewer.images360.loadDone() viewer.scene.add360Images(viewer.images360); viewer.updateModelBound() let {boundSize, center} = viewer.bound Potree.Log(`中心点: ${math.toPrecision(center.toArray(),2)}, boundSize: ${math.toPrecision(boundSize.toArray(),2)} ` , null, 12) viewer.scene.view.setView({ position: center.clone().add(new THREE.Vector3(10,5,10)), target: center }) viewer.dispatchEvent({type:'loadPointCloudDone'}) if(!Potree.settings.UserPointDensity){ Potree.settings.UserPointDensity = 'panoEdit'//'middle' } Potree.Log('loadPointCloudDone 点云加载完毕', null, 10) viewer.dispatchEvent('allLoaded'); } var transformPointcloud = (pointcloud )=>{ //初始化位置 viewer.sidebar && viewer.sidebar.addAlignmentButton(pointcloud) let orientation = pointcloud.panos[0].dataRotation.z let location = pointcloud.panos[0].dataPosition.clone().negate() Alignment.rotate(pointcloud, null, orientation ) Alignment.translate(pointcloud, location ) pointcloud.updateMatrixWorld() } let loadPanosDone = Potree.loadPanosDone = (datasetId, panoData)=>{ //一个数据集获取到它的panos后 Potree.settings.datasetsPanos[datasetId] = {panoData, panos:[]} console.log('panoData', datasetId, panoData) let panoCount = panoData.length let pointcloudLoaded = 0 let datasetsCount = Object.keys(Potree.settings.datasetsPanos).length panoData.forEach((pano, index)=>{ //let cloudPath = `${Potree.scriptPath}/data/panoEdit/uuidcloud/${pano.uuid}/cloud.js` let cloudPath = `https://laser-oss.4dkankan.com/testdata/${Potree.settings.number}/data/bundle_${Potree.settings.number}/building/uuidcloud/${pano.uuid}/cloud.js` let name = datasetId + '-'+pano.uuid let timeStamp = 0 pano.index = index //注意:index不等于uuid,因为有的uuid缺失。但是visibles中存的是下标! Potree.loadPointCloud(cloudPath, name , name, timeStamp, e => { //开始加载点云 let scene = viewer.scene; let pointcloud = e.pointcloud; let config = Potree.config.material let material = pointcloud.material; material.minSize = config.minSize material.maxSize = config.maxSize material.pointSizeType = /* 'ADAPTIVE'// */config.pointSizeType //Potree.PointSizeType[config.pointSizeType]//Potree.PointSizeType.ADAPTIVE;//FIXED pointcloud.changePointSize( 0.2 /* config.realPointSize */ ) //material.size = config.pointSize; pointcloud.changePointOpacity(1) material.shape = Potree.PointShape.SQUARE; pointcloud.color = config.pointColor pointcloud.dataset_id = datasetId; //多个点云指向一个datasetId pointcloud.panoUuid = pano.uuid pointcloud.timeStamp = timeStamp //transformPointcloud(pointcloud, pano) scene.addPointCloud(pointcloud); pointcloudLoaded ++; if(pointcloudLoaded == panoCount ){ datasetLoaded ++ viewer.images360.addPanoData(panoData , datasetId ) if(datasetLoaded == datasetsCount){ pointcloudLoadDone() } } }) }) } if(!Potree.settings.isOfficial){ Potree.settings.datasetsPano = {'testDataset':null} Potree.loadPanosInfo( data=>{loadPanosDone('testDataset', data.sweepLocations)} ) } } /* var changeLog = ()=>{ //如果移动端加了test反而出不来bug的话,用这个 var textarea = document.createElement('textarea'); textarea.id = "consoleLog"; textarea.style.width = '160px'; textarea.style.height = '200px' textarea.style.position = 'fixed' textarea.style.right = 0 textarea.style.bottom = '0' textarea.style['z-index'] = 9999; textarea.style.color = 'black'; textarea.style.opacity = 0.9; textarea.style['font-size'] = '12px'; textarea.style['backgroundColor'] = '#ffffff' document.getElementsByTagName("body")[0].appendChild(textarea); var list = ["log", "error", "warn", "debug", "info", "time", "timeEnd"] var exchange = function (o) { console["old" + o] = console[o]; console[o] = function () { var args = Array.from(arguments) console["old" + o].apply(this, arguments) var t = document.getElementById("consoleLog").innerHTML; var str = '' args.forEach(a=>{ str += a + ' ' }) document.getElementById("consoleLog").innerHTML = str + "\n\n" + t; } } for (var i = 0; i < list.length; i++) { exchange(list[i]) } } changeLog() */ export {start, panoEditStart} /* 坐标转换问题: 由于控制点可以随便输入,所以本地和地理位置的转换也是可拉伸的。而navvis的转换是等比由中心展开, 所以对比两种转化方式时误差较大。 另外地理注册控制点是有参考数据集的,若参考数据集和我放置在0,0,0的数据集一致,就可直接使用,否则要转换。 */