RouteGuider.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. import * as THREE from "../../../../libs/three.js/build/three.module.js";
  2. import {Utils} from "../../../utils.js";
  3. import Sprite from '../../objects/Sprite.js'
  4. import Common from "../../utils/Common.js";
  5. import browser from '../../utils/browser.js'
  6. const texLoader = new THREE.TextureLoader()
  7. const arrowSpacing = 1 //间隔
  8. const arrowSize = arrowSpacing * 0.5
  9. const planeGeo = new THREE.PlaneBufferGeometry(1,1);
  10. const sphereSizeInfo = {
  11. nearBound : 0.1, farBound:25, minSize : 50, maxSize : 200 //scale:arrowSize, restricMeshScale : true,
  12. }
  13. //const arrowsShowingCount = 25; //场景里最多展示多少个箭头
  14. const arrowShowMinDis = 10
  15. export class RouteGuider extends THREE.EventDispatcher{
  16. constructor () {
  17. super();
  18. this.route = [];
  19. this.curve = []
  20. this.scenePoints = []
  21. this.sceneMeshGroup = new THREE.Object3D;
  22. this.mapMeshGroup = new THREE.Object3D;
  23. this.generateDeferred;
  24. viewer.addEventListener('loadPointCloudDone',this.init.bind(this))
  25. this.lastResult;//保存上一个的结果,以便于反向
  26. this.datasetIds = [];//起始和终点的datasetId
  27. }
  28. init(){
  29. if(this.inited) return;
  30. let zoom, resolution=new THREE.Vector2;
  31. viewer.mapViewer.addEventListener('camera_changed', e => {
  32. if(!this.routeStart || !this.routeEnd) return
  33. var camera = e.viewport.camera
  34. Common.intervalTool.isWaiting('routeCameraInterval', ()=>{ //延时update,防止卡顿
  35. if(camera.zoom != zoom || !resolution.equals(e.viewport.resolution)){
  36. //console.log('updateMapArrows')
  37. this.updateMapArrows(true)
  38. zoom = camera.zoom; resolution.copy(e.viewport.resolution)
  39. return true
  40. }
  41. }, browser.isMobile()?500:200)
  42. })
  43. let lastPos = new THREE.Vector3
  44. viewer.addEventListener('camera_changed', e => {
  45. if(!this.routeStart || !this.routeEnd || !e.changeInfo.positionChanged) return
  46. Common.intervalTool.isWaiting('routeCameraInterval2', ()=>{ //延时update,防止卡顿
  47. let currPos = viewer.scene.getActiveCamera().position
  48. if(!currPos.equals(lastPos)){
  49. lastPos.copy(currPos)
  50. this.updateArrowDisplay()
  51. return true
  52. }
  53. }, 1000)
  54. })
  55. var polesMats = {
  56. shadowMat: new THREE.MeshBasicMaterial({
  57. transparent:true, depthTest:false,
  58. map: texLoader.load(Potree.resourcePath+'/textures/pano_instruction_bottomMarker.png' )
  59. }),
  60. sphereMat : new THREE.MeshBasicMaterial({
  61. transparent:true, depthTest:false,
  62. map: texLoader.load(Potree.resourcePath+'/textures/whiteCircle.png' )
  63. }),
  64. hatMats:{
  65. start: new THREE.MeshBasicMaterial({
  66. transparent:true, depthTest:false,
  67. map: texLoader.load(Potree.resourcePath+'/textures/pano_instruction_start_route.png' )
  68. }),
  69. end: new THREE.MeshBasicMaterial({
  70. transparent:true, depthTest:false,
  71. map: texLoader.load(Potree.resourcePath+'/textures/pano_instruction_target_reached.png' )
  72. })
  73. }
  74. }
  75. polesMats.shadowMat.map.anisotropy = 4
  76. this.poleStart = this.createPole(polesMats, 'start')
  77. this.poleEnd = this.createPole(polesMats, 'end')
  78. this.sceneMeshGroup.add(this.poleStart)
  79. this.sceneMeshGroup.add(this.poleEnd)
  80. let map = texLoader.load(Potree.resourcePath+'/textures/routePoint_panorama.png' )
  81. map.anisotropy = 4 // 各向异性过滤 .防止倾斜模糊
  82. this.arrow = new THREE.Mesh(planeGeo, new THREE.MeshBasicMaterial({
  83. transparent:true,
  84. depthTest:false,
  85. map
  86. }))
  87. this.arrow.scale.set(arrowSize,arrowSize,arrowSize)
  88. Potree.Utils.setObjectLayers(this.arrow, 'sceneObjects' )
  89. /* this.testArrow = this.arrow.clone();
  90. this.testArrow.material = this.arrow.material.clone()
  91. this.testArrow.material.color = 'red' */
  92. this.arrows = new THREE.Object3D;
  93. this.sceneMeshGroup.add(this.arrows)
  94. Potree.Utils.setObjectLayers(this.sceneMeshGroup, 'sceneObjects' )
  95. //this.sceneMeshGroup.traverse(e=>e.renderOrder = 90)
  96. viewer.scene.scene.add(this.sceneMeshGroup);
  97. this.sceneMeshGroup.visible = /* this.poleStart.visibile = this.poleEnd.visibile = */ false
  98. //-------------map---------------------
  99. /* this.mapMarkStart = new THREE.Mesh( planeGeo, new THREE.MeshBasicMaterial({
  100. transparent:true, depthTest:false,
  101. map: texLoader.load(Potree.resourcePath+'/textures/map_instruction_start_route.png' )
  102. }))
  103. this.mapMarkEnd = new THREE.Mesh( planeGeo, new THREE.MeshBasicMaterial({
  104. transparent:true, depthTest:false,
  105. map: texLoader.load(Potree.resourcePath+'/textures/map_instruction_target_reached.png' )
  106. }))
  107. this.mapMarkStart.renderOrder = this.mapMarkEnd.renderOrder = 2//在箭头之上 */
  108. let map2 = texLoader.load(Potree.resourcePath+'/textures/routePoint_map_fsna.png' )
  109. this.mapArrowMats = {
  110. default: new THREE.MeshBasicMaterial({
  111. transparent:true, depthTest:false,
  112. map:map2,
  113. }),
  114. fade: new THREE.MeshBasicMaterial({
  115. transparent:true, depthTest:false,
  116. map:map2,
  117. opacity:0.4
  118. }),
  119. }
  120. this.mapArrow = new THREE.Mesh( planeGeo, this.mapArrowMats.default)
  121. this.mapArrow.scale.set(arrowSize,arrowSize,arrowSize)
  122. this.mapArrows = new THREE.Object3D;
  123. this.mapArrows.name = 'mapArrows'
  124. this.mapMeshGroup.add(this.mapArrows)
  125. this.mapMeshGroup.name = 'mapRouteLayer'
  126. this.mapMeshGroup.visible = false
  127. viewer.mapViewer.dispatchEvent({type:'add', object:this.mapMeshGroup, name:'route'})
  128. this.mapArrow.layers.mask = this.mapArrows.layers.mask // 修改成和map中的layer一样的
  129. viewer.modules.SiteModel.bus.addEventListener('FloorChange',()=>{
  130. if(this.routeStart && this.routeEnd){
  131. this.updateOpacityAtMap()
  132. }
  133. })
  134. this.inited = true
  135. }
  136. updateOpacityAtMap(){//只有当前楼层的透明度为1
  137. var currentFloor = viewer.modules.SiteModel.currentFloor
  138. //console.log('updateOpacityAtMap', currentFloor && currentFloor.name)
  139. const lift = 0.3 // 因为发送请求时用的是floorPosition的高度,而它可能会到画好的floor之下,所以有误差
  140. this.mapArrows.children.forEach((arrow,index)=>{
  141. let pos = this.mapPoints[index].clone()
  142. pos.z += lift
  143. let inSide = currentFloor && currentFloor.ifContainsPoint(pos)
  144. arrow.material = inSide ? this.mapArrowMats.default : this.mapArrowMats.fade
  145. //console.log('arrow',index, arrow.material.opacity)
  146. })
  147. viewer.mapViewer.dispatchEvent('content_changed')
  148. }//但是如果楼层刚好只框柱相机位置而没框住地面位置就不好了……
  149. createPole(polesMats, name){
  150. const height = 1.5, sphereCount = 6, shadowSize = 0.5 /* sphereSizeInfo.scale */, sphereSize = 0.05
  151. var group = new THREE.Object3D;
  152. group.name = 'pole_'+name
  153. var shadow = new THREE.Mesh(planeGeo, polesMats.shadowMat)
  154. shadow.scale.set(shadowSize,shadowSize,shadowSize)
  155. var sliceDis = height / (sphereCount+1);
  156. group.add(shadow)
  157. for(let i=0;i<sphereCount;i++){
  158. var sphere = new Sprite({mat: polesMats.sphereMat, renderOrder:3})
  159. sphere.position.set(0,0,sliceDis*(i+1))
  160. sphere.scale.set(sphereSize,sphereSize,sphereSize);
  161. sphere.visible = false
  162. group.add(sphere)
  163. }
  164. var hatSphere = new Sprite({mat: polesMats.hatMats[name], sizeInfo:sphereSizeInfo, renderOrder:4})
  165. sphere.visible = false
  166. hatSphere.position.set(0,0,height)
  167. hatSphere.scale.copy(shadow.scale)
  168. group.add(hatSphere)
  169. return group
  170. }
  171. addTestArrow(){
  172. }
  173. addArrow(position){
  174. var arrow = this.arrow.clone()
  175. arrow.position.copy(position);
  176. this.arrows.add(arrow);
  177. }
  178. addMapArrow(position){
  179. var mapArrow = this.mapArrow.clone()
  180. mapArrow.position.copy(position).setZ(0)
  181. this.mapArrows.add(mapArrow);
  182. }
  183. setArrowDir(arrows,index){
  184. let arrow = arrows[index]
  185. var nextOne = arrows[index+1];
  186. var nextPos = nextOne ? nextOne.position : this.endPolePos //routeEnd
  187. var direction = new THREE.Vector3().subVectors(arrow.position, nextPos).setZ(0);
  188. //direction.normalize();
  189. //console.log(direction.toArray())
  190. var angle = Math.atan2(direction.y, direction.x ) + Math.PI/2 //Math.PI/2是因为贴图本身箭头方向不朝x
  191. arrow.rotation.z = angle
  192. //console.log(angle)
  193. }
  194. setRouteStart(pos, dealZ , datasetId ){
  195. if(this.routeStart && pos && this.routeStart.equals(pos)) return //可能重复设置
  196. this.routeStart = pos && new THREE.Vector3().copy(pos)
  197. if(dealZ && this.routeStart){
  198. this.routeStart.setZ(this.getZAtMap())
  199. this.bus && this.bus.emit('reposStartMarker', this.routeStart)
  200. }
  201. console.log('setRouteStart',this.routeStart&&this.routeStart.toArray())
  202. this.datasetIds[0] = datasetId
  203. //this.setStartPole(pos)
  204. this.generateRoute()
  205. }
  206. setStartPole(pos){
  207. this.startPolePos = pos
  208. this.bus && this.bus.emit('reposStartMarker', pos)
  209. }
  210. setRouteEnd(pos, dealZ , datasetId ){
  211. if(this.routeEnd && pos && this.routeEnd.equals(pos)) return
  212. this.routeEnd = pos && new THREE.Vector3().copy(pos)
  213. if(dealZ && this.routeEnd){
  214. this.routeEnd.setZ(this.getZAtMap())
  215. this.bus && this.bus.emit('reposEndMarker', this.routeEnd)
  216. }
  217. console.log('setRouteEnd',this.routeEnd&&this.routeEnd.toArray())
  218. this.datasetIds[1] = datasetId
  219. //this.setEndPole(pos)
  220. this.generateRoute()
  221. }
  222. getZAtMap(){
  223. //找到position.z与当前高度最接近的漫游点
  224. let result = Common.sortByScore(viewer.images360.panos,[],[e=> -(Math.abs(e.position.z - viewer.images360.position.z)) ])
  225. let pano = result && result[0] && result[0].item
  226. return pano ? pano.floorPosition.z : viewer.bound.boundingBox.min.z + 1
  227. //若在平面图上画实在得不到当前楼层的,大概率是楼层画得不好,那就只能去获取当前楼层的了
  228. //navvis的高度取的是主视图所在楼层的中心高度(可能再高些)
  229. }
  230. setEndPole(pos){
  231. this.endPolePos = pos
  232. this.bus && this.bus.emit('reposEndMarker', pos)
  233. }
  234. getSourceProjectionIndex(route) {//真正的起始
  235. var e = route.findIndex(function(t) {
  236. return t.instruction && t.instruction.type === 'source_projection_to_navgraph'
  237. });
  238. return e < 0 ? 0 : e
  239. }
  240. getDestinationProjectionIndex(route) {//真正的终点
  241. var e = route.findIndex(function(t) {
  242. return t.instruction && t.instruction.type === "destination_projection_to_navgraph"
  243. });
  244. return e < 0 ? route.length - 1 : e
  245. }
  246. generateRoute(){
  247. if(!this.routeStart || !this.routeEnd){
  248. return
  249. }
  250. //array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
  251. let create = ()=>{
  252. this.routeLength = this.route.reduce((total, currentValue, currentIndex, arr)=>{
  253. if(currentIndex == 0)return 0
  254. return total + currentValue.distanceTo(arr[currentIndex-1]);
  255. },0)
  256. let count = Math.max(2,Math.round(this.routeLength / arrowSpacing))//点数
  257. const curve = new THREE.CatmullRomCurve3( this.route );
  258. curve.curveType = 'chordal'//'centripetal' 'catmullrom'这个可能会超出路径外
  259. this.curve = curve
  260. const scenePoints = curve.getSpacedPoints( count );//更平均
  261. //const scenePoints = curve.getPoints( count );
  262. scenePoints.splice(0,1);//去掉首尾
  263. scenePoints.pop()
  264. this.scenePoints = scenePoints
  265. this.updateMapArrows()
  266. this.displayRoute()
  267. {//map focus on this area
  268. const minBound = new THREE.Vector2(1,1)//针对垂直线,在地图上只有一个点
  269. let bound = new THREE.Box2;
  270. this.route.forEach(e=>{
  271. bound.expandByPoint(e)
  272. })
  273. let size = bound.getSize(new THREE.Vector2)
  274. let markerSize = new THREE.Vector2(115,40) //起始和终点的标识呈长方形
  275. let areaSize = viewer.mapViewer.viewports[0].resolution2
  276. let areaArea = areaSize.x * areaSize.y
  277. if(areaArea> 800 * 400){//是放大的
  278. markerSize.multiplyScalar(areaArea / (800 * 400) /* / (size.x * size.y) */)
  279. }
  280. let margin = size.clone().divide(viewer.mapViewer.viewports[0].resolution2).multiply(markerSize) ///边距 重点是起始和终点的标识占据较大
  281. size.add(margin)
  282. let center = bound.getCenter(new THREE.Vector2)
  283. size.x = Math.max(size.x, minBound.x )
  284. size.y = Math.max(size.y, minBound.y )
  285. let duration = 1000
  286. viewer.mapViewer.moveTo(center, size, duration)
  287. }
  288. this.bus.emit('gotResult', {dis:this.routeLength})
  289. /* this.generateDeferred && this.generateDeferred.resolve({dis:this.routeLength})
  290. this.generateDeferred = null */
  291. }
  292. if(Potree.fileServer){
  293. let dealData = (data)=>{
  294. if(!data.data){
  295. console.log('没有数据')
  296. let result
  297. if(data && data.code == 4002){
  298. result = data;//正被修改数据集
  299. }else if(this.routeStart.distanceTo(this.routeEnd) < 1){
  300. result = { code: 500, msg: '距离太短,无法规划路线' }
  301. }else{
  302. result = { code: 500, msg: '超出数据集范围,无法规划路线' }
  303. }
  304. this.clearRoute()
  305. this.setStartPole(this.routeStart)
  306. this.setEndPole(this.routeEnd)
  307. this.displayRoute() //还是要显示一下起始
  308. this.bus && this.bus.emit('gotResult', result )
  309. return //this.generateDeferred && this.generateDeferred.resolve()
  310. }
  311. data = data.data
  312. this.clearRoute()
  313. let length = data.length
  314. if(length < 2){//可能距离太短
  315. console.log('路径点数为'+length+',直接取起点和终点连线')
  316. this.route = [this.routeStart, this.routeEnd];
  317. }else{
  318. let startIndex = this.getSourceProjectionIndex(data)
  319. let endIndex = this.getDestinationProjectionIndex(data)
  320. let effectiveItems = data.slice(startIndex, endIndex + 1 );//只要点云范围内的点
  321. effectiveItems.forEach((item,i)=>{
  322. let pos = viewer.transform.lonlatToLocal.forward(item.location.slice(0))
  323. pos = new THREE.Vector3().fromArray(pos)//.setZ(item.z)
  324. this.route.push(pos)
  325. })
  326. console.log(this.route)
  327. }
  328. this.setStartPole(this.route[0])
  329. this.setEndPole(this.route[this.route.length-1])
  330. create()
  331. /*
  332. distance: 0.17581000000000116
  333. distance_to_previous: 0.17581000000000116
  334. id: 567
  335. instruction: {type: 'source_projection_to_navgraph'}
  336. latitude: 22.366605927999238
  337. location: (3) [113.5957510575092, 22.366605927999238, -1.12419]
  338. longitude: 113.5957510575092
  339. z: -1.12419
  340. */
  341. }
  342. if(this.lastResult && (this.lastResult.data || this.lastResult.data.code != 4002)){//正被修改数据集的话要重新计算
  343. let data = Common.CloneObject(this.lastResult.data) , use; //直接用上次的结果
  344. if(this.lastResult.routeStart.equals(this.routeStart) && this.lastResult.routeEnd.equals(this.routeEnd)){//和上次请求相同
  345. use = true
  346. }else if(this.lastResult.routeStart.equals(this.routeEnd) && this.lastResult.routeEnd.equals(this.routeStart)){//..反向
  347. use = true
  348. if(data.data){
  349. data.data = this.lastResult.data.data.slice(0).reverse()
  350. }
  351. }
  352. if(use){
  353. console.log('直接用上次的结果')
  354. return setTimeout(()=>{dealData(data)}, 1)//延迟是为了等待获得 RouteGuider.generateDeferred
  355. }
  356. }
  357. let start = this.routeStart.clone();
  358. let end = this.routeEnd.clone();
  359. let startLonlat = viewer.transform.lonlatToLocal.inverse(start)
  360. let endLonlat = viewer.transform.lonlatToLocal.inverse(end)
  361. var query = {
  362. source_longitude: startLonlat.x,
  363. source_latitude: startLonlat.y,
  364. source_z: start.z,
  365. destination_longitude: endLonlat.x,
  366. destination_latitude: endLonlat.y,
  367. destination_z: end.z
  368. };
  369. //let url = `/laser/route/${Potree.settings.number}/getRoute/${this.datasetIds[0]}/${this.datasetIds[1]}?`
  370. let url = `/laser/route/${Potree.settings.number}/getRoute/${Potree.settings.originDatasetId}?`
  371. for(let i in query){
  372. url+= (i + '='+ query[i] +'&')
  373. }
  374. Potree.fileServer.get(url).then((data)=>{
  375. console.log(data.data)
  376. if(!this.routeStart || !this.routeEnd)return
  377. this.lastResult = {//保存数据
  378. routeStart : this.routeStart.clone(),
  379. routeEnd: this.routeEnd.clone(),
  380. data,
  381. }
  382. dealData(data)
  383. })
  384. }else{
  385. //创个直线
  386. /* const sliceDis = 1
  387. let dis = this.routeStart.distanceTo(this.routeEnd);
  388. let count = Math.max(2,Math.round(dis / sliceDis))//点数
  389. let realSlideDis = dis / (count-1);
  390. let dir = new THREE.Vector3().subVectors(this.routeEnd, this.routeStart).normalize().multiplyScalar(realSlideDis);
  391. this.route = [this.routeStart];
  392. for(let i=0;i<count-1;i++){
  393. let lastOne = this.route[i];
  394. this.route.push(new THREE.Vector3().addVectors(lastOne,dir))
  395. }
  396. this.route.splice(0,1) //route不用包含收尾 */
  397. this.clearRoute()
  398. this.route = [this.routeStart, this.routeEnd]
  399. create()
  400. }
  401. }
  402. updateMapArrows(ifReset){
  403. if(this.route.length == 0)return
  404. var zoom = viewer.mapViewer.camera.zoom
  405. let isBig = viewer.mapViewer.viewports[0].resolution.y > 300
  406. let count = Math.max(2,Math.round(this.routeLength * zoom / arrowSpacing / (isBig?35:30)))//点数
  407. if(count == this.mapPoints.length+1)return//没变
  408. const mapPoints = this.curve.getSpacedPoints( count );
  409. mapPoints.splice(0,1);//去掉首尾
  410. mapPoints.pop()
  411. this.mapPoints = mapPoints
  412. var scale = (isBig ? 26 : 22)/zoom
  413. this.mapArrow.scale.set(scale,scale,scale)
  414. /* this.mapMarkStart.scale.set(scale,scale,scale)
  415. this.mapMarkEnd.scale.set(scale,scale,scale) */
  416. if(ifReset){//因为缩放而重新排布箭头
  417. this.clearRoute({resetMap:true})
  418. this.displayRoute({resetMap:true})
  419. }
  420. this.updateOpacityAtMap()
  421. }
  422. updateArrowDisplay(){//根据当前位置更新显示一定范围内的箭头
  423. if(this.scenePoints.length == 0)return
  424. /* var a = Common.sortByScore(this.scenePoints , null, [(point)=>{ //是否还要再requires里限制最远距离?
  425. var playerPos = viewer.scene.getActiveCamera().position.clone().setZ(0)
  426. var pos = point.clone().setZ(0)
  427. return -pos.distanceTo(playerPos);
  428. }]);
  429. //获得展示的起始点
  430. let start = a[0].item
  431. let startIndex = this.scenePoints.indexOf(start)
  432. this.arrows.children.forEach((e,i)=>{
  433. if(i<startIndex || i>startIndex+arrowsShowingCount)e.visible = false
  434. else e.visible = true
  435. }) */
  436. let cameraPos = viewer.scene.getActiveCamera().position
  437. this.arrows.children.forEach((e,i)=>{
  438. if(e.position.distanceTo(cameraPos) < arrowShowMinDis) e.visible = true
  439. else e.visible = false
  440. })
  441. viewer.dispatchEvent('content_changed')
  442. }
  443. displayRoute(o={}){
  444. if(!o.resetMap){
  445. this.poleStart.position.copy(this.startPolePos || this.routeStart)
  446. this.poleEnd.position.copy(this.endPolePos || this.routeEnd)
  447. /* this.mapMarkStart.position.copy(this.routeStart).setZ(0)
  448. this.mapMarkEnd.position.copy(this.routeEnd).setZ(0) */
  449. this.scenePoints.forEach(e=>this.addArrow(e))
  450. this.arrows.children.forEach((e,i)=>this.setArrowDir(this.arrows.children,i));
  451. }
  452. this.sceneMeshGroup.traverse(e=>e.visible = true)
  453. this.mapMeshGroup.visible = true
  454. this.mapPoints.forEach(e=>this.addMapArrow(e))
  455. this.mapArrows.children.forEach((e,i)=>this.setArrowDir(this.mapArrows.children,i));
  456. viewer.mapViewer.dispatchEvent({'type':'content_changed'})
  457. this.updateArrowDisplay()
  458. }
  459. clearRoute(o={}){
  460. if(!o.resetMap){
  461. this.routeLength = 0
  462. this.route = []
  463. this.scenePoints = []
  464. this.mapPoints = []
  465. let arrows = this.arrows.children.slice(0)
  466. arrows.forEach(e=>{
  467. this.arrows.remove(e)
  468. })
  469. }
  470. let mapArrows = this.mapArrows.children.slice(0)
  471. mapArrows.forEach(e=>{
  472. this.mapArrows.remove(e)
  473. })
  474. this.sceneMeshGroup.traverse(e=>e.visible = false) //包括sprite也要设置,防止update
  475. this.mapMeshGroup.visible = false
  476. viewer.mapViewer.dispatchEvent({'type':'content_changed'})
  477. viewer.dispatchEvent('content_changed')
  478. }
  479. clear(){//退出
  480. console.log('导航clear')
  481. this.routeStart = null
  482. this.routeEnd = null
  483. this.clearRoute()
  484. }
  485. }
  486. //大概每十米要花一秒
  487. /*
  488. 存在的问题:
  489. 路径不准确。起始点和终点偏移。
  490. https://uat-laser.4dkankan.com/routeDebug/ 可查整个map的通路点位图
  491. */