index.js 78 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024
  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. //江门本地版本
  17. export const enter = ({ dom, mapDom, isLocal, lonlat, scenes, laserRoot, laserOSSRoot, panoOSSRoot }) => {
  18. console.warn('新的页面')
  19. Potree.settings.isOfficial = true //标记为正式、非测试版本
  20. //Potree.fileServer = axios
  21. Potree.settings.libsUrl = './lib/'
  22. let loadStartTime = Date.now()
  23. //正式环境(本地调试会打不开)
  24. if (location.host === 'mix3d.4dkankan.com') {
  25. Potree.settings.urls.prefix = Potree.settings.urls.prefix6
  26. Potree.settings.webSite = 'datav1'
  27. } else if (location.host === 'xfhd.4dkankan.com') {
  28. Potree.settings.urls.prefix = Potree.settings.urls.prefix7
  29. Potree.settings.webSite = 'datav1'
  30. }
  31. if(window.offline){//离线版
  32. Potree.fileStorage = {
  33. get(url){
  34. return new Promise(function(resolve,reject){
  35. let data = window.offlineData[url]
  36. if(data){
  37. resolve(data)
  38. }else{
  39. console.error('没找到',url)
  40. reject()
  41. }
  42. })
  43. }
  44. }
  45. }
  46. if(laserRoot != void 0){
  47. laserRoot.slice(-1) == '/' && (laserRoot = laserRoot.slice(0,-1)) //去掉最后一个'/'
  48. Potree.settings.urls.prefix = laserRoot
  49. }
  50. if(laserOSSRoot != void 0){
  51. Potree.settings.urls.prefix1 = laserOSSRoot
  52. }
  53. if(panoOSSRoot != void 0){
  54. Potree.settings.urls.prefix3 = panoOSSRoot
  55. }
  56. const mapBus = mitt(), sceneBus = mitt()
  57. let isLocal2 = true
  58. if(isLocal2){//本地配置
  59. Potree.settings.isLocal = Potree.settings.tileOriginUrl = isLocal2
  60. }
  61. Potree.settings.showCompass = true
  62. Potree.settings.compassDom = dom.querySelector('#direction')
  63. Potree.settings.mergeType2 = true //标识新版
  64. Potree.settings.modelSkybox = true //是否将全景图贴在模型上(会导致卡顿)。若不显示模型将不显示Reticule
  65. Potree.settings.tiles3DMaxMemory = 300 //稍微增加点
  66. Potree.settings.mergeTransCtlOnClick = true
  67. Potree.settings.canWalkThroughModel = true
  68. let { THREE } = Potree.mergeEditStart(dom, mapDom)
  69. let MergeEditor = viewer.modules.MergeEditor
  70. Potree.settings.unableNavigate = true
  71. if(window.offline){//离线版 改目录
  72. viewer.images360.tileDownloader.getTiles = function(d, sceneNum, useV4url, model){
  73. let kankan = !model.isPointcloud //ModelTypes[model.props.fromType].panos4dkk
  74. if(kankan){
  75. return `/swkk/${sceneNum}/wwwroot/scene_view_data/${sceneNum}/images/${d}`
  76. }else{
  77. return `/swss/${sceneNum}/www/${sceneNum}/scene_view_data/${sceneNum}/images/${d}`
  78. }
  79. }
  80. }
  81. //因为getPose里用的是target,俯视的yaw不准,所以限制一下不要完全俯视
  82. viewer.mainViewport.view.maxPitch-=0.001
  83. viewer.mainViewport.view.minPitch+=0.001
  84. viewer.addEventListener('camera_changed', e => {
  85. var camera = e.viewport.camera
  86. var pos = camera.position
  87. if (e.viewport.name == 'MainView') {
  88. sceneBus.emit('cameraChange', { x: pos.x, y: pos.y, z: pos.z, rotate: camera.rotation })
  89. updateMap()
  90. Potree.Common.intervalTool.isWaiting('updateCamNear', ()=>{
  91. updateCamNear()
  92. }, 1000)
  93. //viewer.scene.tags.children.forEach(tag=>tag.functions.updateVisiFar())
  94. }
  95. })
  96. //-------------------------------------
  97. let modelAinB = (A,B)=>{ //B的expand(5m) bound完全包含A
  98. let boundB = B.boundingBox.clone().expandByVector(new THREE.Vector3(5,5,5)).applyMatrix4(B.matrixWorld)
  99. let boundA = A.boundingBox.clone().applyMatrix4(A.matrixWorld)
  100. return boundB.containsBox(boundA)
  101. }
  102. let changeMeshVisi = (object, show) => {
  103. if(show == void 0) show = Potree.settings.displayMode == 'showPointCloud' || object == viewer.images360.currentPano.pointcloud && Potree.settings.modelSkybox || object.showInPano //showInPano: 装饰物,一直显示
  104. || !object.panos && modelAinB(object, viewer.images360.currentPano.pointcloud) //装饰物
  105. Potree.Utils.updateVisible(object, 'showPanos', show)
  106. }
  107. if(Potree.settings.canWalkThroughModel){
  108. let lastModel
  109. viewer.images360.addEventListener('flyToPano',(e)=>{//开始漫游 漫游到另一个模型就要选中这个模型?
  110. let model = e.toPano.pano.pointcloud
  111. if(lastModel != model){
  112. changeMeshVisi(model, true)
  113. //MergeEditor.selectModel(model)
  114. //model.result_.flyInPano(e.toPano.pano, {dontFly:true}) //切换模型显示,因为flyInPano有事件怕乱所以统一用这个函数
  115. updateCamNear()
  116. }
  117. })
  118. viewer.images360.addEventListener('flyToPanoDone',(e)=>{
  119. if(!e.makeIt)return
  120. let model = viewer.images360.currentPano.pointcloud
  121. if(lastModel != model){
  122. lastModel?.isModel && changeMeshVisi(lastModel, false)
  123. sceneBus.emit('panoModelChange', model.result_ )
  124. }
  125. lastModel = model
  126. })
  127. }
  128. viewer.images360.addEventListener('endChangeMode',(e)=>{
  129. sceneBus.emit('modeChange', {mode: e.mode == 'showPanos' ? 'pano' : 'fuse', model : e.mode == 'showPanos' && viewer.images360.currentPano.pointcloud.result_} )
  130. Potree.Utils.updateVisible(MergeEditor.transformControls, 'showPanos', e.mode == 'showPointCloud')
  131. Potree.Utils.updateVisible(MergeEditor.boxHelper, 'showPanos', e.mode == 'showPointCloud')
  132. if(e.mode == 'showPanos'){
  133. viewer.setControls( viewer.fpControls )
  134. viewer.removeEventListener('camera_changed', camera_changed)
  135. }else{
  136. viewer.addEventListener('camera_changed', camera_changed)
  137. }
  138. viewer.objs.children.forEach((e)=>{changeMeshVisi(e)})
  139. Potree.settings.canWalkThroughModel || viewer.images360.panos.forEach(pano => {
  140. pano.setEnable(e.mode == 'showPanos' ? pano.pointcloud == viewer.images360.currentPano.model : true)
  141. })
  142. Potree.settings.unableNavigate = e.mode == 'showPointCloud'
  143. updateCamNear()
  144. })
  145. let camera_changed = (e) => {
  146. if (e.viewport.name == 'MainView' && e.changeInfo.positionChanged) {
  147. //viewer.mainViewport.camera.position
  148. viewer.mainViewport.view.radius = 0.1 //使pivot在面前一丢丢距离
  149. viewer.setControls(viewer.orbitControls)
  150. viewer.removeEventListener('camera_changed', camera_changed)
  151. }
  152. }
  153. let requestInPano = false
  154. //-------------------------------------
  155. /* viewer.inputHandler.addEventListener('keydown', (e)=>{
  156. if(e.event.key == "e" ){
  157. MergeEditor.transformControls.mode = 'rotate'
  158. }else if(e.event.key == "w"){
  159. MergeEditor.transformControls.mode = 'translate'
  160. }else if(e.event.key == "s"){
  161. MergeEditor.transformControls.mode = 'scale'
  162. }
  163. }) */
  164. viewer.addEventListener('webglError', e => {
  165. console.error('viewer webglError: ' + e)
  166. let memory = '. \n jsHeapSizeLimit:'+ performance.memory.jsHeapSizeLimit/ 1e6 + ', usedJSHeapSize: '+performance.memory.usedJSHeapSize/ 1e6 + '(M)'
  167. sceneBus.emit('webglError', { msg: e.msg + memory })
  168. })
  169. viewer.compass.setAutoDisplay(true)
  170. /* mapBus.on('visible', v => {
  171. //console.log('mapBus visible', v)
  172. viewer.mapViewer.visible = v
  173. if (v) {
  174. viewer.mapViewer.mapLayer.needUpdate = true
  175. }
  176. viewer.mapViewer.dispatchEvent({type:'forceVisible',visible:v})
  177. }) */
  178. {
  179. let index = 1;
  180. //let setDisplay()
  181. if (!Potree.isIframeChild) {
  182. /* viewer.addEventListener('createIframe',(e)=>{//创建了子页面
  183. }) */
  184. window.winIndex = 0;
  185. window.iframeCreated = function (iframe) {
  186. let child = iframe.contentWindow
  187. child.winIndex = index++
  188. //案件里视图提取页面子页面覆盖了父级页面,父级的模型可以隐藏以释放内存
  189. console.error('createdIframe', child.winIndex, child.location.href)
  190. viewer.setDisplay(false)
  191. child.beforeDestroy = function () { //注:在前端仍会找不到beforeDestroy,可能contentWindow变更??所以手动调用setDisplay
  192. console.warn('beforeDestroy', child.winIndex)
  193. child.viewer && child.viewer.setDisplay(false)
  194. //如果是四维看看的场景,先不管了,页面被销毁应该就没了吧
  195. viewer.setDisplay(true)//恢复主页的模型显示
  196. if (!child.viewer) {
  197. try {
  198. let player = child.__sdk.core.get('Player')
  199. /* let runtime = player.model._3dTilesRuntime
  200. let tileset = runtime.getTileset()
  201. tileset._cache.trim(); //使下一次update时dispose所有不可见的tiles
  202. let sceneRenderer = child.__sdk.core.get('SceneRenderer')
  203. player.model.visible = false
  204. runtime.update(16, sceneRenderer.renderer, sceneRenderer.camera, true) //没用,为何_trimTiles的while无法进入
  205. */
  206. player.model.traverse(e => {
  207. e.geometry && e.geometry.dispose()
  208. if (e.material) {
  209. e.material.map && e.material.map.dispose()
  210. if (e.material.uniforms && e.material.uniforms.map && e.material.uniforms.map.value) {
  211. e.material.uniforms.map.value.dispose()
  212. }
  213. }
  214. }) //效果甚微
  215. /* let sceneRenderer = child.__sdk.core.get('SceneRenderer')
  216. sceneRenderer.renderer.render(sceneRenderer.scene, sceneRenderer.camera)
  217. */
  218. } catch (e) {
  219. console.log(e)
  220. }
  221. }
  222. }
  223. }
  224. //不知道删除iframe时是否那些模型还在内存里,需要释放吗? 如果要需要加一个事件
  225. } else {
  226. }
  227. }
  228. window.THREE = THREE
  229. //isLocal = false
  230. let autoLoads = /* window.autoLoads = */ []
  231. let readyToAddModel
  232. let mainBackground = viewer.background
  233. const units = { 1: 'metric', 2: 'imperial' }
  234. let getMeasureType = function (type, unit = 1) {
  235. let info
  236. switch (type) {
  237. case 'free':
  238. info = { measureType: 'Distance' }
  239. break
  240. case 'area':
  241. info = { measureType: 'Area' }
  242. break
  243. case 'vertical':
  244. info = { measureType: 'Ver Distance' }
  245. break
  246. default:
  247. console.error('无此 measure type')
  248. }
  249. info.unit = units[unit]
  250. return info
  251. }
  252. let getMeasureFunction = function (measure, bus) {
  253. measure.addEventListener('highlight', (e) => {
  254. if(measure.type == 'Path'){
  255. bus.emit(e.state ? 'enter' : 'leave')
  256. }else{
  257. bus.emit('highlight', e.state)
  258. }
  259. })
  260. let update = (e)=>{ //拖拽结束后发送changeCallBack
  261. if (measure.parent) {
  262. //未被删除
  263. console.warn('changePoints', measure.dataset_points.length )
  264. if(measure.type == 'Path'){
  265. bus.emit('changePoints', measure.dataset_points.map((p,i)=>{return {position:p.clone(), modelId:measure.points_datasets[i], name:measure.markerLabels[i].text}}))
  266. }else{
  267. bus.emit('update', [
  268. measure.dataset_points.map(p => p.clone()),
  269. measure.points_datasets
  270. ])
  271. }
  272. }
  273. }
  274. measure.addEventListener('marker_dropped', update)
  275. measure.addEventListener('changed', update)
  276. measure.addEventListener('createDone', update)
  277. measure.addEventListener('changeByHistory', update);
  278. return {
  279. /* quit: () => {
  280. Potree.Log('quit结束且删除: ' + measure.id, '#00c7b2')
  281. viewer.dispatchEvent({ type: 'cancel_insertions', remove: true, measure })
  282. }, //触发结束。退出测量模式,清除之前操作 */
  283. destroy: () => {
  284. viewer.dispatchEvent({ type: 'cancel_insertions', remove: true, measure })
  285. viewer.scene.removeMeasurement(measure)
  286. },
  287. /* getPoints: () => {
  288. return measure.points
  289. },
  290. getDatasetLocations: () => {
  291. return measure.dataset_points
  292. },
  293. getDatasets: () => {
  294. return measure.points_datasets
  295. },
  296. getDatasetId: () => {
  297. return measure.datasetId
  298. }, */
  299. getArea: () => {
  300. return measure.area //{value:area, string:..}
  301. },
  302. getDistance: () => {
  303. if (measure.points.length < 2) return 0
  304. var value = measure.points[0].distanceTo(measure.points[1])
  305. return {
  306. value, //米
  307. string: measure.getConvertString(value, 'distance')
  308. }
  309. },
  310. //手动开启或关闭:
  311. show: () => {
  312. Potree.Utils.updateVisible(measure, 'inListByUser', true)
  313. },
  314. hide: () => {
  315. Potree.Utils.updateVisible(measure, 'inListByUser', false)
  316. },
  317. fly() {
  318. let result = viewer.focusOnObject(measure, 'measure', 1200)
  319. return result.msg ? result.msg : result.promise
  320. //返回值 1 deferred 表示即将位移 2 'posNoChange' 表示已在最佳位置 3 'tooFar' 表示距离最佳位置太远
  321. },
  322. changeSelect(isHight) {
  323. //console.log('2d->3d isHight ', isHight)
  324. measure.setSelected(isHight, 'byList')
  325. },
  326. }
  327. }
  328. let sdk = {
  329. sceneBus, mapBus,
  330. canTurnToPanoMode(pos) {
  331. pos = pos ? new THREE.Vector3().copy(pos) : viewer.images360.position
  332. let pano = viewer.images360.findNearestPano(pos)
  333. if (pano && pano.position.distanceTo(pos) < Potree.config.panoFieldRadius * pano.pointcloud.scale.x) {
  334. return {model:pano.pointcloud.result_}
  335. }
  336. //poschange后会调用这个,如果返回false会变为点云模式,且不会自动变回原先的模式
  337. },
  338. getPositionByScreen(pos2d, hopeModelId) {//通过屏幕坐标获取真实坐标 . hopeModelId: 如果指定了模型,优先返回hopeModelId上的intersect
  339. //console.log('getPositionByScreen',hopeModelId)
  340. hopeModelId = null
  341. let worldPos, localPos, modelId, intersect, normal, localNormal
  342. let Handler = viewer.inputHandler
  343. let reGet = () => {//不使用当前鼠标所在位置的intersect,单独算
  344. pos2d.clientX = pos2d.x
  345. pos2d.clientY = pos2d.y
  346. pos2d.onlyGetIntersect = true
  347. pos2d.whichPointcloud = true
  348. if (hopeModelId != void 0) {//隐藏其他的模型
  349. let models = MergeEditor.getAllObjects()
  350. models.forEach(model => {
  351. Potree.Utils.updateVisible(model, 'forPick', model.dataset_id == hopeModelId)
  352. })
  353. }
  354. let intersect2 = Handler.onMouseMove(pos2d)
  355. if (hopeModelId != void 0) {//恢复
  356. let models = MergeEditor.getAllObjects()
  357. models.forEach(model => {
  358. Potree.Utils.updateVisible(model, 'forPick', true)
  359. })
  360. }
  361. if (intersect2 && intersect2.location) {
  362. intersect = intersect2
  363. }
  364. }
  365. if (pos2d && pos2d.inDrag) {
  366. reGet()
  367. } else {
  368. intersect = Handler.intersect
  369. if (intersect) {
  370. modelId = intersect.pointcloud ? intersect.pointcloud.dataset_id : intersect.object.dataset_id
  371. if (hopeModelId != void 0 && modelId != hopeModelId) {
  372. reGet()
  373. }
  374. }
  375. }
  376. if (intersect && intersect.location) {
  377. modelId = intersect.pointcloud ? intersect.pointcloud.dataset_id : intersect.object.dataset_id
  378. /* if(hopeModelId != void 0 && modelId != hopeModelId){
  379. return null
  380. } */
  381. worldPos = intersect.location.clone()
  382. localPos = Potree.Utils.datasetPosTransform({ toDataset: true, datasetId: modelId, position: worldPos })
  383. normal = intersect.normal
  384. localNormal = intersect.localNormal
  385. } else return null
  386. return { worldPos, modelId, normal, localPos, localNormal }
  387. },
  388. getScreenByPosition(pos3d, modelId, canShelter/* , disToCameraLimit */) {//通过模型局部坐标获取屏幕坐标
  389. //console.log('getScreenByPoint ')
  390. let isLocal = modelId != void 0
  391. pos3d = new THREE.Vector3().copy(pos3d)
  392. let worldPos = isLocal ? Potree.Utils.datasetPosTransform({ fromDataset: true, datasetId: modelId, position: pos3d }) : pos3d
  393. if (!worldPos) return
  394. if (canShelter) {
  395. if (viewer.inputHandler.ifBlockedByIntersect(worldPos, 0.1, true)) return { trueSide: false };
  396. }
  397. var viewport = viewer.mainViewport
  398. var camera = viewport.camera
  399. var dom = viewer.renderArea
  400. /* if (tagLimitDis != void 0) {
  401. if (camera.position.distanceToSquared(worldPos) > Math.pow(tagLimitDis, 2)) return false
  402. } */
  403. //console.log('getScreenByPoint ' + pos3d.toArray())
  404. return Potree.Utils.getPos2d(worldPos, viewport, dom)
  405. },
  406. setCameraFov(fov) {
  407. viewer.setFOV(fov)
  408. },
  409. screenshot: (width, height/* , bgOpacity=0 */ ) => {//
  410. //截图
  411. let bgOpacity = Potree.settings.showCesium ? 0 : 1 /* viewer.background == 'skybox' */ //因为要画map底图所以上层只能透明。之后需要的话再改
  412. console.log('bgOpacity', bgOpacity)
  413. Potree.Utils.updateVisible(MergeEditor.boxHelper, 'screenshot', false)
  414. var { getImagePromise, finishPromise } = viewer.startScreenshot({ type: 'default', /* useRenderTarget:true, */bgOpacity }, width, height)
  415. var deferred = $.Deferred();
  416. finishPromise.done(({ dataUrl }) => {
  417. if(Potree.settings.displayMode != 'showPanos' && Potree.settings.showCesium){//need map background
  418. Potree.cesScreenshot(width, height).done((mapBGurl)=>{
  419. let img = new Image(); img.src = dataUrl
  420. let imgBG = new Image(); imgBG.src = mapBGurl
  421. let loadCount = 0
  422. img.onload = imgBG.onload = ()=>{
  423. loadCount++;
  424. if(loadCount == 2){
  425. let url = Potree.Common.imgAddLabel(imgBG,img,{leftRatioToImg:0,topRatioToImg:0})
  426. deferred.resolve(url)
  427. }
  428. }
  429. })
  430. }else{
  431. deferred.resolve(dataUrl)
  432. }
  433. Potree.Utils.updateVisible(MergeEditor.boxHelper, 'screenshot', true)
  434. })
  435. return deferred.promise()
  436. },
  437. getPose() {//获取当前点位和朝向
  438. const camera = viewer.scene.getActiveCamera()
  439. const target = viewer.scene.view.getPivot().clone()
  440. const position = viewer.scene.view.position.clone()
  441. const pose = { position, target, displayMode:Potree.settings.displayMode }
  442. if(Potree.settings.displayMode == 'showPanos'){
  443. let model = viewer.images360.currentPano.pointcloud
  444. pose.panoId = viewer.images360.currentPano.originID
  445. pose.model = model.result_
  446. pose.posInModel = Potree.Utils.datasetPosTransform({ toDataset: true, position: camera.position.clone(), object:model })
  447. pose.rotInModel = Potree.Utils.datasetRotTransform({ toDataset: true, quaternion: camera.quaternion.clone(), getQuaternion: true, pointcloud:model }).toArray() //拿第一个数据集
  448. }
  449. //console.log('getPose',position, target)
  450. return pose
  451. },
  452. comeTo(o = {}) {
  453. //console.log('comeTo',o.position, o.target)
  454. //飞到某个点
  455. let deferred = $.Deferred()
  456. if(o.panoId != void 0){
  457. let model = o.model.model
  458. let pano = model.panos.find(a=>a.originID == o.panoId)
  459. if(pano){
  460. o.rotInModel = new THREE.Quaternion().fromArray(o.rotInModel)
  461. let quaternion = Potree.Utils.datasetRotTransform({ fromDataset: true, quaternion: o.rotInModel, getQuaternion: true, object:model})
  462. o.model.flyInPano(pano, {quaternion, duration:0, callback(){
  463. o.callback && o.callback()
  464. deferred.resolve(true)
  465. }})
  466. return deferred.promise()
  467. }else{
  468. console.warn('没有找到漫游点',o)
  469. }
  470. }else if(requestInPano){
  471. requestInPano.result_.flyOutPano()
  472. }else{
  473. if (o.modelId != void 0) {
  474. ['position', 'target'].forEach(e => {
  475. if (o[e]) {
  476. o[e] = Potree.Utils.datasetPosTransform({ fromDataset: true, datasetId: o.modelId, position: o[e] })
  477. }
  478. })
  479. }
  480. }
  481. if (o.distance) {
  482. let position = o.target || o.position
  483. return viewer.focusOnObject({ position }, 'tag', null, { distance: o.distance }).promise
  484. }
  485. viewer.scene.view.setView($.extend({}, o, {
  486. duration: o.dur,
  487. callback: () => {
  488. o.callback && o.callback()
  489. deferred.resolve(true)
  490. }
  491. }))
  492. return deferred.promise()
  493. },
  494. setBackdrop(sky, type, { scale, rotate }) {//天空盒背景
  495. //console.log('天空盒背景', sky,type)
  496. let setGroundAndText = (color) => {
  497. MergeEditor.secondCompass.dom.find(".dirText").css({ 'color': color })
  498. viewer.compass.dom.find(".dirText").css({ 'color': color })
  499. MergeEditor.ground.material.uniforms.uColor.value.set(color)
  500. //MergeEditor.ground.children[0].material.color.set(color)
  501. }
  502. viewer.dispatchEvent('content_changed')
  503. if(type == 'map'){
  504. MergeEditor.setGroundPlaneImg(null)
  505. viewer.setBackground(mainBackground)
  506. Potree.settings.showCesium = true
  507. buildMap()
  508. viewer.backgroundOpacity = 0
  509. return
  510. }else{
  511. Potree.settings.showCesium = false
  512. }
  513. if (type == 'bimg') {//地面图
  514. MergeEditor.setGroundPlaneImg(sky, scale, rotate)
  515. setGroundAndText('#e0e0e0')
  516. viewer.setBackground(mainBackground)
  517. } else {
  518. MergeEditor.setGroundPlaneImg(null)
  519. if (sky == 'none') {
  520. viewer.setBackground(mainBackground)
  521. setGroundAndText('#eee')
  522. } else if (sky[0] == '#') {
  523. viewer.setBackground(new THREE.Color(sky))
  524. let color = sky == '#fff' ? '#666' : sky == '#333' ? '#eee' : '#bbb' //反相
  525. setGroundAndText(color)
  526. } else if (type == 'image-map' || type == 'vector-map') {//影像|矢量 地图
  527. } else {//环境
  528. viewer.setBackground('skybox', sky)
  529. setGroundAndText('#e0e0e0')
  530. }
  531. }
  532. },
  533. switchMapType(type) {
  534. let map = viewer.mapViewer.mapLayer.maps.find(e => e.name == 'map')
  535. map.switchStyle(type/* map.style == 'satellite' ? 'standard' : 'satellite' */)
  536. },
  537. enableMap(mapArea, latlng) {
  538. if (!viewer.mapViewer) {
  539. //--------------------------------
  540. viewer.mapViewer = new Potree.MapViewer(mapArea)
  541. viewer.mapViewer.initProjection()
  542. //focus
  543. let boundSize = new THREE.Vector3(200, 150, 1).max(viewer.bound.boundSize)
  544. viewer.mapViewer.addEventListener('viewerResize', () => {
  545. viewer.mapViewer.moveTo(viewer.bound.center, boundSize, 0)
  546. }, { once: true })
  547. }
  548. },
  549. enterSceneGuide(pathArr) {//导览 (不需要修改参数)
  550. let editor = viewer.modules.CamAniEditor
  551. console.log('pathArr', pathArr)
  552. //console.log('enterSceneGuide',pathArr)
  553. pathArr.forEach(e=>{
  554. if(e.panoId != void 0){
  555. e.model = e.model.model
  556. }
  557. })
  558. let data = {
  559. //duration: pathArr.slice(0, pathArr.length - 1).reduce(function (total, currentValue) { return total + currentValue.time }, 0), //总时长(要去掉最后一个,因为已到终点,该点time无意义)
  560. points: pathArr,
  561. useDurSlice: true
  562. }
  563. let ani = editor.createMulAnimation(data)
  564. //注:最多只存在一条导览
  565. let bus = mitt()
  566. //播放完成
  567. ani.event_.addEventListener('playDone', () => {
  568. bus.emit('playComplete')
  569. viewer.images360.panos.forEach(e=>e.marker && Potree.Utils.updateVisible(e, 'playAni', true))
  570. })
  571. //切换点
  572. ani.event_.addEventListener('updateCurrentIndex', e => {
  573. bus.emit('changePoint', e.currentIndex + 1)
  574. })
  575. return {
  576. bus,
  577. play() {
  578. MergeEditor.selectModel(null)
  579. viewer.images360.panos.forEach(e=>e.marker && Potree.Utils.updateVisible(e, 'playAni', false))
  580. ani.play()
  581. },
  582. pause() {
  583. viewer.images360.panos.forEach(e=>e.marker && Potree.Utils.updateVisible(e, 'playAni', true))
  584. ani.stop()
  585. },
  586. clear() {
  587. ani.remove()
  588. },
  589. }
  590. },
  591. //[path1, paht2], { time, speed }
  592. calcPathInfo(paths, info) { //传入的time, speed仅有一个。返回完整的 time, speed
  593. //这一版的control似乎无法在某个位置上改变角度,位置和角度一般都是一起变的,所以先不增加单位更换功能。
  594. let pos1 = new THREE.Vector3().copy(paths[0].position)
  595. let pos2 = new THREE.Vector3().copy(paths[1].position)
  596. let dis = pos1.distanceTo(pos2)
  597. if (info.time != void 0) {
  598. info.speed = dis / info.time
  599. } else {
  600. info.time = dis / info.speed
  601. }
  602. return info
  603. },
  604. addModel(props) {
  605. let bus = props.bus = mitt()
  606. //console.log('addModel',props)
  607. props.isFirstLoad = isLocal ? props.bottom == void 0 : (props.isDynamicAdded || props.mode == 'single') // 在编辑时用户添加的 或 展示单个模型 (props.mode='single'模型展示页, props.mode='many'融合页)
  608. if (props.opacity == void 0) props.opacity = 1
  609. if (props.type == 'obj') props.type = 'glb'
  610. props.scale /= 100
  611. if (props.rotation) {
  612. if (props.rotation._x == void 0 && props.rotation.x != void 0) {
  613. props.rotation = new THREE.Euler().setFromVector3(props.rotation)
  614. }
  615. }
  616. let getDefaultRotation = () => {
  617. if(ModelTypes[props.fromType]?.rot90 && props.type != 'glb'){
  618. return new THREE.Euler(Math.PI / 2, 0, 0)
  619. } else return new THREE.Euler(0, 0, 0)
  620. }
  621. if (!props.isFirstLoad) {
  622. if (autoLoads.length == 0) { //首次加载
  623. setTimeout(() => {
  624. let sizes = autoLoads.map(e => e.size || 0)
  625. console.log('需要请求加载的模型大小为', sizes, '总大小', sizes.reduce(function (total, currentValue) {
  626. let current = parseFloat(currentValue)
  627. return total + ((typeof currentValue == 'number' || currentValue.includes('M')) ? current : current / 1024)
  628. }, 0))
  629. readyToAddModel = true //准备开始加载
  630. loadNext()//startLoad(autoLoads[0])
  631. }, 30)
  632. }
  633. autoLoads.push(props)
  634. readyToAddModel = false
  635. } else {
  636. readyToAddModel = true
  637. props.rotation = getDefaultRotation()
  638. }
  639. let model
  640. let done = (model_) => {
  641. model = model_
  642. model.result_ = result
  643. model.props = props
  644. result.model = model
  645. model.fromType = ModelTypes[props.fromType].name
  646. if (!props.isFirstLoad) {
  647. model.visible = false//先不显示,防止卡顿
  648. }
  649. model.showInPano = props.raw.showInPano
  650. props.opacity < 100 && result.changeOpacity(props.opacity)
  651. model.addEventListener('changeSelect', (e) => {
  652. bus.emit('changeSelect', e.selected)
  653. })
  654. let lastState = {}
  655. model.addEventListener('transformChanged', (e) => {
  656. let msg = {}
  657. if (!lastState.position || !model.position.equals(lastState.position)) {
  658. lastState.position = msg.position = model.position.clone()
  659. }
  660. if (!lastState.rotation || !model.rotation.equals(lastState.rotation)) {
  661. lastState.rotation = msg.rotation = model.rotation.clone()
  662. }
  663. if (lastState.scale == void 0 || model.scale.x * 100 != lastState.scale) {
  664. lastState.scale = msg.scale = model.scale.x * 100
  665. }
  666. msg = Potree.Common.CloneObject(msg)
  667. //console.log(msg)
  668. bus.emit('transformChanged', msg)
  669. })
  670. spliceFromArr(model, props, true)
  671. model.addEventListener('changeSelect', (e) => {
  672. MergeEditor.transformControls.visible && e.selected && MergeEditor.transformControls.attach(model, e.clickPos) //: MergeEditor.transformControls.detach()
  673. })
  674. MergeEditor.modelAdded(model)
  675. if (props.mode == 'single') {//模型查看页
  676. MergeEditor.noNeedSelection = true
  677. setTimeout(() => {
  678. MergeEditor.focusOn([model], 1000, true, true)
  679. }, 1)
  680. }
  681. if(ModelTypes[props.fromType].panos4dkk){
  682. Potree.load4dkkPanos(props.raw.num, model, getDefaultRotation(), () => {
  683. bus.emit('loadDone')
  684. }, props.fromType == 0 ? '2k' : '4k' ) //看看场景是2k
  685. } else {
  686. bus.emit('loadDone')
  687. }
  688. //console.log('loadDone' )
  689. }
  690. let progressFun = (progress) => {
  691. bus.emit('loadProgress', progress)
  692. }
  693. let onError = function (xhr) {
  694. bus.emit('loadError', xhr)
  695. console.log('loadError!!!!!!!!!', Potree.Common.getNameFromURL(props.url), props.size, xhr)
  696. spliceFromArr(model, props, false)
  697. }
  698. try {
  699. props.url = JSON.parse(props.url) //去掉 '\'
  700. } catch (e) { }
  701. props.done = done; props.progressFun = progressFun; props.onError = onError
  702. if (readyToAddModel) {
  703. if (autoLoads.filter(e => e.loading).length < maxLoadingCount) {
  704. startLoad(props)
  705. }
  706. }
  707. let scaleMeasure
  708. let result = {
  709. bus,
  710. model,
  711. getDefaultRotation,
  712. supportPano() { //是否支持全景图
  713. return model?.panos?.length > 0
  714. },
  715. flyInPano(pano, {dontFly, quaternion, duration}={}) {// 飞入全景图
  716. requestInPano = model
  717. pano = pano || viewer.images360.findNearestPano(null, model.panos)
  718. if (pano) {
  719. dontFly || viewer.images360.flyToPano({ pano, canCancelLast: true, quaternion, duration})
  720. Potree.settings.displayMode = 'showPanos'
  721. }
  722. },
  723. flyOutPano() {// 飞出全景图(就是切换到正常融合视角)
  724. requestInPano = false
  725. Potree.settings.displayMode = 'showPointCloud'
  726. /* setTimeout(() => {//在下一帧再变,因为3dtiles需要更新一下才会显示tiles
  727. if (!requestInPano) {
  728. Potree.settings.displayMode = 'showPointCloud'
  729. Potree.Utils.updateVisible(MergeEditor.boxHelper, 'showPanos', true)
  730. }
  731. }, 50) */
  732. },
  733. changeShow(show) {
  734. props.show = show //for autoLoads show model
  735. if (model) {
  736. Potree.Utils.updateVisible(model, 'datasetSelection', show)
  737. if (model.panos) {
  738. model.panos.forEach(e => e.setEnable(show))
  739. }
  740. viewer.dispatchEvent('content_changed')
  741. }
  742. },
  743. changeSelect(state) {
  744. console.error('select', state)
  745. if (model) {
  746. let fly = viewer.images360.latestRequestMode != 'showPanos'
  747. MergeEditor.selectModel(model, state, fly, true)
  748. updateCamNear()
  749. //console.log('changeSelect', props.id, state)
  750. }
  751. },
  752. changeScale(s) {
  753. if (model) {
  754. s /= 100
  755. if (model.scale.x == s) return
  756. //MergeEditor.history.beforeChange(model)//但不知道什么时候结束拖拽
  757. model.scale.set(s, s, s)
  758. model.isPointcloud && model.changePointSize(/* Potree.config.material.realPointSize * s */)
  759. model.dispatchEvent("scale_changed")
  760. }
  761. },
  762. changeOpacity(opacity) { //见笔记:透明物体的材质设置
  763. if (opacity == void 0) opacity = 100
  764. opacity /= 100
  765. MergeEditor.changeOpacity(model, opacity)
  766. },
  767. changeBottom(z) {
  768. /* model && MergeEditor.setModelBtmHeight(model,z)
  769. model.dispatchEvent('transformChanged') //改了position */
  770. },
  771. changePosition(pos) {//校准取消时执行
  772. console.log('changePosition', pos.x, pos.y, pos.z)
  773. model && model.position.copy(pos)
  774. model.dispatchEvent({ type: 'position_changed' })
  775. },
  776. changeRotation(rot) {//校准取消时执行
  777. console.log('changeRotation', rot.x, rot.y, rot.z)
  778. model && model.rotation.setFromVector3(rot)
  779. model.dispatchEvent({ type: 'rotation_changed' })
  780. },
  781. enterRotateMode() {
  782. if (model) {
  783. if (MergeEditor.split) {//分屏校准
  784. MergeEditor.setTransformState('rotate')
  785. MergeEditor.transformControls2.attach(model)
  786. MergeEditor.transformControls2.mode = 'rotate'
  787. }
  788. MergeEditor.transformControls.attach(model)
  789. MergeEditor.transformControls.mode = 'rotate'
  790. }
  791. },
  792. enterMoveMode() {
  793. console.log('enterMoveMode')
  794. if (model) {
  795. if (MergeEditor.split) {//分屏校准
  796. MergeEditor.setTransformState('translate')
  797. MergeEditor.transformControls2.attach(model)
  798. MergeEditor.transformControls2.mode = 'translate'
  799. }
  800. MergeEditor.transformControls.attach(model)
  801. MergeEditor.transformControls.mode = 'translate'
  802. }
  803. },
  804. leaveTransform() {
  805. console.log('leaveTransform')
  806. if (MergeEditor.split) {//分屏校准
  807. MergeEditor.setTransformState(null)
  808. } else {
  809. MergeEditor.transformControls.detach()
  810. MergeEditor.transformControls2.detach()
  811. }
  812. MergeEditor.history.clear()
  813. },
  814. enterAlignment() {//开始校准
  815. result.leaveTransform()
  816. MergeEditor.enterSplit()
  817. //console.log('enterAlignment',model.position, model.rotation)
  818. let bus = new mitt()
  819. /* MergeEditor.transformControls.attach(model)
  820. MergeEditor.transformControls.mode = 'translate' */
  821. return {
  822. bus
  823. }
  824. },
  825. leaveAlignment() {
  826. //console.log('leaveAlignment',model.position, model.rotation)
  827. MergeEditor.leaveSplit()
  828. MergeEditor.transformControls.detach()
  829. MergeEditor.transformControls2.detach()
  830. },
  831. enterScaleSet() {//设置比例
  832. let bus = new mitt()
  833. let length, measureBuilded;
  834. //viewer.outlinePass.selectedObjects = []
  835. if (!Potree.Utils.isInsideFrustum(model.boundingBox.clone().applyMatrix4(model.matrixWorld), viewer.scene.getActiveCamera())) {
  836. MergeEditor.focusOn(model, 600)
  837. }
  838. MergeEditor.getAllObjects().forEach(m => {//隐藏其他的模型
  839. if (m != model) Potree.Utils.updateVisible(m, 'enterScaleSet', false)
  840. })
  841. let setScale = () => {
  842. if (length == void 0 || !measureBuilded) return
  843. let vec = new THREE.Vector3().subVectors(viewer.mainViewport.camera.position, scaleMeasure.points[1])
  844. let s = length / (scaleMeasure.points[0].distanceTo(scaleMeasure.points[1]))
  845. result.changeScale(model.scale.x * s * 100)
  846. /* setTimeout(()=>{
  847. viewer.focusOnObject(scaleMeasure , 'measure', 500)
  848. },1) */
  849. let newCamPos = new THREE.Vector3().addVectors(scaleMeasure.points[1], vec.multiplyScalar(s))
  850. viewer.scene.view.setView({
  851. position: newCamPos, target: scaleMeasure.getCenter(), duration: 0, callback: () => {
  852. //更改target到measure中心的好处就是可以让相机绕measure中心转,坏处是每次更改都会变一下画面
  853. }
  854. })
  855. }
  856. return {
  857. bus,
  858. setLength(v) {
  859. if (!v) return
  860. length = v
  861. setScale()
  862. },
  863. startMeasure() {
  864. if (scaleMeasure) {
  865. viewer.dispatchEvent({ type: 'cancel_insertions', remove: true, measure: scaleMeasure })
  866. viewer.scene.removeMeasurement(scaleMeasure)
  867. }
  868. measureBuilded = false
  869. scaleMeasure = viewer.measuringTool.startInsertion(
  870. { measureType: "Distance", unit: "metric" },
  871. () => {
  872. //done:
  873. //bus.emit('end' ) //完成
  874. measureBuilded = true
  875. setScale()
  876. },
  877. () => {
  878. //cancel
  879. //bus.emit('quit') //删除
  880. }
  881. )
  882. scaleMeasure.addEventListener('marker_dropped', (e) => {//拖拽结束后发送changeCallBack
  883. if (scaleMeasure.parent) {
  884. //未被删除
  885. measureBuilded && setScale()
  886. }
  887. })
  888. }
  889. }
  890. },
  891. leaveScaleSet() {
  892. if (scaleMeasure) {
  893. viewer.dispatchEvent({ type: 'cancel_insertions', remove: true, measure: scaleMeasure })
  894. viewer.scene.removeMeasurement(scaleMeasure)
  895. scaleMeasure = null
  896. }
  897. //viewer.outlinePass.selectedObjects = [model];
  898. MergeEditor.getAllObjects().forEach(m => {//恢复其他的模型
  899. if (m != model) Potree.Utils.updateVisible(m, 'enterScaleSet', true)
  900. })
  901. },
  902. destroy() {
  903. model && MergeEditor.removeModel(model)
  904. result.changeSelect(false)
  905. viewer.dispatchEvent('content_changed')
  906. }
  907. }
  908. return result
  909. },
  910. //测量线的点都附着于各个模型,当模型变化时,点跟着变化。
  911. // 新的测量创建方法,传入type 返回新测量对象
  912. startMeasure(type) {
  913. // 寻创建的测量对象有上面绘画测量对象的所有方法
  914. const bus = mitt()
  915. let info = getMeasureType(type)
  916. let measure = viewer.measuringTool.startInsertion(
  917. info,
  918. () => {
  919. //done:
  920. bus.emit('submit')
  921. },
  922. () => {
  923. //cancel
  924. bus.emit('cancel'/* , ret */) //删除
  925. }
  926. )
  927. Potree.Log('startMeasure: ' + measure.id, '#00c7b2')
  928. /* let cancel = ()=>{
  929. Potree.Log('clear删除: ' + measure.id, '#00c7b2')
  930. viewer.dispatchEvent({ type: 'cancel_insertions', remove: true, measure })
  931. viewer.scene.removeMeasurement(measure)
  932. } */
  933. let result = {
  934. bus,
  935. ...getMeasureFunction(measure, bus),
  936. }
  937. /* StartMeasure = Measure & {
  938. // 多了cancel 取消测量的事件,没有参数
  939. // 多了invalidPoint 当用户测量了无效点时的事件,抛出无效原因
  940. bus: Emitter<{ cancel: void; invalidPoint: string }>
  941. } */
  942. return result
  943. },
  944. // 绘画测量线(非新增使用)
  945. // type = 'free' (自由) || 'vertical' (垂直) || 'area' (面积)
  946. // positions 点数组 构成如下 [{ point: {x,y,z}, modelId: 1 }]
  947. drawMeasure(type, dataset_points, points_datasets) {
  948. // 返回测量对象有如下
  949. const bus = mitt()
  950. let info = getMeasureType(type /* , unit */)
  951. //info.points = positions
  952. info.dataset_points = dataset_points
  953. info.points_datasets = points_datasets
  954. //info.sid = sid
  955. info.bus = bus
  956. let measure = viewer.measuringTool.createMeasureFromData(info)
  957. if (!measure) return { bus }
  958. Potree.Log('drawMeasure由数据新建: ' + measure.id, '#00c7b2')
  959. let result = {
  960. bus,
  961. setPositions(dataset_points, points_datasets) {//用于恢复measure的点,不会修改点的个数
  962. measure.dataset_points = dataset_points.map(e => {
  963. return e && new THREE.Vector3().copy(e)
  964. })
  965. measure.points_datasets = points_datasets
  966. measure.points = measure.dataset_points.map((p, i) => {
  967. return Potree.Utils.datasetPosTransform({ fromDataset: true, datasetId: measure.points_datasets[i], position: p })
  968. })
  969. measure.getPoint2dInfo(measure.points)
  970. measure.update({ ifUpdateMarkers: true })
  971. measure.setSelected(false)//隐藏edgelabel
  972. },
  973. ...getMeasureFunction(measure, bus),
  974. }
  975. return result
  976. },
  977. /* export type PathProps = {
  978. // 线段名称
  979. name: string,
  980. // 是否显示名称,
  981. showName: boolean,
  982. // 文字大小
  983. fontSize: number,
  984. // 是否显示方向,
  985. showDirection: boolean,
  986. // 方向是否反向
  987. reverseDirection: boolean,
  988. line: {
  989. width: number,
  990. color: string,
  991. altitudeAboveGround: number
  992. position: SceneLocalPos,
  993. normal: SceneLocalPos,
  994. modelId: string
  995. },
  996. points: {
  997. // 点位名称
  998. name: string,
  999. position: SceneLocalPos,
  1000. modelId: string,
  1001. }[]
  1002. }
  1003. bus: Emitter<{
  1004. // 标注点击事件
  1005. click: void;
  1006. // 鼠标移入标注事件
  1007. enter: void;
  1008. // 鼠标移出标注事件
  1009. leave: void;
  1010. // 线段坐标更改事件
  1011. linePositionChange: {
  1012. pos: SceneLocalPos,
  1013. normal: SceneLocalPos,
  1014. modelId: string
  1015. }
  1016. // 路径点位置变更
  1017. changePoints: PathProps['points']
  1018. // 距离相机位置变更
  1019. toCameraDistanceChange: number
  1020. }>;
  1021. */
  1022. createPath(props){//路线
  1023. console.log('createPath', props)
  1024. let bus = mitt()
  1025. let path
  1026. let info = {type : 'Path', minMarkers : 2, title:props.name}
  1027. if(props.points.length == 0){
  1028. path = viewer.measuringTool.startInsertion( info, () => {
  1029. bus.emit("drawed" ); //完成
  1030. })
  1031. viewer.dispatchEvent({ type: 'cancel_insertions', dontRemove: true, measure:path }) //要等进入编辑才能继续编辑
  1032. }else{
  1033. info.points_datasets = props.points.map(e=>e.modelId)
  1034. info.dataset_points = props.points.map(e=>e.position)
  1035. path = viewer.measuringTool.createMeasureFromData(info);
  1036. if(props.line.position) {
  1037. let pos = Potree.Utils.datasetPosTransform({toDataset:true, position: props.line.position, datasetId: props.line.modelId, reverse: props.reverseDirection, showArrows: props.showDirection})
  1038. path.updateTitlePos(pos)
  1039. }
  1040. }
  1041. {
  1042. let curSelectMarker
  1043. path.addEventListener('markerSelect',(e)=>{
  1044. let msg
  1045. if(e.cancel){
  1046. curSelectMarker == e.marker && (msg = -1) //是当前选中的marker就取消
  1047. }else{
  1048. curSelectMarker = e.marker
  1049. msg = path.markers.indexOf(e.marker)
  1050. }
  1051. //msg != void 0 && console.log('msg',msg)
  1052. msg != void 0 && bus.emit('activePoint', msg )
  1053. })
  1054. path.addEventListener('titlePosChanged',(e)=>{
  1055. bus.emit('linePositionChange', {
  1056. modelId: e.root.dataset_id,
  1057. pos: Potree.Utils.datasetPosTransform({toDataset:true, position: e.position.clone(), datasetId: e.root.dataset_id })
  1058. })
  1059. })
  1060. /* path.addEventListener('titlePosChanged',(e)=>{
  1061. }) */
  1062. }
  1063. let funs = getMeasureFunction(path, bus)
  1064. let fadeFar = -1
  1065. let functions = Object.assign(funs,{
  1066. bus,
  1067. changeEditMode(state){//进入编辑
  1068. if(!state){
  1069. viewer.dispatchEvent({ type: 'cancel_insertions', dontRemove: true, measure:path })
  1070. }
  1071. path.setEditEnable(state)
  1072. functions.changeVisibilityRange(fadeFar)
  1073. },
  1074. changeCanEdit(state){//是否点击pen图标以加点和删点
  1075. if(state){
  1076. if(path.points.length < 2){//继续绘制
  1077. info.resume = true, info.measure = path
  1078. path = viewer.measuringTool.startInsertion( info, () => {
  1079. bus.emit("drawed" ); //完成
  1080. })
  1081. }
  1082. }else{
  1083. viewer.dispatchEvent({ type: 'cancel_insertions', dontRemove: true, measure:path })
  1084. }
  1085. path.setAddOrRemPoint(state)
  1086. },
  1087. visibility(v){
  1088. //console.log('visibility', path.title, v)
  1089. Potree.Utils.updateVisible(path,'user', v)
  1090. },
  1091. visibilityName(v){
  1092. path.setTitleVisi(path.titleLabel.parent, v, 'user')
  1093. },
  1094. changeName(name){
  1095. path.setTitle(name)
  1096. },
  1097. changePointName(index,name){
  1098. path.setMarkerTitle(index, name)
  1099. },
  1100. changePathPoints(points){
  1101. console.log('changePathPoints??????????',points)
  1102. },
  1103. deletePoint(index){
  1104. path.removePoint(index)
  1105. },
  1106. changeFontSize(fontsize){
  1107. path.setFontSize(fontsize)
  1108. },
  1109. changeLine({width,color,altitudeAboveGround}){
  1110. path.setPathWidth(width)
  1111. path.setPathColor(color)
  1112. },
  1113. changeVisibilityRange(far){//设置消失距离
  1114. fadeFar = far
  1115. path.setFadeFar(( far== -1 || path.editEnable) ? null : far) //注意:编辑时显示全部
  1116. },
  1117. changeDirection(show,reverse){
  1118. path.setArrowDisplay(show)
  1119. if(path.reverse != reverse){
  1120. path.reverse = reverse
  1121. path.constructor.updateArrows(true)
  1122. }
  1123. },
  1124. createAni(tension){
  1125. let distance = path.getTotalDistance()
  1126. let pathPoints = path.points.map(e=>e.clone().add(new THREE.Vector3(0,0,2))) //在地面之上一定高度
  1127. if(path.reverse) pathPoints.reverse()
  1128. const speed = 3, //m/s
  1129. turnDisPerRad = 1.5,
  1130. maxTurnDis = 3,//拐弯最大距离
  1131. maxRoadTurnRatio = 0.8 //每段路单次转弯最大比例,防止拐弯占据一整条路直到下一个点
  1132. let roadLens = []
  1133. let vecs = pathPoints.map((p,i)=>{
  1134. if(i==0)return
  1135. let last = pathPoints[i-1]
  1136. roadLens.push(p.distanceTo(last))
  1137. return new THREE.Vector3().subVectors(p,last).normalize()
  1138. })
  1139. let turnDis = vecs.map((vec,i)=>{//在每个转折点拐弯前后需要的米数
  1140. if(i==0 || i==vecs.length-1)return 0
  1141. let next = vecs[i+1]
  1142. let angle = next.angleTo(vec)
  1143. return Math.min(turnDisPerRad * angle / 2, maxTurnDis )
  1144. })
  1145. let points = []
  1146. let len = pathPoints.length
  1147. for(let i=0;i<len;i++){
  1148. let thisPoint = pathPoints[i]
  1149. let nextPoint = pathPoints[i+1]
  1150. if(i==0 || i==len-1){//首尾的点直接加入,其他点不加
  1151. points.push({
  1152. position: thisPoint.clone(),
  1153. target: i==0 ? nextPoint.clone() : pathPoints[len-1].clone().add(vecs[len-1])
  1154. })
  1155. }
  1156. if(i<len-1){ //加入每段边要加入的两个(or一个)拐点 ,拐点之间方向沿着路径
  1157. let turnDis1 = Math.min(turnDis[i], roadLens[i] * maxRoadTurnRatio)
  1158. let turnDis2 = Math.min(turnDis[i+1], roadLens[i] * maxRoadTurnRatio)
  1159. let turnDisSum = turnDis1 + turnDis2 //两端拐弯距离之和。
  1160. if(turnDisSum > roadLens[i]){//如果超过了路长度, 该条路就只有一个拐点
  1161. turnDis1 = turnDis1 / turnDisSum * roadLens[i]
  1162. let p = thisPoint.clone().add(vecs[i+1].clone().multiplyScalar(turnDis1))
  1163. points.push({position: p, target: nextPoint.clone()})
  1164. }else{
  1165. if(turnDis1>0){ //i==0时为0
  1166. let turnPoint1 = thisPoint.clone().add(vecs[i+1].clone().multiplyScalar(turnDis1))
  1167. points.push({position: turnPoint1, target: nextPoint.clone()})
  1168. }
  1169. if(turnDis2>0){//i==len-2时为0
  1170. let turnPoint2 = nextPoint.clone().sub(vecs[i+1].clone().multiplyScalar(turnDis2))
  1171. points.push({position:turnPoint2, target: nextPoint.clone()})
  1172. }
  1173. }
  1174. }
  1175. }
  1176. //加后缀&test以看路线
  1177. let data = {
  1178. name : 'path_guideTour',
  1179. duration : distance / speed,
  1180. points,
  1181. tension
  1182. }
  1183. path.animation_ = viewer.modules.CamAniEditor.createAnimation(data)
  1184. },
  1185. play(playDone){
  1186. let oldStates = {
  1187. editEnable: path.editEnable,
  1188. addOrRemovePoint: path.addOrRemovePoint
  1189. }
  1190. path.editEnable && functions.changeEditMode(false)
  1191. path.addOrRemovePoint && path.setAddOrRemPoint(false)
  1192. functions.createAni();//不传参数时路径最圆润缓和,但会脱离原路径。传参后除了拐弯都按路径,参数越大越圆润,但容易有折回的bug。 如果没有严格要求就不传参效果最佳。
  1193. path.animation_.play()
  1194. path.animation_.addEventListener('playDone', () => {
  1195. oldStates.editEnable && functions.changeEditMode(true)
  1196. oldStates.addOrRemovePoint && path.setAddOrRemPoint(true)
  1197. playDone && playDone()
  1198. },{once:true})
  1199. },
  1200. pause(){
  1201. path.animation_.pause()
  1202. viewer.modules.CamAniEditor.removeAnimation(path.animation_)
  1203. }
  1204. })
  1205. for(let i in functions){
  1206. if(functions[i] instanceof Function){
  1207. let oldFun = functions[i]
  1208. functions[i] = function(){
  1209. console.warn('path', i, path.title, ...arguments)
  1210. oldFun.apply(this, arguments)
  1211. }
  1212. }
  1213. }
  1214. path.functions = functions
  1215. props.line && functions.changeLine(props.line)
  1216. functions
  1217. return functions
  1218. },
  1219. createTagging(props){
  1220. let bus = mitt()
  1221. console.warn('createTagging', props)
  1222. let root = viewer.scene.pointclouds.concat(viewer.objs.children).find(e=>e.dataset_id == props.modelId)
  1223. if(!root){
  1224. return console.error('热点没有找到该modelId,模型是否已经删除?')
  1225. }
  1226. let info = {
  1227. position: new THREE.Vector3().copy(props.position), //局部坐标
  1228. normal: new THREE.Vector3().copy(props.normal),
  1229. root, lineLength: props.altitudeAboveGround,
  1230. title: props.title, fontsize: props.fontSize,
  1231. spotUrl: props.image
  1232. }
  1233. let tag = viewer.tagTool.createTagFromData(info)
  1234. tag.addEventListener('mouseover',()=>{
  1235. bus.emit('enter')
  1236. })
  1237. tag.addEventListener('mouseleave',()=>{
  1238. bus.emit('leave')
  1239. })
  1240. tag.addEventListener('click',()=>{
  1241. bus.emit('click')
  1242. })
  1243. tag.addEventListener('posChanged',(e)=>{
  1244. bus.emit('changePosition', {
  1245. modelId: tag.root.dataset_id,
  1246. normal: tag.normal.clone(),
  1247. pos: tag.position.clone()
  1248. })
  1249. })
  1250. tag.functions = {
  1251. bus,
  1252. changeType(type){
  1253. console.log('changeType', tag.title, type)
  1254. let onMesh = type == '3d'
  1255. if(tag.onMesh != onMesh){
  1256. tag.changeOnMesh(onMesh)
  1257. }
  1258. },
  1259. visibility(v){// 标注可见性
  1260. Potree.Utils.updateVisible(tag,'user', v)
  1261. },
  1262. visibilityTitle(v){
  1263. tag.setTitleVisi(v, 'user')
  1264. },
  1265. changePosition({modelId,position,normal}){
  1266. let root = viewer.scene.pointclouds.concat(viewer.objs.children).find(e=>e.dataset_id == props.modelId)
  1267. tag.changePos({root,position,normal})
  1268. },
  1269. changeImage(url){
  1270. tag.changeMap(url)
  1271. },
  1272. changeTitle(title){
  1273. tag.setTitle(title)
  1274. },
  1275. changeMat({scale,rotation}){//大小旋转 贴墙时
  1276. tag.setFaceAngle(rotation)
  1277. tag.changeSpotScale(scale)
  1278. },
  1279. changeFontSize(fontsize){
  1280. tag.setFontSize(fontsize)
  1281. },
  1282. // 更改离地高度
  1283. changeLineHeight(height){//线长
  1284. tag.changeLineLen(height)
  1285. },
  1286. changeCanMove(canMove){
  1287. tag.dragEnable = canMove
  1288. },
  1289. getImageCenter(){ //热点在模型的本地坐标
  1290. /* tag.titleLabel.parent.updateMatrix()
  1291. //tag.titleLabel.parent.updateMatrixWorld()
  1292. let pos = tag.titleLabel.parent.getWorldPosition(new THREE.Vector3)
  1293. console.log(pos) */
  1294. return tag.onMesh ? tag.position : new THREE.Vector3().addVectors(tag.position, tag.titleLabel.parent.position)
  1295. },
  1296. /* toCameraDistance(far){//多远会消失
  1297. tag.farSquared = far * far
  1298. this.updateVisiFar(dis)
  1299. },
  1300. updateVisiFar(){//我自己调用
  1301. if(tag.farSquared){
  1302. let v = viewer.mainViewport.camera.position.distanceToSquared(tag.position) < tag.farSquared
  1303. Potree.Utils.updateVisible(tag,'updateVisiFar',v)
  1304. }
  1305. }, */
  1306. getCameraDisSquared(){//距离intersect的位置
  1307. return viewer.mainViewport.camera.position.distanceToSquared(tag.getWorldPosition(new THREE.Vector3)) /* < tag.farSquared */
  1308. },
  1309. destory(){
  1310. tag.dispose()
  1311. },
  1312. }
  1313. /*
  1314. tag.functions.changeType(props.type)
  1315. tag.functions.changeImage(props.image)
  1316. */
  1317. return tag.functions
  1318. },
  1319. /*
  1320. addTag(info) {//加标签
  1321. let bus = mitt()
  1322. let tag
  1323. let done = () => {
  1324. bus.emit('added')
  1325. bus.emit('update', { position: tag.position.clone(), normal: o.normal.clone(), modelId: tag.root.dataset_id })
  1326. tag = tag_
  1327. tag.spot.addEventListener('mouseover', () => {
  1328. bus.emit('hoverState', true)
  1329. })
  1330. tag.spot.addEventListener('mouseout', () => {
  1331. bus.emit('hoverState', false)
  1332. })
  1333. }
  1334. if (!info.position) {
  1335. viewer.tagTool.startInsertion().done(tag_ => {
  1336. done()
  1337. })
  1338. } else {
  1339. info.root = MergeEditor.getAllObjects().find(e => e.dataset_id == info.modelId)
  1340. if (!info.root) {
  1341. console.error('没有找到该modelId')
  1342. }
  1343. tag = viewer.tagTool.createTagFromData(info)
  1344. done()
  1345. }
  1346. let result = {
  1347. bus,
  1348. getScreenPos() {
  1349. let pos3d = new THREE.Vector3().setFromMatrixPosition(tag.matrixWorld)
  1350. return sdk.getScreenByPosition(pos3d)
  1351. },
  1352. show() {
  1353. Potree.Utils.updateVisible(tag, 'byList', true)
  1354. },
  1355. hide() {
  1356. Potree.Utils.updateVisible(tag, 'byList', false)
  1357. },
  1358. destroy() {
  1359. if (tag) {
  1360. tag.dispose()
  1361. }
  1362. viewer.dispatchEvent({ type: 'cancel_insertions', remove: true })
  1363. },
  1364. changeTitle(title) {
  1365. tag.changeTitle(title)
  1366. }
  1367. }
  1368. return result
  1369. }, */
  1370. /* export type PathProps = {
  1371. line: {
  1372. width: number,
  1373. color: string,
  1374. altitudeAboveGround: number
  1375. position: SceneLocalPos,
  1376. modelId: string
  1377. },
  1378. points: {
  1379. position: SceneLocalPos,
  1380. modelId: string,
  1381. }[]
  1382. } */
  1383. showGrid() {
  1384. Potree.Utils.updateVisible(viewer.modules.MergeEditor.ground, 'hideGrid', true)
  1385. viewer.dispatchEvent('content_changed')
  1386. },
  1387. hideGrid() {
  1388. Potree.Utils.updateVisible(viewer.modules.MergeEditor.ground, 'hideGrid', false)
  1389. viewer.dispatchEvent('content_changed')
  1390. }
  1391. }
  1392. function spliceFromArr(model, props, loaded){
  1393. //let autoLoads.find()
  1394. props.loadFinish = true
  1395. props.loading = false
  1396. if (loaded) {
  1397. props.loaded = true
  1398. props.model = model
  1399. } else {
  1400. props.error = true
  1401. }
  1402. /* let haventLoad = autoLoads.filter(e=>!e.loading && !e.loadFinish);
  1403. if( haventLoad[0]){
  1404. startLoad(haventLoad[0])
  1405. */
  1406. if (!loadNext()) {
  1407. if (autoLoads.filter(e => !e.loadFinish).length == 0 && autoLoads.filter(e => e.loaded).length > 0 && !props.isFirstLoad) {//设置相机位置:当自动开始加载第一个模型时(其余的也跟着自动加载),等这批加载完后;
  1408. let autoLoadsDone = autoLoads.filter(e => e.loaded).map(e => e.model)
  1409. let loadTimeCost = Date.now() - loadStartTime
  1410. console.log('所有模型加载完毕, 耗时', parseInt(loadTimeCost) )
  1411. autoLoads.filter(e => e.loaded && e.show).forEach(e => e.model.visible = true)
  1412. MergeEditor.focusOn(autoLoadsDone, 1000, true, true)
  1413. autoLoads.length = 0
  1414. }
  1415. }
  1416. }
  1417. function loadNext(){
  1418. let haventLoad = autoLoads.filter(e => !e.loading && !e.loadFinish);
  1419. let loading = autoLoads.filter(e => e.loading);
  1420. let needLoad = haventLoad.slice(0, maxLoadingCount - loading.length)
  1421. needLoad.forEach(e => startLoad(e))
  1422. return haventLoad.length > 0
  1423. }
  1424. function startLoad(prop){
  1425. /* if(prop.raw.visible !== 1){//用于临时隐藏
  1426. setTimeout(()=>{
  1427. spliceFromArr(null, prop, false)
  1428. prop.bus.emit('loadError' )
  1429. },1)
  1430. return
  1431. } */
  1432. if(prop.loading || prop.loadFinish)return
  1433. Potree.Log(`--开始加载--`, { font: { color: '#f68' } });
  1434. console.log('id:', prop.id, ', title:', prop.title, ', filename:', Potree.Common.getNameFromURL(prop.url), ', type:', prop.type, prop)
  1435. prop.unlit = prop.renderType != 'normal'
  1436. prop.maximumScreenSpaceError = 70
  1437. prop.prefix = prop.raw.prefix
  1438. /* laserRoot != void 0 && (prop.prefix = laserRoot) //prefix for getdataset
  1439. //Potree.settings.urls.prefix = prop.prefix = '' */
  1440. Potree.addModel(prop, prop.done, prop.progressFun, prop.onError)
  1441. prop.loading = true
  1442. }
  1443. function buildMap(){
  1444. if (Potree.settings.showCesium && !window.cesiumViewer) {
  1445. viewer.backgroundOpacity = 0
  1446. Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2ZGM2YzY0ZC1kNWE0LTRiYTgtYTkwNS1kYmJiODRjMWUwMmQiLCJpZCI6MjMzMTQ1LCJpYXQiOjE3MjI5OTUwNTB9.niqpkl6xOkQ2KeJjelyDDDydmSGqKXKb5cX2NyxSNAw'
  1447. window.cesiumViewer = new Cesium.Viewer('app', {
  1448. useDefaultRenderLoop: true,
  1449. requestRenderMode: true, //add 只有需要render时才会render,如tile加载完后、镜头移动后
  1450. animation: false,
  1451. baseLayerPicker: false,
  1452. fullscreenButton: false,
  1453. geocoder: false,
  1454. homeButton: false,
  1455. infoBox: false,
  1456. sceneModePicker: false,
  1457. selectionIndicator: false,
  1458. timeline: false,
  1459. navigationHelpButton: false,
  1460. //imageryProvider : Cesium.createOpenStreetMapImageryProvider({url : 'https://a.tile.openstreetmap.org/'}),
  1461. imageryProvider: Cesium.UrlTemplateImageryProvider({ //直接用84坐标,不用转高德
  1462. //"https://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&style=7&yrs=m&x=${x}&y=${y}&z=${z}" //
  1463. //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',
  1464. 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',
  1465. minimumLevel: 0,
  1466. maximumLevel: 19
  1467. }),
  1468. //高德秘钥版 imageryProvider: new Cesium.AmapImageryProvider({key, mapStyle: 'normal'})
  1469. //报错 401 (Unauthorized) 的方法 https://blog.csdn.net/LBY_XK/article/details/121992641
  1470. terrainShadows: Cesium.ShadowMode.DISABLED, //terrain地形
  1471. });
  1472. //lonlat = [113.595236803415,22.3665168584444]//[113.600356,22.364093]
  1473. Potree.setLonlat(lonlat[0], lonlat[1])
  1474. Potree.cesScreenshot = (w,h)=>{
  1475. console.log('cesScreenshot',w,h)
  1476. cesiumViewer.scene.canvas.style.width = w+'px'
  1477. cesiumViewer.scene.canvas.style.height = h+'px'
  1478. cesiumViewer.scene.canvas.style.visibility = 'hidden'
  1479. cesiumViewer.resize()
  1480. cesAspect = w/h
  1481. let deferred = $.Deferred();
  1482. updateMap(w/h)//hfov可能改变了需要update。
  1483. setTimeout(()=>{ //延迟是似乎还要做别的处理,否则立即截图的话可能得到绿色底图(俯视状态容易触发)
  1484. let oldMode = window.cesiumViewer._cesiumWidget._scene.requestRenderMode
  1485. window.cesiumViewer._cesiumWidget._scene.requestRenderMode = 0 //强制render,否则会黑屏
  1486. cesiumViewer.render();
  1487. let dataUrl = window.cesiumViewer.scene.canvas.toDataURL('image/png')
  1488. window.cesiumViewer._cesiumWidget._scene.requestRenderMode = oldMode
  1489. //Potree.Common.downloadFile(dataUrl, 'screenshot.png')
  1490. cesAspect = null
  1491. cesiumViewer.scene.canvas.style.width = ''
  1492. cesiumViewer.scene.canvas.style.height = ''
  1493. cesiumViewer.scene.canvas.style.visibility = ''
  1494. deferred.resolve(dataUrl)
  1495. },200) //时间短了容易黑屏
  1496. return deferred.promise()
  1497. }
  1498. }
  1499. updateMap()
  1500. }
  1501. function updateCamNear(type){// 有的漫游场景模型缩放的很小(0.1%),需要缩小near才能看见, 但会造成z-fighting, 离远了看大模型会闪烁
  1502. const min = 0.0001, max = 0.1
  1503. let near , bigScale = 0.2
  1504. if(Potree.settings.displayMode == 'showPanos'/* && type != 'cameraMove' */){
  1505. let currentModel = viewer.images360.currentPano.pointcloud
  1506. near = Potree.math.linearClamp(currentModel.scale.x, [0, 1], [min, max])
  1507. }else/* if(type == 'cameraMove') */{
  1508. //没有完美的解决方式,优先考虑选中的模型。否则优先考虑离得近的。 另外尽量用大的,因为缩很小的情况很少。
  1509. //虽然案例说应该看model.bound.size,但如果非场景模型,缩很小的话也不需要凑近看。
  1510. let allModels = viewer.objs.children.concat(viewer.scene.pointclouds)
  1511. if(allModels.length == 0)return
  1512. allModels.sort((a,b)=>{return a.scale.x - b.scale.x})
  1513. let minS = allModels[0].scale.x, maxS = allModels.pop().scale.x
  1514. let considerModel
  1515. if(minS>bigScale) near = max
  1516. else{
  1517. if(MergeEditor.selected){
  1518. considerModel = MergeEditor.selected
  1519. near = Potree.math.linearClamp(considerModel.scale.x, [0, bigScale], [min, max])
  1520. }else{
  1521. //allModels = allModels.filter() //写不下去了好难,就算了吧, 折中
  1522. near = Potree.math.linearClamp(minS, [0, bigScale], [max/4, max])
  1523. }
  1524. }
  1525. }
  1526. if(near != viewer.mainViewport.camera.near){
  1527. console.log('updateNear',near)
  1528. viewer.mainViewport.camera.near = near
  1529. viewer.mainViewport.camera.updateProjectionMatrix()
  1530. viewer.dispatchEvent('content_changed')
  1531. }
  1532. }
  1533. function updateMap( ){
  1534. if (Potree.settings.showCesium && Potree.settings.displayMode == 'showPointCloud') {
  1535. let camera = viewer.mainViewport.camera
  1536. let pPos = new THREE.Vector3(0, 0, 0).applyMatrix4(camera.matrixWorld);
  1537. let pRight = new THREE.Vector3(600, 0, 0).applyMatrix4(camera.matrixWorld);
  1538. let pUp = new THREE.Vector3(0, 600, 0).applyMatrix4(camera.matrixWorld);
  1539. let pTarget = viewer.scene.view.getPivot();
  1540. let toCes = (pos) => {
  1541. let xy = [pos.x, pos.y];
  1542. let height = pos.z;
  1543. let deg = viewer.transform.lonlatToLocal.inverse(xy) // toMap.forward(xy);
  1544. let cPos = Cesium.Cartesian3.fromDegrees(...deg, height);
  1545. return cPos;
  1546. };
  1547. let cPos = toCes(pPos);
  1548. let cUpTarget = toCes(pUp);
  1549. let cTarget = toCes(pTarget);
  1550. let cDir = Cesium.Cartesian3.subtract(cTarget, cPos, new Cesium.Cartesian3());
  1551. let cUp = Cesium.Cartesian3.subtract(cUpTarget, cPos, new Cesium.Cartesian3());
  1552. cDir = Cesium.Cartesian3.normalize(cDir, new Cesium.Cartesian3());
  1553. cUp = Cesium.Cartesian3.normalize(cUp, new Cesium.Cartesian3());
  1554. cesiumViewer.camera.setView({
  1555. destination: cPos,
  1556. orientation: {
  1557. direction: cDir,
  1558. up: cUp
  1559. }
  1560. });
  1561. let aspect = cesAspect || viewer.scene.getActiveCamera().aspect;
  1562. //console.log('updateMap', aspect)
  1563. if (aspect < 1) {
  1564. let fovy = Math.PI * (viewer.scene.getActiveCamera().fov / 180);
  1565. cesiumViewer.camera.frustum.fov = fovy;
  1566. } else {
  1567. let fovy = Math.PI * (viewer.scene.getActiveCamera().fov / 180);
  1568. let fovx = Math.atan(Math.tan(0.5 * fovy) * aspect) * 2
  1569. cesiumViewer.camera.frustum.fov = fovx;
  1570. }
  1571. cesiumViewer.render(); //立即render,否则会和点云render不同步而错位
  1572. }
  1573. }
  1574. return sdk
  1575. }
  1576. /*
  1577. 暂定不同场景间的漫游点不能互通。虽然它们可能是摆放正确的,如果是组成一整个场景的话还是要打通……
  1578. 不互通的方法是设置pano.enable
  1579. 现在需要互通了。但是还需要设置neibgbours, 有点麻烦,暂时没写。
  1580. */
  1581. export default enter