start.js 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  1. import * as THREE from "../libs/three.js/build/three.module.js";
  2. import {settings, config} from './settings.js'
  3. import math from './utils/math.js'
  4. import browser from './utils/browser.js'
  5. import './custom/three.shim.js'
  6. import {Utils} from "./utils.js"
  7. import "./custom/potree.shim.js"
  8. var start = function(dom, mapDom, number ){ //t-Zvd3w0m
  9. /* {
  10. let obj = JSON.parse(localStorage.getItem('setting'))
  11. for(let i in obj){
  12. console.log(i + ': ' + obj[i])
  13. }
  14. }
  15. */
  16. Potree.settings.number = number || 't-o5YMR13'// 't-iksBApb'// 写在viewer前
  17. let viewer = new Potree.Viewer(dom , mapDom);
  18. let Alignment = viewer.modules.Alignment
  19. //let pointDensity = config.pointDensity.middle
  20. viewer.setEDLEnabled(false);
  21. viewer.setFOV(config.view.fov);
  22. //viewer.setPointBudget(pointDensity.pointBudget);
  23. viewer.loadSettingsFromURL();
  24. if(!Potree.settings.isOfficial){
  25. viewer.loadGUI(() => {
  26. viewer.setLanguage('en');
  27. //$("#menu_appearance").next().show();
  28. $("#menu_tools").next().show();
  29. $("#menu_scene").next().show();
  30. $("#siteModel").show();
  31. //$("#alignment").show();
  32. viewer.toggleSidebar();
  33. });
  34. Potree.settings.sizeFitToLevel = true//当type为衰减模式时自动根据level调节大小。每长一级,大小就除以2
  35. }
  36. Potree.loadDatasetsCallback = function(data, ifReload){
  37. if(!data || data.length == 0)return console.error('getDataSet加载的数据为空')
  38. Potree.datasetData = data
  39. viewer.transform = null
  40. var datasetLength = data.length
  41. var pointcloudLoaded = 0
  42. var panosLoaded = 0
  43. var pointcloudLoadDone = function(){//点云cloud.js加载完毕后
  44. viewer.updateModelBound()
  45. let {boundSize, center} = viewer.bound
  46. Potree.Log(`中心点: ${math.toPrecision(center.toArray(),2)}, boundSize: ${math.toPrecision(boundSize.toArray(),2)} ` , null, 12)
  47. if(!Potree.settings.isOfficial){
  48. Potree.loadMapEntity('all') //加载floorplan
  49. }
  50. if(!ifReload){
  51. viewer.scene.view.setView({
  52. position: center.clone().add(new THREE.Vector3(10,5,10)),
  53. target: center
  54. })
  55. viewer.dispatchEvent({type:'loadPointCloudDone'})
  56. if(!Potree.settings.UserPointDensity){
  57. Potree.settings.UserPointDensity = 'high'//'middle'
  58. }
  59. Potree.Log('loadPointCloudDone 点云加载完毕', null, 10)
  60. }
  61. }
  62. var panosLoadDone = function(){
  63. viewer.images360.loadDone()
  64. viewer.scene.add360Images(viewer.images360);
  65. viewer.mapViewer.addListener(viewer.images360)
  66. {//初始位置
  67. var urlFirstView = false
  68. var panoId = browser.urlHasValue('pano',true);
  69. if(panoId !== ''){
  70. var pos
  71. var pano = viewer.images360.panos.find(e=>e.id==panoId);
  72. if(pano){
  73. viewer.images360.focusPano({
  74. pano,
  75. duration:0,
  76. callback:()=>{/* Potree.settings.displayMode = 'showPanos' */}
  77. })
  78. }
  79. }else{//考虑到多数据集距离很远,或者像隧道那种场景,要使视野范围内一定能看到点云,最好初始点设置在漫游点上
  80. let {boundSize, center} = viewer.bound
  81. let pano = viewer.images360.findNearestPano(center)
  82. /* pano && viewer.scene.view.setView({
  83. position: pano.position.clone().add(new THREE.Vector3(10,10,10)),
  84. target: pano.position
  85. }) */
  86. pano && viewer.images360.flyToPano({
  87. pano, duration:0,
  88. target : viewer.images360.bound.center
  89. })
  90. }
  91. }
  92. viewer.addVideo()//addFire()
  93. console.log('allLoaded')
  94. viewer.dispatchEvent('allLoaded')
  95. }
  96. var transformPointcloud = (pointcloud, dataset)=>{
  97. var locationLonLat = dataset.location.slice(0,2)
  98. //当只有一个dataset时,无论如何transform 点云和漫游点都能对应上。
  99. var location = viewer.transform.lonlatToLocal.forward(locationLonLat) //transform.inverse()
  100. //初始化位置
  101. viewer.sidebar && viewer.sidebar.addAlignmentButton(pointcloud)
  102. //dataset.orientation = 0
  103. Alignment.rotate(pointcloud, null, dataset.orientation)
  104. Alignment.translate(pointcloud, new THREE.Vector3(location[0], location[1], dataset.location[2]))
  105. pointcloud.updateMatrixWorld()
  106. Potree.Log(`点云${pointcloud.dataset_id}旋转值:${pointcloud.orientationUser}, 位置${math.toPrecision(pointcloud.translateUser.toArray(),3)}, 经纬度 ${locationLonLat}, spacing ${pointcloud.material.spacing}`, null, 17 )
  107. //-------------------
  108. //viewer.mapView.showSources(false);
  109. }
  110. if(!Potree.settings.originDatasetId)Potree.settings.originDatasetId = data[0].id
  111. var originDataset = data.find(e=>e.id == Potree.settings.originDatasetId)
  112. {//拿初始数据集作为基准。它的位置是000
  113. var locationLonLat = originDataset.location.slice(0,2)
  114. proj4.defs("NAVVIS:TMERC", "+proj=tmerc +ellps=WGS84 +lon_0=" + locationLonLat[0].toPrecision(15) + " +lat_0=" + locationLonLat[1].toPrecision(15));
  115. proj4.defs("WGS84", "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs");
  116. let transform1 = proj4("WGS84", "NAVVIS:TMERC"); //这个ok TMERC是展开的平面投影
  117. 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;");
  118. viewer.transform = {
  119. lonlatToLocal : transform1,
  120. lonlatTo4550 : transform2 // 转大地坐标EPSG:4550
  121. }
  122. viewer.mapViewer && viewer.mapViewer.mapLayer.maps[0].updateProjection()
  123. }
  124. data.forEach((dataset,index)=>{
  125. if(!ifReload){
  126. var datasetCode = dataset.sceneCode || dataset.name //对应4dkk的场景码
  127. var cloudPath = `${Potree.settings.urls.prefix1}/${Potree.settings.webSite}/${datasetCode}/data/${datasetCode}/webcloud/cloud.js`
  128. var timeStamp = dataset.createTime ? dataset.createTime.replace(/[^0-9]/ig,'') : ''; //每重算一次后缀随createTime更新一次
  129. //console.warn(dataset.name, 'timeStamp', timeStamp)
  130. Potree.loadPointCloud(cloudPath, dataset.name ,datasetCode, timeStamp, e => {
  131. let scene = viewer.scene;
  132. let pointcloud = e.pointcloud;
  133. let config = Potree.config.material
  134. let material = pointcloud.material;
  135. pointcloud.hasDepthTex = Potree.settings.useDepthTex && (!!dataset.has_depth || Potree.settings.isLocalhost && Potree.settings.number == 'SS-t-7DUfWAUZ3V') //test
  136. material.minSize = config.minSize
  137. material.maxSize = config.maxSize
  138. material.pointSizeType = config.pointSizeType //Potree.PointSizeType[config.pointSizeType]//Potree.PointSizeType.ADAPTIVE;//FIXED
  139. pointcloud.changePointSize(config.realPointSize) //material.size = config.pointSize;
  140. pointcloud.changePointOpacity(1)
  141. material.shape = Potree.PointShape.SQUARE;
  142. pointcloud.color = pointcloud.material.color = dataset.color
  143. pointcloud.dataset_id = dataset.id;//供漫游点找到属于的dataset点云
  144. pointcloud.timeStamp = timeStamp
  145. transformPointcloud(pointcloud,dataset)
  146. scene.addPointCloud(pointcloud);
  147. if(!Potree.settings.isOfficial){
  148. Potree.settings.floorplanEnables[dataset.id] = true
  149. Potree.settings.floorplanType[dataset.id] = 'default'
  150. }
  151. pointcloudLoaded ++;
  152. if(pointcloudLoaded == datasetLength)pointcloudLoadDone()
  153. Potree.loadPanos(dataset.id, (data) => {
  154. //console.log('loadPanos',dataset.sceneCode, dataset.id, data)
  155. viewer.images360.addPanoData(data, dataset.id )
  156. panosLoaded ++;
  157. if(panosLoaded == datasetLength){
  158. panosLoadDone()
  159. }
  160. })
  161. })
  162. }else{
  163. let pointcloud = viewer.scene.pointclouds.find(p => p.dataset_id == dataset.id)
  164. if(!pointcloud){
  165. Potree.Log('数据集id变了,自动使用第一个','#500')
  166. pointcloud = viewer.scene.pointclouds[0]
  167. }
  168. //先归零
  169. Alignment.translate(pointcloud, pointcloud.translateUser.clone().negate())
  170. Alignment.rotate(pointcloud, null, - pointcloud.orientationUser)
  171. transformPointcloud(pointcloud, dataset)
  172. }
  173. })
  174. if(ifReload){
  175. //loadDone()
  176. }
  177. }
  178. Potree.loadDatasets(Potree.loadDatasetsCallback)
  179. window.testTransform = function(locationLonLat, location1, location2){
  180. proj4.defs("NAVVIS:test", "+proj=tmerc +ellps=WGS84 +lon_0=" + locationLonLat[0].toPrecision(15) + " +lat_0=" + locationLonLat[1].toPrecision(15));
  181. let transform = proj4("WGS84", "NAVVIS:test"); //这个ok navvis里也是这两种转换 见proj4Factory
  182. if(location1){//经纬度
  183. return transform.forward(location1)
  184. }else{
  185. return transform.inverse(location2)
  186. }
  187. }
  188. window.THREE = THREE
  189. window.buttonFunction = function(){
  190. viewer.scene.pointclouds.forEach(e=>e.predictNodeMaxLevel())
  191. /*
  192. viewer.startScreenshot({type:'measure', measurement:viewer.scene.measurements[0]})
  193. viewer.modules.RouteGuider.routeStart = new THREE.Vector3(0,0,-1.3)
  194. viewer.modules.RouteGuider.routeEnd = new THREE.Vector3(-10,0,-1.3)
  195. */
  196. }
  197. if(Potree.settings.isLocalhost){
  198. let before = {}
  199. viewer.inputHandler.addEventListener('keydown',e=>{ //测试的代码
  200. if(e.event.key == 't'){
  201. viewer.images360.cube.visible = true
  202. viewer.images360.cube.material.wireframe = true
  203. }else if(e.event.key == 'y'){
  204. viewer.images360.cube.material.wireframe = false
  205. viewer.images360.cube.visible = Potree.settings.displayMode == 'showPanos'
  206. }
  207. })
  208. }
  209. }
  210. //=======================================================================
  211. /*
  212. 漫游点编辑
  213. */
  214. //=======================================================================
  215. var panoEditStart = function(dom, number, fileServer){
  216. Potree.settings.editType = 'pano'
  217. Potree.settings.number = number
  218. Potree.settings.unableNavigate = true
  219. let viewer = new Potree.Viewer(dom);
  220. let Alignment = viewer.modules.Alignment
  221. viewer.setEDLEnabled(false);
  222. viewer.setFOV(config.view.fov);
  223. viewer.loadSettingsFromURL();
  224. let datasetLoaded = 0;
  225. if(!Potree.settings.isOfficial){
  226. viewer.loadGUI(() => {
  227. viewer.setLanguage('en');
  228. $("#menu_tools").next().show();
  229. $("#panos").show();
  230. $("#alignment").show();
  231. viewer.toggleSidebar();
  232. });
  233. Potree.settings.sizeFitToLevel = true
  234. }
  235. var pointcloudLoadDone = function( ){//所有点云cloud.js加载完毕后
  236. viewer.scene.pointclouds.forEach(c=>{
  237. transformPointcloud(c)
  238. })
  239. viewer.images360.loadDone()
  240. viewer.scene.add360Images(viewer.images360);
  241. viewer.updateModelBound()
  242. let {boundSize, center} = viewer.bound
  243. Potree.Log(`中心点: ${math.toPrecision(center.toArray(),2)}, boundSize: ${math.toPrecision(boundSize.toArray(),2)} ` , null, 12)
  244. viewer.scene.view.setView({
  245. position: center.clone().add(new THREE.Vector3(10,5,10)),
  246. target: center
  247. })
  248. viewer.dispatchEvent({type:'loadPointCloudDone'})
  249. if(!Potree.settings.UserPointDensity){
  250. Potree.settings.UserPointDensity = 'panoEdit'//'middle'
  251. }
  252. Potree.Log('loadPointCloudDone 点云加载完毕', null, 10)
  253. viewer.dispatchEvent('allLoaded');
  254. }
  255. var transformPointcloud = (pointcloud )=>{ //初始化位置
  256. viewer.sidebar && viewer.sidebar.addAlignmentButton(pointcloud)
  257. let orientation = pointcloud.panos[0].dataRotation.z + Math.PI
  258. let location = pointcloud.panos[0].dataPosition.clone()//.negate()
  259. Alignment.rotate(pointcloud, null, orientation )
  260. Alignment.translate(pointcloud, location )
  261. pointcloud.updateMatrixWorld()
  262. }
  263. let loadPanosDone = Potree.loadPanosDone = (datasetId, panoData )=>{ //一个数据集获取到它的panos后
  264. Potree.settings.datasetsPanos[datasetId] = {panoData, panos:[]}
  265. console.log('panoData', datasetId, panoData)
  266. let panoCount = panoData.length
  267. let pointcloudLoaded = 0
  268. let datasetsCount = Object.keys(Potree.settings.datasetsPanos).length
  269. panoData.forEach((pano, index)=>{
  270. //let cloudPath = `${Potree.scriptPath}/data/panoEdit/uuidcloud/${pano.uuid}/cloud.js`
  271. let cloudPath = `https://laser-oss.4dkankan.com/${Potree.settings.webSite}/${Potree.settings.number}/data/bundle_${Potree.settings.number}/building/uuidcloud/${pano.uuid}/cloud.js`
  272. let name = datasetId + '-'+pano.uuid
  273. let timeStamp = 0
  274. pano.index = index //注意:index不等于uuid,因为有的uuid缺失。但是visibles中存的是下标!
  275. Potree.loadPointCloud(cloudPath, name , name, timeStamp, e => { //开始加载点云
  276. let scene = viewer.scene;
  277. let pointcloud = e.pointcloud;
  278. let config = Potree.config.material
  279. let material = pointcloud.material;
  280. material.minSize = config.minSize
  281. material.maxSize = config.maxSize
  282. material.pointSizeType = /* 'ADAPTIVE'// */config.pointSizeType //Potree.PointSizeType[config.pointSizeType]//Potree.PointSizeType.ADAPTIVE;//FIXED
  283. pointcloud.changePointSize( 0.1 /* config.realPointSize */ ) //material.size = config.pointSize;
  284. pointcloud.changePointOpacity(1)
  285. material.shape = Potree.PointShape.SQUARE;
  286. pointcloud.color = config.pointColor
  287. pointcloud.dataset_id = datasetId; //多个点云指向一个datasetId
  288. pointcloud.panoUuid = pano.uuid
  289. pointcloud.timeStamp = timeStamp
  290. //transformPointcloud(pointcloud, pano)
  291. scene.addPointCloud(pointcloud);
  292. pointcloudLoaded ++;
  293. if(pointcloudLoaded == panoCount ){
  294. datasetLoaded ++
  295. viewer.images360.addPanoData(panoData , datasetId )
  296. if(datasetLoaded == datasetsCount){
  297. pointcloudLoadDone()
  298. }
  299. }
  300. })
  301. })
  302. }
  303. if(!Potree.settings.isOfficial){
  304. Potree.settings.datasetsPano = {'testDataset':null}
  305. Potree.loadPanosInfo( data=>{loadPanosDone('testDataset', data.sweepLocations)} )
  306. }
  307. }
  308. var mergeEditStart = function(dom){
  309. Potree.settings.editType = 'merge'
  310. Potree.settings.intersectOnObjs = true
  311. Potree.settings.boundAddObjs = true
  312. Potree.settings.unableNavigate = true
  313. let viewer = new Potree.Viewer(dom );
  314. let Alignment = viewer.modules.Alignment
  315. viewer.setEDLEnabled(false);
  316. viewer.setFOV(config.view.fov);
  317. viewer.loadSettingsFromURL();
  318. {
  319. viewer.mainViewport.view.position.set(30,30,30)
  320. viewer.mainViewport.view.lookAt(0,0,0)
  321. viewer.updateModelBound()//init
  322. //this.bound = new THREE.Box3(new THREE.Vector3(-1,-1,-1),new THREE.Vector3(1,1,1))
  323. viewer.transformationTool.setModeEnable('scale',false)
  324. viewer.ssaaRenderPass.sampleLevel = 1 // sampleLevel为1 的话,ground就不会变黑
  325. viewer.inputHandler.fixSelection = true //不通过点击屏幕而切换transfrom选中状态
  326. }
  327. Potree.settings.sizeFitToLevel = true//当type为衰减模式时自动根据level调节大小。每长一级,大小就除以2
  328. Potree.loadPointCloudScene = function(sceneCode, type, id, done, onError){//对应4dkk的场景码
  329. let loadCloud = (cloudPath, sceneName, sceneCode, timeStamp, color)=>{
  330. Potree.loadPointCloud(cloudPath, sceneName , sceneCode, timeStamp, e => {
  331. let scene = viewer.scene;
  332. let pointcloud = e.pointcloud;
  333. let config = Potree.config.material
  334. let material = pointcloud.material;
  335. material.minSize = config.minSize
  336. material.maxSize = config.maxSize
  337. material.pointSizeType = config.pointSizeType //Potree.PointSizeType[config.pointSizeType]//Potree.PointSizeType.ADAPTIVE;//FIXED
  338. pointcloud.changePointSize(config.realPointSize) //material.size = config.pointSize;
  339. pointcloud.changePointOpacity(1)
  340. material.shape = Potree.PointShape.SQUARE;
  341. color && (pointcloud.color = pointcloud.material.color = color)
  342. pointcloud.timeStamp = timeStamp
  343. //transformPointcloud(pointcloud, originDataset)
  344. scene.addPointCloud(pointcloud);
  345. {
  346. viewer.updateModelBound()
  347. let {boundSize, center} = viewer.bound
  348. viewer.dispatchEvent({type:'loadPointCloudDone'})
  349. if(!Potree.settings.UserPointDensity){
  350. Potree.settings.UserPointDensity = 'high'//'middle'
  351. }
  352. Potree.Log('loadPointCloudDone 点云加载完毕', null, 10)
  353. }
  354. /* Potree.loadPanos(dataset.id, (data) => { //暂时不加载panos了,因为没有id
  355. //console.log('loadPanos',dataset.sceneCode, dataset.id, data)
  356. viewer.images360.addPanoData(data, dataset.id )
  357. viewer.images360.loadDone()
  358. viewer.scene.add360Images(viewer.images360); */
  359. viewer.dispatchEvent('allLoaded')
  360. done(pointcloud)
  361. },onError)
  362. }
  363. if(type == 'laser'){
  364. Potree.loadDatasets((data)=>{
  365. let originDataset = data.find(e=>e.sceneCode == sceneCode);//只加载初始数据集
  366. let timeStamp = originDataset.createTime ? originDataset.createTime.replace(/[^0-9]/ig,'') : ''; //每重算一次后缀随createTime更新一次
  367. let cloudPath = `${Potree.settings.urls.prefix1}/${Potree.settings.webSite}/${sceneCode}/data/${sceneCode}/webcloud/cloud.js`
  368. loadCloud(cloudPath, originDataset.sceneName, sceneCode, timeStamp, originDataset.color)
  369. }, sceneCode, onError)
  370. }else{//las or ply
  371. let name = type + '|' + id
  372. let cloudPath = sceneCode + '/cloud.js'
  373. loadCloud(cloudPath, name, name, '' )
  374. }
  375. }
  376. let setMatrix = (pointcloud)=>{//为了漫游点变换,要算一下 类似setMatrix
  377. /* pointcloud.transformMatrix = new THREE.Matrix4().multiplyMatrices(pointcloud.matrix, pointcloud.pos1MatrixInvert)//还原一点位移
  378. pointcloud.transformInvMatrix.copy(pointcloud.transformMatrix).invert()
  379. pointcloud.rotateMatrix = new THREE.Matrix4().makeRotationFromEuler(pointcloud.rotation);
  380. pointcloud.rotateInvMatrix.copy(pointcloud.rotateMatrix).invert()
  381. pointcloud.panos.forEach(e=>e.transformByPointcloud()) */
  382. //pointcloud.updateBound()
  383. //pointcloud.getPanosBound()
  384. viewer.updateModelBound()
  385. }
  386. let moveModel = (e)=>{//根据鼠标移动的位置改变位置
  387. let camera = viewer.mainViewport.camera
  388. var origin = new THREE.Vector3(e.pointer.x, e.pointer.y, -1).unproject(camera),
  389. end = new THREE.Vector3(e.pointer.x, e.pointer.y, 1).unproject(camera)
  390. var dir = end.sub(origin)
  391. let planeZ = 0;
  392. let r = (planeZ - origin.z)/dir.z
  393. let x = r * dir.x + origin.x
  394. let y = r * dir.y + origin.y
  395. //过后改为根据intersect的点来设置底部高度;这样的话,需要发送高度
  396. /*let pos = new THREE.Vector3(x,y, planeZ )
  397. modelEditing.updateMatrixWorld()
  398. let boundCenter = modelEditing.boundingBox.getCenter(new THREE.Vector3).applyMatrix4(modelEditing.matrixWorld);
  399. */
  400. MergeEditor.moveBoundCenterTo(modelEditing,new THREE.Vector3(x,y, modelEditing.boundCenter.z)) //使模型中心的xy在鼠标所在位置
  401. modelEditing.dispatchEvent("position_changed")
  402. }
  403. let cancelMove = ()=>{
  404. modelEditing = null
  405. viewer.removeEventListener('global_mousemove', moveModel);
  406. viewer.removeEventListener('global_click', confirmPos);
  407. }
  408. let confirmPos = ()=>{
  409. MergeEditor.focusOn(modelEditing)
  410. cancelMove()
  411. return {stopContinue:true}
  412. }
  413. let modelType, modelEditing, MergeEditor = viewer.modules.MergeEditor
  414. Potree.addModel = function(prop, done, onProgress, onError){ //加载模型
  415. let loadDone = (model)=>{
  416. model.dataset_id = prop.id //唯一标识
  417. if(prop.position){
  418. model.position.copy(prop.position)
  419. }
  420. if(prop.rotation){
  421. model.rotation.setFromVector3(prop.rotation)
  422. }
  423. if(prop.scale){
  424. model.scale.set(prop.scale,prop.scale,prop.scale)
  425. }
  426. if(model.isPointcloud){
  427. model.renderOrder = Potree.config.renderOrders.model; //same as glb
  428. }
  429. /* {//transform --------维持离地高度和中心点的版本
  430. let updateBound = ()=>{
  431. model.updateMatrixWorld()
  432. viewer.updateModelBound()
  433. }
  434. let maintainBtmZAndCenter = ()=>{
  435. MergeEditor.maintainBoundXY(model)
  436. MergeEditor.setModelBtmHeight(model)
  437. updateBound()
  438. model.dispatchEvent('transformChanged')
  439. }
  440. model.addEventListener('position_changed', ()=>{
  441. updateBound()
  442. MergeEditor.getBoundCenter(model);//更新boundcenter
  443. MergeEditor.computeBtmHeight(model)
  444. if(prop.bottomRange && (model.btmHeight > prop.bottomRange.max || model.btmHeight < prop.bottomRange.min)){
  445. model.btmHeight = THREE.Math.clamp(model.btmHeight, prop.bottomRange.min, prop.bottomRange.max)
  446. MergeEditor.setModelBtmHeight(model)
  447. updateBound()
  448. }
  449. model.dispatchEvent('transformChanged')
  450. })
  451. model.addEventListener("rotation_changed", maintainBtmZAndCenter )
  452. model.addEventListener("scale_changed", maintainBtmZAndCenter )
  453. model.addEventListener('transformChanged', ()=>{
  454. MergeEditor.modelTransformCallback(model)
  455. })
  456. //离地高度只是boundingbox在transform后的最低点的高度,而非模型transform后的最低点的高度,所以旋转过后看起来不太准确
  457. } */
  458. {//transform --------维持中心点的版本
  459. let updateBound = ()=>{
  460. model.updateMatrixWorld()
  461. viewer.updateModelBound()
  462. }
  463. let maintainCenter = ()=>{
  464. //MergeEditor.maintainBoundXY(model)
  465. MergeEditor.maintainBoundCenter(model)
  466. updateBound()
  467. model.dispatchEvent('transformChanged')
  468. }
  469. model.addEventListener('position_changed', ()=>{
  470. updateBound()
  471. MergeEditor.getBoundCenter(model);//更新boundcenter
  472. model.dispatchEvent('transformChanged')
  473. })
  474. model.addEventListener("rotation_changed", maintainCenter )
  475. model.addEventListener("scale_changed", maintainCenter )
  476. model.addEventListener('transformChanged', ()=>{
  477. MergeEditor.modelTransformCallback(model)
  478. })
  479. }
  480. model.updateMatrixWorld()
  481. viewer.updateModelBound()
  482. MergeEditor.getBoundCenter(model) //初始化
  483. model.lastMatrixWorld = model.matrixWorld.clone()
  484. done(model) // 先发送成功,因为2d界面会随机执行changePosition等初始化,然后这边再将模型移到中心地面上
  485. if(prop.isFirstLoad){
  486. MergeEditor.moveBoundCenterTo(model, new THREE.Vector3(0,0,0))
  487. MergeEditor.setModelBtmHeight(model, 0) //初始加载设置离地高度为0
  488. if(prop.mode != 'single'){//如果不是模型展示页,模型会随着鼠标位置移动
  489. viewer.addEventListener('global_mousemove', moveModel);
  490. viewer.addEventListener('global_click', confirmPos, 3);
  491. modelEditing = model;
  492. }
  493. model.dispatchEvent("position_changed")
  494. }else{
  495. //MergeEditor.setModelBtmHeight(model, prop.bottom || 0) //默认离地高度为0
  496. modelEditing = null
  497. }
  498. }
  499. if(prop.type == 'glb'){
  500. let callback = (object)=>{
  501. //focusOnSelect(object, 1000)
  502. object.isModel = true
  503. //object.dataset_id = Date.now() //暂时
  504. object.traverse(e=>e.material && (e.material.transparent = true))
  505. /* object.addEventListener('click',(e)=>{
  506. //只是为了能得到hoverElement识别才加这个侦听
  507. }) */
  508. loadDone(object)
  509. }
  510. let info = {
  511. name: prop.type,
  512. id: prop.id,
  513. unlit:true,
  514. /* transform : {
  515. position : prop.position,
  516. rotation : new THREE.Euler().setFromVector3(prop.rotation),
  517. scale: new THREE.Vector3(prop.scale,prop.scale,prop.scale),
  518. } */
  519. }
  520. if(prop.type == 'glb'){
  521. info.glburl = prop.url
  522. }
  523. viewer.loadModel(info , callback, onProgress, onError)
  524. }else{
  525. //else if(prop.type == 'las' || prop.type == 'ply')
  526. Potree.loadPointCloudScene(prop.url, prop.type, prop.modelId, (pointcloud)=>{
  527. pointcloud.matrixAutoUpdate = true
  528. pointcloud.initialPosition = pointcloud.position.clone()
  529. pointcloud.pos1MatrixInvert = new THREE.Matrix4().setPosition(pointcloud.initialPosition).invert()
  530. /* let maintainBtmZ = ()=>{
  531. MergeEditor.setModelBtmHeight(pointcloud)
  532. updateMatrix()
  533. }
  534. let updateMatrix = ()=>{
  535. setMatrix(pointcloud)
  536. pointcloud.dispatchEvent('transformChanged')
  537. }
  538. pointcloud.addEventListener('position_changed', updateMatrix )
  539. pointcloud.addEventListener("orientation_changed", maintainBtmZ )
  540. pointcloud.addEventListener("scale_changed", maintainBtmZ ) */
  541. loadDone(pointcloud)
  542. /* pointcloud.addEventListener('select',(e)=>{
  543. if(Potree.settings.displayMode == 'showPanos')return
  544. console.log('select',e)
  545. //viewer.setControls(viewer.orbitControls)
  546. MergeEditor.focusOnSelect(pointcloud)
  547. viewer.outlinePass.selectedObjects = [pointcloud]
  548. return {stopContinue:true}
  549. },1)
  550. pointcloud.addEventListener('deselect',(e)=>{
  551. console.log('deselect',e)
  552. //viewer.setControls(viewer.fpControls)
  553. viewer.outlinePass.selectedObjects = []
  554. }) */
  555. }, onError)
  556. }
  557. }
  558. return {THREE}
  559. }
  560. /* var changeLog = ()=>{ //如果移动端加了test反而出不来bug的话,用这个
  561. var textarea = document.createElement('textarea');
  562. textarea.id = "consoleLog";
  563. textarea.style.width = '160px';
  564. textarea.style.height = '200px'
  565. textarea.style.position = 'fixed'
  566. textarea.style.right = 0
  567. textarea.style.bottom = '0'
  568. textarea.style['z-index'] = 9999;
  569. textarea.style.color = 'black';
  570. textarea.style.opacity = 0.9;
  571. textarea.style['font-size'] = '12px';
  572. textarea.style['backgroundColor'] = '#ffffff'
  573. document.getElementsByTagName("body")[0].appendChild(textarea);
  574. var list = ["log", "error", "warn", "debug", "info", "time", "timeEnd"]
  575. var exchange = function (o) {
  576. console["old" + o] = console[o];
  577. console[o] = function () {
  578. var args = Array.from(arguments)
  579. console["old" + o].apply(this, arguments)
  580. var t = document.getElementById("consoleLog").innerHTML;
  581. var str = ''
  582. args.forEach(a=>{
  583. str += a + ' '
  584. })
  585. document.getElementById("consoleLog").innerHTML = str + "\n\n" + t;
  586. }
  587. }
  588. for (var i = 0; i < list.length; i++) {
  589. exchange(list[i])
  590. }
  591. }
  592. changeLog() */
  593. export {start, panoEditStart, mergeEditStart}
  594. /*
  595. 坐标转换问题:
  596. 由于控制点可以随便输入,所以本地和地理位置的转换也是可拉伸的。而navvis的转换是等比由中心展开,
  597. 所以对比两种转化方式时误差较大。
  598. 另外地理注册控制点是有参考数据集的,若参考数据集和我放置在0,0,0的数据集一致,就可直接使用,否则要转换。
  599. */