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 './custom/three.shim.js' import {Utils} from "./utils.js" import "./custom/potree.shim.js" var start = function(dom, mapDom, number ){ //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前 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.prefix1}/${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.useDepthTex && (!!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); if(!Potree.settings.isOfficial){ Potree.settings.floorplanEnables[dataset.id] = true Potree.settings.floorplanType[dataset.id] = 'default' } 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){ 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 + Math.PI 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/${Potree.settings.webSite}/${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.1 /* 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 mergeEditStart = function(dom){ Potree.settings.editType = 'merge' Potree.settings.intersectOnObjs = true Potree.settings.boundAddObjs = true 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(); { viewer.mainViewport.view.position.set(30,30,30) viewer.mainViewport.view.lookAt(0,0,0) viewer.updateModelBound()//init //this.bound = new THREE.Box3(new THREE.Vector3(-1,-1,-1),new THREE.Vector3(1,1,1)) viewer.transformationTool.setModeEnable('scale',false) viewer.ssaaRenderPass.sampleLevel = 1 // sampleLevel为1 的话,ground就不会变黑 viewer.inputHandler.fixSelection = true //不通过点击屏幕而切换transfrom选中状态 } Potree.settings.sizeFitToLevel = true//当type为衰减模式时自动根据level调节大小。每长一级,大小就除以2 Potree.loadPointCloudScene = function(sceneCode, type, id, done, onError){//对应4dkk的场景码 let loadCloud = (cloudPath, sceneName, sceneCode, timeStamp, color)=>{ Potree.loadPointCloud(cloudPath, sceneName , sceneCode, 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 = 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; color && (pointcloud.color = pointcloud.material.color = color) pointcloud.timeStamp = timeStamp //transformPointcloud(pointcloud, originDataset) scene.addPointCloud(pointcloud); { viewer.updateModelBound() let {boundSize, center} = viewer.bound viewer.dispatchEvent({type:'loadPointCloudDone'}) if(!Potree.settings.UserPointDensity){ Potree.settings.UserPointDensity = 'high'//'middle' } Potree.Log('loadPointCloudDone 点云加载完毕', null, 10) } /* Potree.loadPanos(dataset.id, (data) => { //暂时不加载panos了,因为没有id //console.log('loadPanos',dataset.sceneCode, dataset.id, data) viewer.images360.addPanoData(data, dataset.id ) viewer.images360.loadDone() viewer.scene.add360Images(viewer.images360); */ viewer.dispatchEvent('allLoaded') done(pointcloud) },onError) } if(type == 'laser'){ Potree.loadDatasets((data)=>{ let originDataset = data.find(e=>e.sceneCode == sceneCode);//只加载初始数据集 let timeStamp = originDataset.createTime ? originDataset.createTime.replace(/[^0-9]/ig,'') : ''; //每重算一次后缀随createTime更新一次 let cloudPath = `${Potree.settings.urls.prefix1}/${Potree.settings.webSite}/${sceneCode}/data/${sceneCode}/webcloud/cloud.js` loadCloud(cloudPath, originDataset.sceneName, sceneCode, timeStamp, originDataset.color) }, sceneCode, onError) }else{//las or ply let name = type + '|' + id let cloudPath = sceneCode + '/cloud.js' loadCloud(cloudPath, name, name, '' ) } } let setMatrix = (pointcloud)=>{//为了漫游点变换,要算一下 类似setMatrix /* pointcloud.transformMatrix = new THREE.Matrix4().multiplyMatrices(pointcloud.matrix, pointcloud.pos1MatrixInvert)//还原一点位移 pointcloud.transformInvMatrix.copy(pointcloud.transformMatrix).invert() pointcloud.rotateMatrix = new THREE.Matrix4().makeRotationFromEuler(pointcloud.rotation); pointcloud.rotateInvMatrix.copy(pointcloud.rotateMatrix).invert() pointcloud.panos.forEach(e=>e.transformByPointcloud()) */ //pointcloud.updateBound() //pointcloud.getPanosBound() viewer.updateModelBound() } let moveModel = (e)=>{//根据鼠标移动的位置改变位置 let camera = viewer.mainViewport.camera var origin = new THREE.Vector3(e.pointer.x, e.pointer.y, -1).unproject(camera), end = new THREE.Vector3(e.pointer.x, e.pointer.y, 1).unproject(camera) var dir = end.sub(origin) let planeZ = 0; let r = (planeZ - origin.z)/dir.z let x = r * dir.x + origin.x let y = r * dir.y + origin.y //过后改为根据intersect的点来设置底部高度;这样的话,需要发送高度 /*let pos = new THREE.Vector3(x,y, planeZ ) modelEditing.updateMatrixWorld() let boundCenter = modelEditing.boundingBox.getCenter(new THREE.Vector3).applyMatrix4(modelEditing.matrixWorld); */ MergeEditor.moveBoundCenterTo(modelEditing,new THREE.Vector3(x,y, modelEditing.boundCenter.z)) //使模型中心的xy在鼠标所在位置 modelEditing.dispatchEvent("position_changed") } let cancelMove = ()=>{ modelEditing = null viewer.removeEventListener('global_mousemove', moveModel); viewer.removeEventListener('global_click', confirmPos); } let confirmPos = ()=>{ MergeEditor.focusOn(modelEditing) cancelMove() return {stopContinue:true} } let modelType, modelEditing, MergeEditor = viewer.modules.MergeEditor Potree.addModel = function(prop, done, onProgress, onError){ //加载模型 let loadDone = (model)=>{ model.dataset_id = prop.id //唯一标识 if(prop.position){ model.position.copy(prop.position) } if(prop.rotation){ model.rotation.setFromVector3(prop.rotation) } if(prop.scale){ model.scale.set(prop.scale,prop.scale,prop.scale) } if(model.isPointcloud){ model.renderOrder = Potree.config.renderOrders.model; //same as glb } /* {//transform --------维持离地高度和中心点的版本 let updateBound = ()=>{ model.updateMatrixWorld() viewer.updateModelBound() } let maintainBtmZAndCenter = ()=>{ MergeEditor.maintainBoundXY(model) MergeEditor.setModelBtmHeight(model) updateBound() model.dispatchEvent('transformChanged') } model.addEventListener('position_changed', ()=>{ updateBound() MergeEditor.getBoundCenter(model);//更新boundcenter MergeEditor.computeBtmHeight(model) if(prop.bottomRange && (model.btmHeight > prop.bottomRange.max || model.btmHeight < prop.bottomRange.min)){ model.btmHeight = THREE.Math.clamp(model.btmHeight, prop.bottomRange.min, prop.bottomRange.max) MergeEditor.setModelBtmHeight(model) updateBound() } model.dispatchEvent('transformChanged') }) model.addEventListener("rotation_changed", maintainBtmZAndCenter ) model.addEventListener("scale_changed", maintainBtmZAndCenter ) model.addEventListener('transformChanged', ()=>{ MergeEditor.modelTransformCallback(model) }) //离地高度只是boundingbox在transform后的最低点的高度,而非模型transform后的最低点的高度,所以旋转过后看起来不太准确 } */ {//transform --------维持中心点的版本 let updateBound = ()=>{ model.updateMatrixWorld() viewer.updateModelBound() } let maintainCenter = ()=>{ //MergeEditor.maintainBoundXY(model) MergeEditor.maintainBoundCenter(model) updateBound() model.dispatchEvent('transformChanged') } model.addEventListener('position_changed', ()=>{ updateBound() MergeEditor.getBoundCenter(model);//更新boundcenter model.dispatchEvent('transformChanged') }) model.addEventListener("rotation_changed", maintainCenter ) model.addEventListener("scale_changed", maintainCenter ) model.addEventListener('transformChanged', ()=>{ MergeEditor.modelTransformCallback(model) }) } model.updateMatrixWorld() viewer.updateModelBound() MergeEditor.getBoundCenter(model) //初始化 model.lastMatrixWorld = model.matrixWorld.clone() done(model) // 先发送成功,因为2d界面会随机执行changePosition等初始化,然后这边再将模型移到中心地面上 if(prop.isFirstLoad){ MergeEditor.moveBoundCenterTo(model, new THREE.Vector3(0,0,0)) MergeEditor.setModelBtmHeight(model, 0) //初始加载设置离地高度为0 if(prop.mode != 'single'){//如果不是模型展示页,模型会随着鼠标位置移动 viewer.addEventListener('global_mousemove', moveModel); viewer.addEventListener('global_click', confirmPos, 3); modelEditing = model; } model.dispatchEvent("position_changed") }else{ //MergeEditor.setModelBtmHeight(model, prop.bottom || 0) //默认离地高度为0 modelEditing = null } } if(prop.type == 'glb'){ let callback = (object)=>{ //focusOnSelect(object, 1000) object.isModel = true //object.dataset_id = Date.now() //暂时 object.traverse(e=>e.material && (e.material.transparent = true)) /* object.addEventListener('click',(e)=>{ //只是为了能得到hoverElement识别才加这个侦听 }) */ loadDone(object) } let info = { name: prop.type, id: prop.id, unlit:true, /* transform : { position : prop.position, rotation : new THREE.Euler().setFromVector3(prop.rotation), scale: new THREE.Vector3(prop.scale,prop.scale,prop.scale), } */ } if(prop.type == 'glb'){ info.glburl = prop.url } viewer.loadModel(info , callback, onProgress, onError) }else{ //else if(prop.type == 'las' || prop.type == 'ply') Potree.loadPointCloudScene(prop.url, prop.type, prop.modelId, (pointcloud)=>{ pointcloud.matrixAutoUpdate = true pointcloud.initialPosition = pointcloud.position.clone() pointcloud.pos1MatrixInvert = new THREE.Matrix4().setPosition(pointcloud.initialPosition).invert() /* let maintainBtmZ = ()=>{ MergeEditor.setModelBtmHeight(pointcloud) updateMatrix() } let updateMatrix = ()=>{ setMatrix(pointcloud) pointcloud.dispatchEvent('transformChanged') } pointcloud.addEventListener('position_changed', updateMatrix ) pointcloud.addEventListener("orientation_changed", maintainBtmZ ) pointcloud.addEventListener("scale_changed", maintainBtmZ ) */ loadDone(pointcloud) /* pointcloud.addEventListener('select',(e)=>{ if(Potree.settings.displayMode == 'showPanos')return console.log('select',e) //viewer.setControls(viewer.orbitControls) MergeEditor.focusOnSelect(pointcloud) viewer.outlinePass.selectedObjects = [pointcloud] return {stopContinue:true} },1) pointcloud.addEventListener('deselect',(e)=>{ console.log('deselect',e) //viewer.setControls(viewer.fpControls) viewer.outlinePass.selectedObjects = [] }) */ }, onError) } } return {THREE} } /* 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, mergeEditStart} /* 坐标转换问题: 由于控制点可以随便输入,所以本地和地理位置的转换也是可拉伸的。而navvis的转换是等比由中心展开, 所以对比两种转化方式时误差较大。 另外地理注册控制点是有参考数据集的,若参考数据集和我放置在0,0,0的数据集一致,就可直接使用,否则要转换。 */