index.js 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488
  1. import mitt from 'mitt'
  2. import axios from 'axios' //{ axios } from '@/api'
  3. let requestLoadCount = 0
  4. let maxLoadingCount = 2; //正在加载模型的最大数目
  5. //0看看,1看见,2深时,3用户上传三维模型,4深时mesh,5深光点云,6深光mesh
  6. const ModelTypes = {
  7. 0 : {name:'看看(八目)', panos4dkk:true},
  8. 1 : {name:'看见(双目转台)', panos4dkk:true, rot90:true},
  9. 2 : {name:'深时', },
  10. 3 : {name:'用户上传三维模型'},
  11. 4 : {name:'深时mesh(激光转台)',panos4dkk:true, rot90:true},//3dtiles
  12. 5 : {name:'深光点云' },
  13. 6 : {name:'深光mesh',panos4dkk:true, rot90:true},//3dtiles
  14. }
  15. let cesAspect
  16. export const enter = ({ dom, mapDom, isLocal, lonlat, scenes }) => {
  17. console.warn('新的页面')
  18. Potree.settings.isOfficial = true //标记为正式、非测试版本
  19. //Potree.fileServer = axios
  20. Potree.settings.libsUrl = './lib/'
  21. let loadStartTime = Date.now()
  22. //正式环境(本地调试会打不开)
  23. if (location.host === 'mix3d.4dkankan.com') {
  24. Potree.settings.urls.prefix = Potree.settings.urls.prefix6
  25. Potree.settings.webSite = 'datav1'
  26. } else if (location.host === 'xfhd.4dkankan.com') {
  27. Potree.settings.urls.prefix = Potree.settings.urls.prefix7
  28. Potree.settings.webSite = 'datav1'
  29. }
  30. const mapBus = mitt(), sceneBus = mitt()
  31. const tagLimitDis = 8;
  32. Potree.settings.showCompass = true
  33. Potree.settings.compassDom = dom.querySelector('#direction')
  34. Potree.settings.showObjectsOnMap = true
  35. Potree.settings.mergeType2 = true //标识新版
  36. Potree.settings.modelSkybox = true //是否将全景图贴在模型上(会导致卡顿)。若不显示模型将不显示Reticule
  37. Potree.settings.tiles3DMaxMemory = 300 //稍微增加点
  38. Potree.settings.mergeTransCtlOnClick = true
  39. Potree.settings.canWalkThroughModel = true
  40. Potree.config.view.near = 0.0001 //以防有的漫游场景模型缩放的很小(0.1%) 但似乎会造成z-fighting,不记得之前是否有过bug
  41. let { THREE } = Potree.mergeEditStart(dom, mapDom)
  42. let MergeEditor = viewer.modules.MergeEditor
  43. Potree.settings.unableNavigate = true
  44. /* Potree.settings.showCesium = !!lonlat
  45. Potree.settings.showCesium && buildMap()
  46. */
  47. //因为getPose里用的是target,俯视的yaw不准,所以限制一下不要完全俯视
  48. viewer.mainViewport.view.maxPitch-=0.001
  49. viewer.mainViewport.view.minPitch+=0.001
  50. viewer.addEventListener('camera_changed', e => {
  51. var camera = e.viewport.camera
  52. var pos = camera.position
  53. if (e.viewport.name == 'MainView') {
  54. sceneBus.emit('cameraChange', { x: pos.x, y: pos.y, z: pos.z, rotate: camera.rotation })
  55. updateMap()
  56. }
  57. })
  58. //-------------------------------------
  59. let modelAinB = (A,B)=>{ //B的expand(5m) bound完全包含A
  60. let boundB = B.boundingBox.clone().expandByVector(new THREE.Vector3(5,5,5)).applyMatrix4(B.matrixWorld)
  61. let boundA = A.boundingBox.clone().applyMatrix4(A.matrixWorld)
  62. return boundB.containsBox(boundA)
  63. }
  64. let changeMeshVisi = (object, show) => {
  65. if(show == void 0) show = Potree.settings.displayMode == 'showPointCloud' || object == viewer.images360.currentPano.pointcloud && Potree.settings.modelSkybox || object.showInPano //showInPano: 装饰物,一直显示
  66. || !object.panos && modelAinB(object, viewer.images360.currentPano.pointcloud) //装饰物
  67. Potree.Utils.updateVisible(object, 'showPanos', show)
  68. }
  69. if(Potree.settings.canWalkThroughModel){
  70. let lastModel
  71. viewer.images360.addEventListener('flyToPano',(e)=>{//开始漫游 漫游到另一个模型就要选中这个模型?
  72. let model = e.toPano.pano.pointcloud
  73. if(lastModel != model){
  74. changeMeshVisi(model, true)
  75. //MergeEditor.selectModel(model)
  76. //model.result_.flyInPano(e.toPano.pano, {dontFly:true}) //切换模型显示,因为flyInPano有事件怕乱所以统一用这个函数
  77. }
  78. })
  79. viewer.images360.addEventListener('flyToPanoDone',(e)=>{
  80. if(!e.makeIt)return
  81. let model = viewer.images360.currentPano.pointcloud
  82. if(lastModel != model){
  83. lastModel?.isModel && changeMeshVisi(lastModel, false)
  84. sceneBus.emit('panoModelChange', model.result_ )
  85. }
  86. lastModel = model
  87. })
  88. }
  89. viewer.images360.addEventListener('endChangeMode',(e)=>{
  90. sceneBus.emit('modeChange', {mode: e.mode == 'showPanos' ? 'pano' : 'fuse', model : e.mode == 'showPanos' && viewer.images360.currentPano.pointcloud.result_} )
  91. Potree.Utils.updateVisible(MergeEditor.transformControls, 'showPanos', e.mode == 'showPointCloud')
  92. Potree.Utils.updateVisible(MergeEditor.boxHelper, 'showPanos', e.mode == 'showPointCloud')
  93. if(e.mode == 'showPanos'){
  94. viewer.setControls( viewer.fpControls )
  95. viewer.removeEventListener('camera_changed', camera_changed)
  96. }else{
  97. viewer.addEventListener('camera_changed', camera_changed)
  98. }
  99. viewer.objs.children.forEach((e)=>{changeMeshVisi(e)})
  100. Potree.settings.canWalkThroughModel || viewer.images360.panos.forEach(pano => {
  101. pano.setEnable(e.mode == 'showPanos' ? pano.pointcloud == viewer.images360.currentPano.model : true)
  102. })
  103. Potree.settings.unableNavigate = e.mode == 'showPointCloud'
  104. })
  105. let camera_changed = (e) => {
  106. if (e.viewport.name == 'MainView' && e.changeInfo.positionChanged) {
  107. //viewer.mainViewport.camera.position
  108. viewer.mainViewport.view.radius = 0.1 //使pivot在面前一丢丢距离
  109. viewer.setControls(viewer.orbitControls)
  110. viewer.removeEventListener('camera_changed', camera_changed)
  111. }
  112. }
  113. let requestInPano = false
  114. //-------------------------------------
  115. /* viewer.inputHandler.addEventListener('keydown', (e)=>{
  116. if(e.event.key == "e" ){
  117. MergeEditor.transformControls.mode = 'rotate'
  118. }else if(e.event.key == "w"){
  119. MergeEditor.transformControls.mode = 'translate'
  120. }else if(e.event.key == "s"){
  121. MergeEditor.transformControls.mode = 'scale'
  122. }
  123. }) */
  124. viewer.addEventListener('webglError', e => {
  125. console.error('viewer webglError: ' + e)
  126. sceneBus.emit('webglError', { msg: e.msg })
  127. })
  128. viewer.compass.setAutoDisplay(true)
  129. /* mapBus.on('visible', v => {
  130. //console.log('mapBus visible', v)
  131. viewer.mapViewer.visible = v
  132. if (v) {
  133. viewer.mapViewer.mapLayer.needUpdate = true
  134. }
  135. viewer.mapViewer.dispatchEvent({type:'forceVisible',visible:v})
  136. }) */
  137. {
  138. let index = 1;
  139. //let setDisplay()
  140. if (!Potree.isIframeChild) {
  141. /* viewer.addEventListener('createIframe',(e)=>{//创建了子页面
  142. }) */
  143. window.winIndex = 0;
  144. window.iframeCreated = function (iframe) {
  145. let child = iframe.contentWindow
  146. child.winIndex = index++
  147. //案件里视图提取页面子页面覆盖了父级页面,父级的模型可以隐藏以释放内存
  148. console.error('createdIframe', child.winIndex, child.location.href)
  149. viewer.setDisplay(false)
  150. child.beforeDestroy = function () { //注:在前端仍会找不到beforeDestroy,可能contentWindow变更??所以手动调用setDisplay
  151. console.warn('beforeDestroy', child.winIndex)
  152. child.viewer && child.viewer.setDisplay(false)
  153. //如果是四维看看的场景,先不管了,页面被销毁应该就没了吧
  154. viewer.setDisplay(true)//恢复主页的模型显示
  155. if (!child.viewer) {
  156. try {
  157. let player = child.__sdk.core.get('Player')
  158. /* let runtime = player.model._3dTilesRuntime
  159. let tileset = runtime.getTileset()
  160. tileset._cache.trim(); //使下一次update时dispose所有不可见的tiles
  161. let sceneRenderer = child.__sdk.core.get('SceneRenderer')
  162. player.model.visible = false
  163. runtime.update(16, sceneRenderer.renderer, sceneRenderer.camera, true) //没用,为何_trimTiles的while无法进入
  164. */
  165. player.model.traverse(e => {
  166. e.geometry && e.geometry.dispose()
  167. if (e.material) {
  168. e.material.map && e.material.map.dispose()
  169. if (e.material.uniforms && e.material.uniforms.map && e.material.uniforms.map.value) {
  170. e.material.uniforms.map.value.dispose()
  171. }
  172. }
  173. }) //效果甚微
  174. /* let sceneRenderer = child.__sdk.core.get('SceneRenderer')
  175. sceneRenderer.renderer.render(sceneRenderer.scene, sceneRenderer.camera)
  176. */
  177. } catch (e) {
  178. console.log(e)
  179. }
  180. }
  181. }
  182. }
  183. //不知道删除iframe时是否那些模型还在内存里,需要释放吗? 如果要需要加一个事件
  184. } else {
  185. }
  186. }
  187. window.THREE = THREE
  188. //isLocal = false
  189. let autoLoads = /* window.autoLoads = */ []
  190. let readyToAddModel
  191. let mainBackground = viewer.background
  192. const units = { 1: 'metric', 2: 'imperial' }
  193. let getMeasureType = function (type, unit = 1) {
  194. let info
  195. switch (type) {
  196. case 'free':
  197. info = { measureType: 'Distance' }
  198. break
  199. case 'area':
  200. info = { measureType: 'Area' }
  201. break
  202. case 'vertical':
  203. info = { measureType: 'Ver Distance' }
  204. break
  205. default:
  206. console.error('无此 measure type')
  207. }
  208. info.unit = units[unit]
  209. return info
  210. }
  211. let getMeasureFunction = function (measure, bus) {
  212. measure.addEventListener('highlight', (e) => {
  213. //console.log('3d->2d highlight',e.state)
  214. bus.emit('highlight', e.state)
  215. })
  216. measure.addEventListener('marker_dropped', (e) => {//拖拽结束后发送changeCallBack
  217. if (measure.parent) {
  218. //未被删除
  219. bus.emit('update', [
  220. measure.dataset_points.map(p => p.clone()),
  221. measure.points_datasets
  222. ])
  223. }
  224. })
  225. return {
  226. /* quit: () => {
  227. Potree.Log('quit结束且删除: ' + measure.id, '#00c7b2')
  228. viewer.dispatchEvent({ type: 'cancel_insertions', remove: true, measure })
  229. }, //触发结束。退出测量模式,清除之前操作 */
  230. destroy: () => {
  231. viewer.dispatchEvent({ type: 'cancel_insertions', remove: true, measure })
  232. viewer.scene.removeMeasurement(measure)
  233. },
  234. /* getPoints: () => {
  235. return measure.points
  236. },
  237. getDatasetLocations: () => {
  238. return measure.dataset_points
  239. },
  240. getDatasets: () => {
  241. return measure.points_datasets
  242. },
  243. getDatasetId: () => {
  244. return measure.datasetId
  245. }, */
  246. getArea: () => {
  247. return measure.area //{value:area, string:..}
  248. },
  249. getDistance: () => {
  250. if (measure.points.length < 2) return 0
  251. var value = measure.points[0].distanceTo(measure.points[1])
  252. return {
  253. value, //米
  254. string: measure.getConvertString(value, 'distance')
  255. }
  256. },
  257. //手动开启或关闭:
  258. show: () => {
  259. Potree.Utils.updateVisible(measure, 'inListByUser', true)
  260. },
  261. hide: () => {
  262. Potree.Utils.updateVisible(measure, 'inListByUser', false)
  263. },
  264. fly() {
  265. let result = viewer.focusOnObject(measure, 'measure', 1200)
  266. return result.msg ? result.msg : result.promise
  267. //返回值 1 deferred 表示即将位移 2 'posNoChange' 表示已在最佳位置 3 'tooFar' 表示距离最佳位置太远
  268. },
  269. changeSelect(isHight) {
  270. console.log('2d->3d isHight ', isHight)
  271. measure.setSelected(isHight, 'byList')
  272. },
  273. }
  274. }
  275. let sdk = {
  276. sceneBus, mapBus,
  277. canTurnToPanoMode(pos) {
  278. pos = pos ? new THREE.Vector3().copy(pos) : viewer.images360.position
  279. let pano = viewer.images360.findNearestPano(pos)
  280. if (pano && pano.position.distanceTo(pos) < Potree.config.panoFieldRadius * pano.pointcloud.scale.x) {
  281. return {model:pano.pointcloud.result_}
  282. }
  283. //poschange后会调用这个,如果返回false会变为点云模式,且不会自动变回原先的模式
  284. },
  285. getPositionByScreen(pos2d, hopeModelId) {//通过屏幕坐标获取真实坐标 . hopeModelId: 如果指定了模型,优先返回hopeModelId上的intersect
  286. //console.log('getPositionByScreen',hopeModelId)
  287. hopeModelId = null
  288. let worldPos, localPos, modelId, intersect
  289. let Handler = viewer.inputHandler
  290. let reGet = () => {//不使用当前鼠标所在位置的intersect,单独算
  291. pos2d.clientX = pos2d.x
  292. pos2d.clientY = pos2d.y
  293. pos2d.onlyGetIntersect = true
  294. pos2d.whichPointcloud = true
  295. if (hopeModelId != void 0) {//隐藏其他的模型
  296. let models = MergeEditor.getAllObjects()
  297. models.forEach(model => {
  298. Potree.Utils.updateVisible(model, 'forPick', model.dataset_id == hopeModelId)
  299. })
  300. }
  301. let intersect2 = Handler.onMouseMove(pos2d)
  302. if (hopeModelId != void 0) {//恢复
  303. let models = MergeEditor.getAllObjects()
  304. models.forEach(model => {
  305. Potree.Utils.updateVisible(model, 'forPick', true)
  306. })
  307. }
  308. if (intersect2 && intersect2.location) {
  309. intersect = intersect2
  310. }
  311. }
  312. if (pos2d && pos2d.inDrag) {
  313. reGet()
  314. } else {
  315. intersect = Handler.intersect
  316. if (intersect) {
  317. modelId = intersect.pointcloud ? intersect.pointcloud.dataset_id : intersect.object.dataset_id
  318. if (hopeModelId != void 0 && modelId != hopeModelId) {
  319. reGet()
  320. }
  321. }
  322. }
  323. if (intersect && intersect.location) {
  324. modelId = intersect.pointcloud ? intersect.pointcloud.dataset_id : intersect.object.dataset_id
  325. /* if(hopeModelId != void 0 && modelId != hopeModelId){
  326. return null
  327. } */
  328. worldPos = intersect.location.clone()
  329. localPos = Potree.Utils.datasetPosTransform({ toDataset: true, datasetId: modelId, position: worldPos })
  330. } else return null
  331. return { worldPos, modelId, localPos }
  332. },
  333. getScreenByPosition(pos3d, modelId, canShelter/* , disToCameraLimit */) {//通过模型局部坐标获取屏幕坐标
  334. //console.log('getScreenByPoint ')
  335. let isLocal = modelId != void 0
  336. pos3d = new THREE.Vector3().copy(pos3d)
  337. let worldPos = isLocal ? Potree.Utils.datasetPosTransform({ fromDataset: true, datasetId: modelId, position: pos3d }) : pos3d
  338. if (!worldPos) return
  339. if (canShelter) {
  340. if (viewer.inputHandler.ifBlockedByIntersect(worldPos, 0.1, true)) return { trueSide: false };
  341. }
  342. var viewport = viewer.mainViewport
  343. var camera = viewport.camera
  344. var dom = viewer.renderArea
  345. if (tagLimitDis != void 0) {
  346. if (camera.position.distanceToSquared(worldPos) > Math.pow(tagLimitDis, 2)) return false
  347. }
  348. //console.log('getScreenByPoint ' + pos3d.toArray())
  349. return Potree.Utils.getPos2d(worldPos, viewport, dom)
  350. },
  351. setCameraFov(fov) {
  352. viewer.setFOV(fov)
  353. },
  354. screenshot: (width, height/* , bgOpacity=0 */ ) => {//
  355. //截图
  356. let bgOpacity = Potree.settings.showCesium ? 0 : 1 /* viewer.background == 'skybox' */ //因为要画map底图所以上层只能透明。之后需要的话再改
  357. console.log('bgOpacity', bgOpacity)
  358. Potree.Utils.updateVisible(MergeEditor.boxHelper, 'screenshot', false)
  359. var { getImagePromise, finishPromise } = viewer.startScreenshot({ type: 'default', /* useRenderTarget:true, */bgOpacity }, width, height)
  360. var deferred = $.Deferred();
  361. finishPromise.done(({ dataUrl }) => {
  362. if(Potree.settings.displayMode != 'showPanos' && Potree.settings.showCesium){//need map background
  363. Potree.cesScreenshot(width, height).done((mapBGurl)=>{
  364. let img = new Image(); img.src = dataUrl
  365. let imgBG = new Image(); imgBG.src = mapBGurl
  366. let loadCount = 0
  367. img.onload = imgBG.onload = ()=>{
  368. loadCount++;
  369. if(loadCount == 2){
  370. let url = Potree.Common.imgAddLabel(imgBG,img,{leftRatioToImg:0,topRatioToImg:0})
  371. deferred.resolve(url)
  372. }
  373. }
  374. })
  375. }else{
  376. deferred.resolve(dataUrl)
  377. }
  378. Potree.Utils.updateVisible(MergeEditor.boxHelper, 'screenshot', true)
  379. })
  380. return deferred.promise()
  381. },
  382. getPose() {//获取当前点位和朝向
  383. const camera = viewer.scene.getActiveCamera()
  384. const target = viewer.scene.view.getPivot().clone()
  385. const position = viewer.scene.view.position.clone()
  386. const pose = { position, target, displayMode:Potree.settings.displayMode }
  387. if(Potree.settings.displayMode == 'showPanos'){
  388. let model = viewer.images360.currentPano.pointcloud
  389. pose.panoId = viewer.images360.currentPano.originID
  390. pose.model = model.result_
  391. pose.posInModel = Potree.Utils.datasetPosTransform({ toDataset: true, position: camera.position.clone(), object:model })
  392. pose.rotInModel = Potree.Utils.datasetRotTransform({ toDataset: true, quaternion: camera.quaternion.clone(), getQuaternion: true, pointcloud:model }).toArray() //拿第一个数据集
  393. }
  394. //console.log('getPose',position, target)
  395. return pose
  396. },
  397. comeTo(o = {}) {
  398. //console.log('comeTo',o.position, o.target)
  399. //飞到某个点
  400. let deferred = $.Deferred()
  401. if(o.panoId != void 0){
  402. let model = o.model.model
  403. let pano = model.panos.find(a=>a.originID == o.panoId)
  404. if(pano){
  405. o.rotInModel = new THREE.Quaternion().fromArray(o.rotInModel)
  406. let quaternion = Potree.Utils.datasetRotTransform({ fromDataset: true, quaternion: o.rotInModel, getQuaternion: true, object:model})
  407. o.model.flyInPano(pano, {quaternion, duration:0, callback(){
  408. o.callback && o.callback()
  409. deferred.resolve(true)
  410. }})
  411. return deferred.promise()
  412. }else{
  413. console.warn('没有找到漫游点',o)
  414. }
  415. }else if(requestInPano){
  416. requestInPano.result_.flyOutPano()
  417. }else{
  418. if (o.modelId != void 0) {
  419. ['position', 'target'].forEach(e => {
  420. if (o[e]) {
  421. o[e] = Potree.Utils.datasetPosTransform({ fromDataset: true, datasetId: o.modelId, position: o[e] })
  422. }
  423. })
  424. }
  425. }
  426. if (o.distance) {
  427. let position = o.target || o.position
  428. return viewer.focusOnObject({ position }, 'tag', null, { distance: o.distance }).promise
  429. }
  430. viewer.scene.view.setView($.extend({}, o, {
  431. duration: o.dur,
  432. callback: () => {
  433. o.callback && o.callback()
  434. deferred.resolve(true)
  435. }
  436. }))
  437. return deferred.promise()
  438. },
  439. setBackdrop(sky, type, { scale, rotate }) {//天空盒背景
  440. //console.log('天空盒背景', sky,type)
  441. let setGroundAndText = (color) => {
  442. MergeEditor.secondCompass.dom.find(".dirText").css({ 'color': color })
  443. viewer.compass.dom.find(".dirText").css({ 'color': color })
  444. MergeEditor.ground.material.uniforms.uColor.value.set(color)
  445. //MergeEditor.ground.children[0].material.color.set(color)
  446. }
  447. viewer.dispatchEvent('content_changed')
  448. if(type == 'map'){
  449. MergeEditor.setGroundPlaneImg(null)
  450. viewer.setBackground(mainBackground)
  451. Potree.settings.showCesium = true
  452. buildMap()
  453. viewer.backgroundOpacity = 0
  454. return
  455. }else{
  456. Potree.settings.showCesium = false
  457. }
  458. if (type == 'bimg') {//地面图
  459. MergeEditor.setGroundPlaneImg(sky, scale, rotate)
  460. setGroundAndText('#e0e0e0')
  461. viewer.setBackground(mainBackground)
  462. } else {
  463. MergeEditor.setGroundPlaneImg(null)
  464. if (sky == 'none') {
  465. viewer.setBackground(mainBackground)
  466. setGroundAndText('#eee')
  467. } else if (sky[0] == '#') {
  468. viewer.setBackground(new THREE.Color(sky))
  469. let color = sky == '#fff' ? '#666' : sky == '#333' ? '#eee' : '#bbb' //反相
  470. setGroundAndText(color)
  471. } else if (type == 'image-map' || type == 'vector-map') {//影像|矢量 地图
  472. } else {//环境
  473. viewer.setBackground('skybox', sky)
  474. setGroundAndText('#e0e0e0')
  475. }
  476. }
  477. },
  478. switchMapType(type) {
  479. let map = viewer.mapViewer.mapLayer.maps.find(e => e.name == 'map')
  480. map.switchStyle(type/* map.style == 'satellite' ? 'standard' : 'satellite' */)
  481. },
  482. enableMap(mapArea, latlng) {
  483. if (!viewer.mapViewer) {
  484. //--------------------------------
  485. viewer.mapViewer = new Potree.MapViewer(mapArea)
  486. viewer.mapViewer.initProjection()
  487. //focus
  488. let boundSize = new THREE.Vector3(200, 150, 1).max(viewer.bound.boundSize)
  489. viewer.mapViewer.addEventListener('viewerResize', () => {
  490. viewer.mapViewer.moveTo(viewer.bound.center, boundSize, 0)
  491. }, { once: true })
  492. }
  493. },
  494. enterSceneGuide(pathArr) {//导览 (不需要修改参数)
  495. let editor = viewer.modules.CamAniEditor
  496. console.log('pathArr', pathArr)
  497. //console.log('enterSceneGuide',pathArr)
  498. pathArr.forEach(e=>{
  499. if(e.panoId != void 0){
  500. e.model = e.model.model
  501. }
  502. })
  503. let data = {
  504. //duration: pathArr.slice(0, pathArr.length - 1).reduce(function (total, currentValue) { return total + currentValue.time }, 0), //总时长(要去掉最后一个,因为已到终点,该点time无意义)
  505. points: pathArr,
  506. useDurSlice: true
  507. }
  508. let ani = editor.createMulAnimation(data)
  509. //注:最多只存在一条导览
  510. let bus = mitt()
  511. //播放完成
  512. ani.event_.addEventListener('playDone', () => {
  513. bus.emit('playComplete')
  514. viewer.images360.panos.forEach(e=>e.marker && Potree.Utils.updateVisible(e, 'playAni', true))
  515. })
  516. //切换点
  517. ani.event_.addEventListener('updateCurrentIndex', e => {
  518. bus.emit('changePoint', e.currentIndex + 1)
  519. })
  520. return {
  521. bus,
  522. play() {
  523. MergeEditor.selectModel(null)
  524. viewer.images360.panos.forEach(e=>e.marker && Potree.Utils.updateVisible(e, 'playAni', false))
  525. ani.play()
  526. },
  527. pause() {
  528. viewer.images360.panos.forEach(e=>e.marker && Potree.Utils.updateVisible(e, 'playAni', true))
  529. ani.stop()
  530. },
  531. clear() {
  532. ani.remove()
  533. },
  534. }
  535. },
  536. //[path1, paht2], { time, speed }
  537. calcPathInfo(paths, info) { //传入的time, speed仅有一个。返回完整的 time, speed
  538. //这一版的control似乎无法在某个位置上改变角度,位置和角度一般都是一起变的,所以先不增加单位更换功能。
  539. let pos1 = new THREE.Vector3().copy(paths[0].position)
  540. let pos2 = new THREE.Vector3().copy(paths[1].position)
  541. let dis = pos1.distanceTo(pos2)
  542. if (info.time != void 0) {
  543. info.speed = dis / info.time
  544. } else {
  545. info.time = dis / info.speed
  546. }
  547. return info
  548. },
  549. addModel(props) {
  550. let bus = props.bus = mitt()
  551. //console.log('addModel',props)
  552. props.isFirstLoad = isLocal ? props.bottom == void 0 : (props.isDynamicAdded || props.mode == 'single') // 在编辑时用户添加的 或 展示单个模型 (props.mode='single'模型展示页, props.mode='many'融合页)
  553. if (props.opacity == void 0) props.opacity = 1
  554. if (props.type == 'obj') props.type = 'glb'
  555. props.scale /= 100
  556. if (props.rotation) {
  557. if (props.rotation._x == void 0 && props.rotation.x != void 0) {
  558. props.rotation = new THREE.Euler().setFromVector3(props.rotation)
  559. }
  560. }
  561. let getDefaultRotation = () => {
  562. if(ModelTypes[props.fromType]?.rot90 && props.type != 'glb'){
  563. return new THREE.Euler(Math.PI / 2, 0, 0)
  564. } else return new THREE.Euler(0, 0, 0)
  565. }
  566. if (!props.isFirstLoad) {
  567. if (autoLoads.length == 0) { //首次加载
  568. setTimeout(() => {
  569. let sizes = autoLoads.map(e => e.size || 0)
  570. console.log('需要请求加载的模型大小为', sizes, '总大小', sizes.reduce(function (total, currentValue) {
  571. let current = parseFloat(currentValue)
  572. return total + ((typeof currentValue == 'number' || currentValue.includes('M')) ? current : current / 1024)
  573. }, 0))
  574. readyToAddModel = true //准备开始加载
  575. loadNext()//startLoad(autoLoads[0])
  576. }, 30)
  577. }
  578. autoLoads.push(props)
  579. readyToAddModel = false
  580. } else {
  581. readyToAddModel = true
  582. props.rotation = getDefaultRotation()
  583. }
  584. let model
  585. let done = (model_) => {
  586. model = model_
  587. model.result_ = result
  588. model.props = props
  589. result.model = model
  590. model.fromType = ModelTypes[props.fromType].name
  591. if (!props.isFirstLoad) {
  592. model.visible = false//先不显示,防止卡顿
  593. }
  594. model.showInPano = props.raw.showInPano
  595. props.opacity < 100 && result.changeOpacity(props.opacity)
  596. model.addEventListener('changeSelect', (e) => {
  597. bus.emit('changeSelect', e.selected)
  598. })
  599. let lastState = {}
  600. model.addEventListener('transformChanged', (e) => {
  601. let msg = {}
  602. if (!lastState.position || !model.position.equals(lastState.position)) {
  603. lastState.position = msg.position = model.position.clone()
  604. }
  605. if (!lastState.rotation || !model.rotation.equals(lastState.rotation)) {
  606. lastState.rotation = msg.rotation = model.rotation.clone()
  607. }
  608. if (lastState.scale == void 0 || model.scale.x * 100 != lastState.scale) {
  609. lastState.scale = msg.scale = model.scale.x * 100
  610. }
  611. msg = Potree.Common.CloneObject(msg)
  612. //console.log(msg)
  613. bus.emit('transformChanged', msg)
  614. })
  615. spliceFromArr(model, props, true)
  616. model.addEventListener('changeSelect', (e) => {
  617. MergeEditor.transformControls.visible && e.selected && MergeEditor.transformControls.attach(model, e.clickPos) //: MergeEditor.transformControls.detach()
  618. })
  619. if (props.mode == 'single') {//模型查看页
  620. MergeEditor.noNeedSelection = true
  621. setTimeout(() => {
  622. MergeEditor.focusOn([model], 1000, true, true)
  623. }, 1)
  624. }
  625. if(ModelTypes[props.fromType].panos4dkk){
  626. Potree.load4dkkPanos(props.raw.num, model, getDefaultRotation(), () => {
  627. bus.emit('loadDone')
  628. }, props.fromType == 0 ? '2k' : '4k' ) //看看场景是2k
  629. } else {
  630. bus.emit('loadDone')
  631. }
  632. //console.log('loadDone' )
  633. }
  634. let progressFun = (progress) => {
  635. bus.emit('loadProgress', progress)
  636. }
  637. let onError = function (xhr) {
  638. bus.emit('loadError', xhr)
  639. console.log('loadError!!!!!!!!!', Potree.Common.getNameFromURL(props.url), props.size, xhr)
  640. spliceFromArr(model, props, false)
  641. }
  642. try {
  643. props.url = JSON.parse(props.url) //去掉 '\'
  644. } catch (e) { }
  645. props.done = done; props.progressFun = progressFun; props.onError = onError
  646. if (readyToAddModel) {
  647. if (autoLoads.filter(e => e.loading).length < maxLoadingCount) {
  648. startLoad(props)
  649. }
  650. }
  651. let scaleMeasure
  652. let result = {
  653. bus,
  654. model,
  655. getDefaultRotation,
  656. supportPano() { //是否支持全景图
  657. return model?.panos?.length > 0
  658. },
  659. flyInPano(pano, {dontFly, quaternion, duration}={}) {// 飞入全景图
  660. requestInPano = model
  661. pano = pano || viewer.images360.findNearestPano(null, model.panos)
  662. if (pano) {
  663. dontFly || viewer.images360.flyToPano({ pano, canCancelLast: true, quaternion, duration})
  664. Potree.settings.displayMode = 'showPanos'
  665. }
  666. },
  667. flyOutPano() {// 飞出全景图(就是切换到正常融合视角)
  668. requestInPano = false
  669. Potree.settings.displayMode = 'showPointCloud'
  670. /* setTimeout(() => {//在下一帧再变,因为3dtiles需要更新一下才会显示tiles
  671. if (!requestInPano) {
  672. Potree.settings.displayMode = 'showPointCloud'
  673. Potree.Utils.updateVisible(MergeEditor.boxHelper, 'showPanos', true)
  674. }
  675. }, 50) */
  676. },
  677. changeShow(show) {
  678. props.show = show //for autoLoads show model
  679. if (model) {
  680. Potree.Utils.updateVisible(model, 'datasetSelection', show)
  681. if (model.panos) {
  682. model.panos.forEach(e => e.setEnable(show))
  683. }
  684. viewer.dispatchEvent('content_changed')
  685. }
  686. },
  687. changeSelect(state) {
  688. console.error('select', state)
  689. if (model) {
  690. let fly = viewer.images360.latestRequestMode != 'showPanos'
  691. MergeEditor.selectModel(model, state, fly, true)
  692. //console.log('changeSelect', props.id, state)
  693. }
  694. },
  695. changeScale(s) {
  696. if (model) {
  697. s /= 100
  698. if (model.scale.x == s) return
  699. //MergeEditor.history.beforeChange(model)//但不知道什么时候结束拖拽
  700. model.scale.set(s, s, s)
  701. model.isPointcloud && model.changePointSize(/* Potree.config.material.realPointSize * s */)
  702. model.dispatchEvent("scale_changed")
  703. }
  704. },
  705. changeOpacity(opacity) { //见笔记:透明物体的材质设置
  706. if (opacity == void 0) opacity = 100
  707. opacity /= 100
  708. MergeEditor.changeOpacity(model, opacity)
  709. },
  710. changeBottom(z) {
  711. /* model && MergeEditor.setModelBtmHeight(model,z)
  712. model.dispatchEvent('transformChanged') //改了position */
  713. },
  714. changePosition(pos) {//校准取消时执行
  715. console.log('changePosition', pos.x, pos.y, pos.z)
  716. model && model.position.copy(pos)
  717. model.dispatchEvent({ type: 'position_changed' })
  718. },
  719. changeRotation(rot) {//校准取消时执行
  720. console.log('changeRotation', rot.x, rot.y, rot.z)
  721. model && model.rotation.setFromVector3(rot)
  722. model.dispatchEvent({ type: 'rotation_changed' })
  723. },
  724. enterRotateMode() {
  725. if (model) {
  726. if (MergeEditor.split) {//分屏校准
  727. MergeEditor.setTransformState('rotate')
  728. MergeEditor.transformControls2.attach(model)
  729. MergeEditor.transformControls2.mode = 'rotate'
  730. }
  731. MergeEditor.transformControls.attach(model)
  732. MergeEditor.transformControls.mode = 'rotate'
  733. }
  734. },
  735. enterMoveMode() {
  736. console.log('enterMoveMode')
  737. if (model) {
  738. if (MergeEditor.split) {//分屏校准
  739. MergeEditor.setTransformState('translate')
  740. MergeEditor.transformControls2.attach(model)
  741. MergeEditor.transformControls2.mode = 'translate'
  742. }
  743. MergeEditor.transformControls.attach(model)
  744. MergeEditor.transformControls.mode = 'translate'
  745. }
  746. },
  747. leaveTransform() {
  748. console.log('leaveTransform')
  749. if (MergeEditor.split) {//分屏校准
  750. MergeEditor.setTransformState(null)
  751. } else {
  752. MergeEditor.transformControls.detach()
  753. MergeEditor.transformControls2.detach()
  754. }
  755. MergeEditor.history.clear()
  756. },
  757. enterAlignment() {//开始校准
  758. result.leaveTransform()
  759. MergeEditor.enterSplit()
  760. //console.log('enterAlignment',model.position, model.rotation)
  761. let bus = new mitt()
  762. /* MergeEditor.transformControls.attach(model)
  763. MergeEditor.transformControls.mode = 'translate' */
  764. return {
  765. bus
  766. }
  767. },
  768. leaveAlignment() {
  769. //console.log('leaveAlignment',model.position, model.rotation)
  770. MergeEditor.leaveSplit()
  771. MergeEditor.transformControls.detach()
  772. MergeEditor.transformControls2.detach()
  773. },
  774. enterScaleSet() {//设置比例
  775. let bus = new mitt()
  776. let length, measureBuilded;
  777. //viewer.outlinePass.selectedObjects = []
  778. if (!Potree.Utils.isInsideFrustum(model.boundingBox.clone().applyMatrix4(model.matrixWorld), viewer.scene.getActiveCamera())) {
  779. MergeEditor.focusOn(model, 600)
  780. }
  781. MergeEditor.getAllObjects().forEach(m => {//隐藏其他的模型
  782. if (m != model) Potree.Utils.updateVisible(m, 'enterScaleSet', false)
  783. })
  784. let setScale = () => {
  785. if (length == void 0 || !measureBuilded) return
  786. let vec = new THREE.Vector3().subVectors(viewer.mainViewport.camera.position, scaleMeasure.points[1])
  787. let s = length / (scaleMeasure.points[0].distanceTo(scaleMeasure.points[1]))
  788. result.changeScale(model.scale.x * s * 100)
  789. /* setTimeout(()=>{
  790. viewer.focusOnObject(scaleMeasure , 'measure', 500)
  791. },1) */
  792. let newCamPos = new THREE.Vector3().addVectors(scaleMeasure.points[1], vec.multiplyScalar(s))
  793. viewer.scene.view.setView({
  794. position: newCamPos, target: scaleMeasure.getCenter(), duration: 0, callback: () => {
  795. //更改target到measure中心的好处就是可以让相机绕measure中心转,坏处是每次更改都会变一下画面
  796. }
  797. })
  798. }
  799. return {
  800. bus,
  801. setLength(v) {
  802. if (!v) return
  803. length = v
  804. setScale()
  805. },
  806. startMeasure() {
  807. if (scaleMeasure) {
  808. viewer.dispatchEvent({ type: 'cancel_insertions', remove: true, measure: scaleMeasure })
  809. viewer.scene.removeMeasurement(scaleMeasure)
  810. }
  811. measureBuilded = false
  812. scaleMeasure = viewer.measuringTool.startInsertion(
  813. { measureType: "Distance", unit: "metric" },
  814. () => {
  815. //done:
  816. //bus.emit('end' ) //完成
  817. measureBuilded = true
  818. setScale()
  819. },
  820. () => {
  821. //cancel
  822. //bus.emit('quit') //删除
  823. }
  824. )
  825. scaleMeasure.addEventListener('marker_dropped', (e) => {//拖拽结束后发送changeCallBack
  826. if (scaleMeasure.parent) {
  827. //未被删除
  828. measureBuilded && setScale()
  829. }
  830. })
  831. }
  832. }
  833. },
  834. leaveScaleSet() {
  835. if (scaleMeasure) {
  836. viewer.dispatchEvent({ type: 'cancel_insertions', remove: true, measure: scaleMeasure })
  837. viewer.scene.removeMeasurement(scaleMeasure)
  838. scaleMeasure = null
  839. }
  840. //viewer.outlinePass.selectedObjects = [model];
  841. MergeEditor.getAllObjects().forEach(m => {//恢复其他的模型
  842. if (m != model) Potree.Utils.updateVisible(m, 'enterScaleSet', true)
  843. })
  844. },
  845. destroy() {
  846. model && MergeEditor.removeModel(model)
  847. result.changeSelect(false)
  848. viewer.dispatchEvent('content_changed')
  849. }
  850. }
  851. return result
  852. },
  853. //测量线的点都附着于各个模型,当模型变化时,点跟着变化。
  854. // 新的测量创建方法,传入type 返回新测量对象
  855. startMeasure(type) {
  856. // 寻创建的测量对象有上面绘画测量对象的所有方法
  857. const bus = mitt()
  858. let info = getMeasureType(type)
  859. let measure = viewer.measuringTool.startInsertion(
  860. info,
  861. () => {
  862. //done:
  863. /* bus.emit('submit', {
  864. dataset_points: measure.dataset_points.map(p=>p.clone()) ,
  865. points_datasets: measure.points_datasets
  866. } ) //完成 */
  867. bus.emit('submit')
  868. bus.emit('update', [
  869. measure.dataset_points.map(p => p.clone()),
  870. measure.points_datasets
  871. ])
  872. },
  873. () => {
  874. //cancel
  875. bus.emit('cancel'/* , ret */) //删除
  876. }
  877. )
  878. Potree.Log('startMeasure: ' + measure.id, '#00c7b2')
  879. /* let cancel = ()=>{
  880. Potree.Log('clear删除: ' + measure.id, '#00c7b2')
  881. viewer.dispatchEvent({ type: 'cancel_insertions', remove: true, measure })
  882. viewer.scene.removeMeasurement(measure)
  883. } */
  884. let result = {
  885. bus,
  886. ...getMeasureFunction(measure, bus),
  887. }
  888. /* StartMeasure = Measure & {
  889. // 多了cancel 取消测量的事件,没有参数
  890. // 多了invalidPoint 当用户测量了无效点时的事件,抛出无效原因
  891. bus: Emitter<{ cancel: void; invalidPoint: string }>
  892. } */
  893. return result
  894. },
  895. // 绘画测量线(非新增使用)
  896. // type = 'free' (自由) || 'vertical' (垂直) || 'area' (面积)
  897. // positions 点数组 构成如下 [{ point: {x,y,z}, modelId: 1 }]
  898. drawMeasure(type, dataset_points, points_datasets) {
  899. // 返回测量对象有如下
  900. const bus = mitt()
  901. let info = getMeasureType(type /* , unit */)
  902. //info.points = positions
  903. info.dataset_points = dataset_points
  904. info.points_datasets = points_datasets
  905. //info.sid = sid
  906. info.bus = bus
  907. let measure = viewer.measuringTool.createMeasureFromData(info)
  908. if (!measure) return { bus }
  909. Potree.Log('drawMeasure由数据新建: ' + measure.id, '#00c7b2')
  910. let result = {
  911. bus,
  912. setPositions(dataset_points, points_datasets) {//用于恢复measure的点,不会修改点的个数
  913. measure.dataset_points = dataset_points.map(e => {
  914. return e && new THREE.Vector3().copy(e)
  915. })
  916. measure.points_datasets = points_datasets
  917. measure.points = measure.dataset_points.map((p, i) => {
  918. return Potree.Utils.datasetPosTransform({ fromDataset: true, datasetId: measure.points_datasets[i], position: p })
  919. })
  920. measure.getPoint2dInfo(measure.points)
  921. measure.update({ ifUpdateMarkers: true })
  922. measure.setSelected(false)//隐藏edgelabel
  923. },
  924. ...getMeasureFunction(measure, bus),
  925. }
  926. return result
  927. },
  928. addTag(info) {//加标签
  929. let bus = mitt()
  930. let tag
  931. let done = () => {
  932. bus.emit('added')
  933. bus.emit('update', { position: tag.position.clone(), normal: o.normal.clone(), modelId: tag.root.dataset_id })
  934. tag = tag_
  935. tag.spot.addEventListener('mouseover', () => {
  936. bus.emit('hoverState', true)
  937. })
  938. tag.spot.addEventListener('mouseout', () => {
  939. bus.emit('hoverState', false)
  940. })
  941. }
  942. if (!info.position) {
  943. viewer.tagTool.startInsertion().done(tag_ => {
  944. done()
  945. })
  946. } else {
  947. info.root = MergeEditor.getAllObjects().find(e => e.dataset_id == info.modelId)
  948. if (!info.root) {
  949. console.error('没有找到该modelId')
  950. }
  951. tag = viewer.tagTool.createTagFromData(info)
  952. done()
  953. }
  954. let result = {
  955. bus,
  956. getScreenPos() {
  957. let pos3d = new THREE.Vector3().setFromMatrixPosition(tag.matrixWorld)
  958. return sdk.getScreenByPosition(pos3d)
  959. },
  960. show() {
  961. Potree.Utils.updateVisible(tag, 'byList', true)
  962. },
  963. hide() {
  964. Potree.Utils.updateVisible(tag, 'byList', false)
  965. },
  966. destroy() {
  967. if (tag) {
  968. tag.dispose()
  969. }
  970. viewer.dispatchEvent({ type: 'cancel_insertions', remove: true })
  971. },
  972. changeTitle(title) {
  973. tag.changeTitle(title)
  974. }
  975. }
  976. return result
  977. },
  978. showGrid() {
  979. Potree.Utils.updateVisible(viewer.modules.MergeEditor.ground, 'hideGrid', true)
  980. viewer.dispatchEvent('content_changed')
  981. },
  982. hideGrid() {
  983. Potree.Utils.updateVisible(viewer.modules.MergeEditor.ground, 'hideGrid', false)
  984. viewer.dispatchEvent('content_changed')
  985. }
  986. }
  987. function spliceFromArr(model, props, loaded){
  988. //let autoLoads.find()
  989. props.loadFinish = true
  990. props.loading = false
  991. if (loaded) {
  992. props.loaded = true
  993. props.model = model
  994. } else {
  995. props.error = true
  996. }
  997. /* let haventLoad = autoLoads.filter(e=>!e.loading && !e.loadFinish);
  998. if( haventLoad[0]){
  999. startLoad(haventLoad[0])
  1000. */
  1001. if (!loadNext()) {
  1002. if (autoLoads.filter(e => !e.loadFinish).length == 0 && autoLoads.filter(e => e.loaded).length > 0 && !props.isFirstLoad) {//设置相机位置:当自动开始加载第一个模型时(其余的也跟着自动加载),等这批加载完后;
  1003. let autoLoadsDone = autoLoads.filter(e => e.loaded).map(e => e.model)
  1004. let loadTimeCost = Date.now() - loadStartTime
  1005. console.log('所有模型加载完毕, 耗时', parseInt(loadTimeCost) )
  1006. autoLoads.filter(e => e.loaded && e.show).forEach(e => e.model.visible = true)
  1007. MergeEditor.focusOn(autoLoadsDone, 1000, true, true)
  1008. autoLoads.length = 0
  1009. }
  1010. }
  1011. }
  1012. function loadNext(){
  1013. let haventLoad = autoLoads.filter(e => !e.loading && !e.loadFinish);
  1014. let loading = autoLoads.filter(e => e.loading);
  1015. let needLoad = haventLoad.slice(0, maxLoadingCount - loading.length)
  1016. needLoad.forEach(e => startLoad(e))
  1017. return haventLoad.length > 0
  1018. }
  1019. function startLoad(prop){
  1020. /* if(prop.raw.visible !== 1){//用于临时隐藏
  1021. setTimeout(()=>{
  1022. spliceFromArr(null, prop, false)
  1023. prop.bus.emit('loadError' )
  1024. },1)
  1025. return
  1026. } */
  1027. if(prop.loading || prop.loadFinish)return
  1028. Potree.Log(`--开始加载--`, { font: { color: '#f68' } });
  1029. console.log('id:', prop.id, ', title:', prop.title, ', filename:', Potree.Common.getNameFromURL(prop.url), ', type:', prop.type, prop)
  1030. prop.unlit = prop.renderType != 'normal'
  1031. prop.maximumScreenSpaceError = 70
  1032. prop.prefix = prop.raw.prefix
  1033. Potree.addModel(prop, prop.done, prop.progressFun, prop.onError)
  1034. prop.loading = true
  1035. }
  1036. function buildMap(){
  1037. if (Potree.settings.showCesium && !window.cesiumViewer) {
  1038. viewer.backgroundOpacity = 0
  1039. Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2ZGM2YzY0ZC1kNWE0LTRiYTgtYTkwNS1kYmJiODRjMWUwMmQiLCJpZCI6MjMzMTQ1LCJpYXQiOjE3MjI5OTUwNTB9.niqpkl6xOkQ2KeJjelyDDDydmSGqKXKb5cX2NyxSNAw'
  1040. window.cesiumViewer = new Cesium.Viewer('app', {
  1041. useDefaultRenderLoop: true,
  1042. requestRenderMode: true, //add 只有需要render时才会render,如tile加载完后、镜头移动后
  1043. animation: false,
  1044. baseLayerPicker: false,
  1045. fullscreenButton: false,
  1046. geocoder: false,
  1047. homeButton: false,
  1048. infoBox: false,
  1049. sceneModePicker: false,
  1050. selectionIndicator: false,
  1051. timeline: false,
  1052. navigationHelpButton: false,
  1053. //imageryProvider : Cesium.createOpenStreetMapImageryProvider({url : 'https://a.tile.openstreetmap.org/'}),
  1054. imageryProvider: Cesium.UrlTemplateImageryProvider({ //直接用84坐标,不用转高德
  1055. //"https://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&style=7&yrs=m&x=${x}&y=${y}&z=${z}" //
  1056. //url : 'https://webst0{0-7}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}&token=YOUR_API_KEY',
  1057. url: 'https://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}&token=YOUR_API_KEY',
  1058. minimumLevel: 0,
  1059. maximumLevel: 19
  1060. }),
  1061. //高德秘钥版 imageryProvider: new Cesium.AmapImageryProvider({key, mapStyle: 'normal'})
  1062. //报错 401 (Unauthorized) 的方法 https://blog.csdn.net/LBY_XK/article/details/121992641
  1063. terrainShadows: Cesium.ShadowMode.DISABLED, //terrain地形
  1064. });
  1065. //lonlat = [113.595236803415,22.3665168584444]//[113.600356,22.364093]
  1066. Potree.setLonlat(lonlat[0], lonlat[1])
  1067. Potree.cesScreenshot = (w,h)=>{
  1068. console.log('cesScreenshot',w,h)
  1069. cesiumViewer.scene.canvas.style.width = w+'px'
  1070. cesiumViewer.scene.canvas.style.height = h+'px'
  1071. cesiumViewer.scene.canvas.style.visibility = 'hidden'
  1072. cesiumViewer.resize()
  1073. cesAspect = w/h
  1074. let deferred = $.Deferred();
  1075. updateMap(w/h)//hfov可能改变了需要update。
  1076. setTimeout(()=>{ //延迟是似乎还要做别的处理,否则立即截图的话可能得到绿色底图(俯视状态容易触发)
  1077. let oldMode = window.cesiumViewer._cesiumWidget._scene.requestRenderMode
  1078. window.cesiumViewer._cesiumWidget._scene.requestRenderMode = 0 //强制render,否则会黑屏
  1079. cesiumViewer.render();
  1080. let dataUrl = window.cesiumViewer.scene.canvas.toDataURL('image/png')
  1081. window.cesiumViewer._cesiumWidget._scene.requestRenderMode = oldMode
  1082. //Potree.Common.downloadFile(dataUrl, 'screenshot.png')
  1083. cesAspect = null
  1084. cesiumViewer.scene.canvas.style.width = ''
  1085. cesiumViewer.scene.canvas.style.height = ''
  1086. cesiumViewer.scene.canvas.style.visibility = ''
  1087. deferred.resolve(dataUrl)
  1088. },200) //时间短了容易黑屏
  1089. return deferred.promise()
  1090. }
  1091. }
  1092. updateMap()
  1093. }
  1094. function updateMap( ){
  1095. if (Potree.settings.showCesium && Potree.settings.displayMode == 'showPointCloud') {
  1096. let camera = viewer.mainViewport.camera
  1097. let pPos = new THREE.Vector3(0, 0, 0).applyMatrix4(camera.matrixWorld);
  1098. let pRight = new THREE.Vector3(600, 0, 0).applyMatrix4(camera.matrixWorld);
  1099. let pUp = new THREE.Vector3(0, 600, 0).applyMatrix4(camera.matrixWorld);
  1100. let pTarget = viewer.scene.view.getPivot();
  1101. let toCes = (pos) => {
  1102. let xy = [pos.x, pos.y];
  1103. let height = pos.z;
  1104. let deg = viewer.transform.lonlatToLocal.inverse(xy) // toMap.forward(xy);
  1105. let cPos = Cesium.Cartesian3.fromDegrees(...deg, height);
  1106. return cPos;
  1107. };
  1108. let cPos = toCes(pPos);
  1109. let cUpTarget = toCes(pUp);
  1110. let cTarget = toCes(pTarget);
  1111. let cDir = Cesium.Cartesian3.subtract(cTarget, cPos, new Cesium.Cartesian3());
  1112. let cUp = Cesium.Cartesian3.subtract(cUpTarget, cPos, new Cesium.Cartesian3());
  1113. cDir = Cesium.Cartesian3.normalize(cDir, new Cesium.Cartesian3());
  1114. cUp = Cesium.Cartesian3.normalize(cUp, new Cesium.Cartesian3());
  1115. cesiumViewer.camera.setView({
  1116. destination: cPos,
  1117. orientation: {
  1118. direction: cDir,
  1119. up: cUp
  1120. }
  1121. });
  1122. let aspect = cesAspect || viewer.scene.getActiveCamera().aspect;
  1123. console.log('updateMap', aspect)
  1124. if (aspect < 1) {
  1125. let fovy = Math.PI * (viewer.scene.getActiveCamera().fov / 180);
  1126. cesiumViewer.camera.frustum.fov = fovy;
  1127. } else {
  1128. let fovy = Math.PI * (viewer.scene.getActiveCamera().fov / 180);
  1129. let fovx = Math.atan(Math.tan(0.5 * fovy) * aspect) * 2
  1130. cesiumViewer.camera.frustum.fov = fovx;
  1131. }
  1132. cesiumViewer.render(); //立即render,否则会和点云render不同步而错位
  1133. }
  1134. }
  1135. return sdk
  1136. }
  1137. /*
  1138. 暂定不同场景间的漫游点不能互通。虽然它们可能是摆放正确的,如果是组成一整个场景的话还是要打通……
  1139. 不互通的方法是设置pano.enable
  1140. 现在需要互通了。但是还需要设置neibgbours, 有点麻烦,暂时没写。
  1141. */
  1142. export default enter