RouteGuider.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. import * as THREE from "../../libs/three.js/build/three.module.js";
  2. import {Utils} from "../utils.js";
  3. import { EventDispatcher } from "../EventDispatcher.js";
  4. import Sprite from '../viewer/Sprite'
  5. const texLoader = new THREE.TextureLoader()
  6. const arrowSpacing = 1 //间隔
  7. const arrowSize = arrowSpacing * 0.5
  8. const planeGeo = new THREE.PlaneBufferGeometry(1,1);
  9. const sphereSizeInfo = {
  10. nearBound : 2, scale:arrowSize, restricMeshScale : true,
  11. }
  12. export class RouteGuider extends EventDispatcher{
  13. constructor () {
  14. super();
  15. this._routeStart = null
  16. this._routeEnd = null
  17. this.route = [];
  18. this.curve = []
  19. this.sceneMeshGroup = new THREE.Object3D;
  20. this.mapMeshGroup = new THREE.Object3D;
  21. viewer.addEventListener('loadPointCloudDone',this.init.bind(this))
  22. }
  23. init(){
  24. if(this.inited) return;
  25. var polesMats = {
  26. shadowMat: new THREE.MeshBasicMaterial({
  27. transparent:true, depthTest:false,
  28. map: texLoader.load(Potree.resourcePath+'/textures/pano_instruction_bottomMarker.png' )
  29. }),
  30. sphereMat : new THREE.MeshBasicMaterial({
  31. transparent:true, depthTest:false,
  32. map: texLoader.load(Potree.resourcePath+'/textures/whiteCircle.png' )
  33. }),
  34. hatMats:{
  35. start: new THREE.MeshBasicMaterial({
  36. transparent:true, depthTest:false,
  37. map: texLoader.load(Potree.resourcePath+'/textures/pano_instruction_start_route.png' )
  38. }),
  39. end: new THREE.MeshBasicMaterial({
  40. transparent:true, depthTest:false,
  41. map: texLoader.load(Potree.resourcePath+'/textures/pano_instruction_target_reached.png' )
  42. })
  43. }
  44. }
  45. this.poleStart = this.createPole(polesMats, 'start')
  46. this.poleEnd = this.createPole(polesMats, 'end')
  47. this.sceneMeshGroup.add(this.poleStart)
  48. this.sceneMeshGroup.add(this.poleEnd)
  49. let map = texLoader.load(Potree.resourcePath+'/textures/routePoint_panorama.png' )
  50. map.anisotropy = 4 // 各向异性过滤 .防止倾斜模糊
  51. this.arrow = new THREE.Mesh(planeGeo, new THREE.MeshBasicMaterial({
  52. transparent:true,
  53. depthTest:false,
  54. map
  55. }))
  56. this.arrow.scale.set(arrowSize,arrowSize,arrowSize)
  57. viewer.setObjectLayers(this.arrow, 'route' )
  58. this.testArrow = this.arrow.clone();
  59. this.testArrow.material = this.arrow.material.clone()
  60. this.testArrow.material.color = 'red'
  61. this.arrows = new THREE.Object3D;
  62. this.sceneMeshGroup.add(this.arrows)
  63. viewer.setObjectLayers(this.sceneMeshGroup, 'route' )
  64. //this.sceneMeshGroup.traverse(e=>e.renderOrder = 90)
  65. viewer.scene.scene.add(this.sceneMeshGroup);
  66. this.sceneMeshGroup.visible = /* this.poleStart.visibile = this.poleEnd.visibile = */ false
  67. //-------------map---------------------
  68. this.mapMarkStart = new THREE.Mesh( planeGeo, new THREE.MeshBasicMaterial({
  69. transparent:true, depthTest:false,
  70. map: texLoader.load(Potree.resourcePath+'/textures/map_instruction_start_route.png' )
  71. }))
  72. this.mapMarkEnd = new THREE.Mesh( planeGeo, new THREE.MeshBasicMaterial({
  73. transparent:true, depthTest:false,
  74. map: texLoader.load(Potree.resourcePath+'/textures/map_instruction_target_reached.png' )
  75. }))
  76. this.mapArrow = new THREE.Mesh( planeGeo, new THREE.MeshBasicMaterial({
  77. transparent:true, depthTest:false,
  78. map: texLoader.load(Potree.resourcePath+'/textures/routePoint_map_fsna.png' )
  79. }))
  80. this.mapArrow.scale.set(arrowSize,arrowSize,arrowSize)
  81. this.mapArrows = new THREE.Object3D;
  82. this.mapArrows.name = 'mapArrows'
  83. //viewer.setObjectLayers(this.mapArrow, 'route' )
  84. this.mapMeshGroup.add(this.mapMarkStart)
  85. this.mapMeshGroup.add(this.mapMarkEnd)
  86. this.mapMeshGroup.add(this.mapArrows)
  87. this.mapMeshGroup.name = 'mapRouteLayer'
  88. this.mapMeshGroup.visible = /* this.mapMarkStart.visible = this.mapMarkEnd.visible = */ false
  89. viewer.mapViewer.emit('add',{object:this.mapMeshGroup, name:'route'})
  90. this.mapArrow.layers.mask = this.mapArrows.layers.mask // 修改成和map中的layer一样的
  91. this.inited = true
  92. }
  93. createPole(polesMats, name){
  94. const height = 1.5, sphereCount = 6, shadowSize = sphereSizeInfo.scale, sphereSize = 0.04
  95. var group = new THREE.Object3D;
  96. group.name = 'pole_'+name
  97. var shadow = new THREE.Mesh(planeGeo,polesMats.shadowMat)
  98. shadow.scale.set(shadowSize,shadowSize,shadowSize)
  99. var sliceDis = height / (sphereCount+1);
  100. group.add(shadow)
  101. for(let i=0;i<sphereCount;i++){
  102. var sphere = new Sprite({mat: polesMats.sphereMat})
  103. sphere.position.set(0,0,sliceDis*(i+1))
  104. sphere.scale.set(sphereSize,sphereSize,sphereSize);
  105. group.add(sphere)
  106. }
  107. var hatSphere = new Sprite({mat: polesMats.hatMats[name], sizeInfo:sphereSizeInfo})
  108. hatSphere.position.set(0,0,height)
  109. hatSphere.scale.copy(shadow.scale)
  110. group.add(hatSphere)
  111. return group
  112. }
  113. addTestArrow(){
  114. }
  115. addArrow(position){
  116. var arrow = this.arrow.clone()
  117. arrow.position.copy(position);
  118. this.arrows.add(arrow);
  119. }
  120. addMapArrow(position){
  121. var mapArrow = this.mapArrow.clone()
  122. mapArrow.position.copy(position).setZ(0)
  123. this.mapArrows.add(mapArrow);
  124. }
  125. setArrowDir(arrows,index){
  126. let arrow = arrows[index]
  127. var nextOne = arrows[index+1];
  128. var nextPos = nextOne ? nextOne.position : this.routeEnd
  129. var direction = new THREE.Vector3().subVectors(arrow.position, nextPos).setZ(0);
  130. //direction.normalize();
  131. //console.log(direction.toArray())
  132. var angle = Math.atan2(direction.y, direction.x ) + Math.PI/2 //Math.PI/2是因为贴图本身箭头方向不朝x
  133. arrow.rotation.z = angle
  134. //console.log(angle)
  135. }
  136. get routeStart(){
  137. return this._routeStart && this._routeStart.clone()
  138. }
  139. set routeStart(pos){
  140. this._routeStart = pos && pos.clone()
  141. this.generateRoute()
  142. }
  143. get routeEnd(){
  144. return this._routeEnd && this._routeEnd.clone()
  145. }
  146. set routeEnd(pos){
  147. this._routeEnd = pos && pos.clone()
  148. this.generateRoute()
  149. }
  150. generateRoute(){
  151. if(!this.routeStart || !this.routeEnd)return
  152. this.clearRoute()
  153. //array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
  154. let create = ()=>{
  155. this.routeLenth = this.route.reduce((total, currentValue, currentIndex, arr)=>{
  156. if(currentIndex == 0)return 0
  157. return total + currentValue.distanceTo(arr[currentIndex-1]);
  158. },0)
  159. let count = Math.max(2,Math.round(this.routeLenth / arrowSpacing))//点数
  160. const curve = new THREE.CatmullRomCurve3( this.route );
  161. curve.curveType = 'catmullrom'
  162. this.curve = curve
  163. const scenePoints = curve.getSpacedPoints( count );//更平均
  164. //const scenePoints = curve.getPoints( count );
  165. scenePoints.splice(0,1);//去掉首尾
  166. scenePoints.pop()
  167. this.scenePoints = scenePoints
  168. this.updateMapArrows()
  169. this.displayRoute()
  170. }
  171. if(Potree.fileServer){
  172. let start = this.routeStart;
  173. let end = this.routeEnd;
  174. let startLonlat = viewer.transform.lonlatToLocal.inverse(start)
  175. let endLonlat = viewer.transform.lonlatToLocal.inverse(end)
  176. var query = {
  177. source_longitude: startLonlat.x,
  178. source_latitude: startLonlat.y,
  179. source_z: start.z,
  180. destination_longitude: endLonlat.x,
  181. destination_latitude: endLonlat.y,
  182. destination_z: end.z
  183. };
  184. let url = `/laser/route/${Potree.settings.number}/getRoute?`
  185. for(let i in query){
  186. url+= (i + '='+ query[i] +'&')
  187. }
  188. Potree.fileServer.get(url).then((data)=>{
  189. console.log(data)
  190. data.forEach(item=>{
  191. let pos = viewer.transform.lonlatToLocal.forward(item.location)
  192. pos = new THREE.Vector3().fromArray(pos)
  193. this.route.push(pos)
  194. })
  195. create()
  196. /*
  197. distance: 0.17581000000000116
  198. distance_to_previous: 0.17581000000000116
  199. id: 567
  200. instruction: {type: 'source_projection_to_navgraph'}
  201. latitude: 22.366605927999238
  202. location: (3) [113.5957510575092, 22.366605927999238, -1.12419]
  203. longitude: 113.5957510575092
  204. z: -1.12419
  205. */
  206. })
  207. }else{
  208. //创个直线
  209. /* const sliceDis = 1
  210. let dis = this.routeStart.distanceTo(this.routeEnd);
  211. let count = Math.max(2,Math.round(dis / sliceDis))//点数
  212. let realSlideDis = dis / (count-1);
  213. let dir = new THREE.Vector3().subVectors(this.routeEnd, this.routeStart).normalize().multiplyScalar(realSlideDis);
  214. this.route = [this.routeStart];
  215. for(let i=0;i<count-1;i++){
  216. let lastOne = this.route[i];
  217. this.route.push(new THREE.Vector3().addVectors(lastOne,dir))
  218. }
  219. this.route.splice(0,1) //route不用包含收尾 */
  220. this.route = [this.routeStart, this.routeEnd]
  221. create()
  222. }
  223. }
  224. updateMapArrows(){
  225. let count = Math.max(2,Math.round(this.routeLenth / viewer.mapViewer.camera.zoom *10/ arrowSpacing))//点数
  226. const mapPoints = this.curve.getSpacedPoints( count );
  227. mapPoints.splice(0,1);//去掉首尾
  228. mapPoints.pop()
  229. this.mapPoints = mapPoints
  230. }
  231. displayRoute(){
  232. this.sceneMeshGroup.visible = true
  233. this.mapMeshGroup.visible = true
  234. this.poleStart.position.copy(this.routeStart)
  235. this.poleEnd.position.copy(this.routeEnd)
  236. this.mapMarkStart.position.copy(this.routeStart).setZ(0)
  237. this.mapMarkEnd.position.copy(this.routeEnd).setZ(0)
  238. this.scenePoints.forEach(e=>this.addArrow(e))
  239. this.mapPoints.forEach(e=>this.addMapArrow(e))
  240. this.arrows.children.forEach((e,i)=>this.setArrowDir(this.arrows.children,i));
  241. this.mapArrows.children.forEach((e,i)=>this.setArrowDir(this.mapArrows.children,i));
  242. }
  243. clearRoute(){
  244. this.routeLenth = 0
  245. this.route = []
  246. this.scenePoints = []
  247. this.mapPoints = []
  248. let arrows = this.arrows.children.slice(0)
  249. let mapArrows = this.mapArrows.children.slice(0)
  250. arrows.forEach(e=>{
  251. this.arrows.remove(e)
  252. })
  253. mapArrows.forEach(e=>{
  254. this.mapArrows.remove(e)
  255. })
  256. }
  257. clear(){//退出
  258. this.sceneMeshGroup.visible = false
  259. this.mapMeshGroup.visible = false
  260. this.routeStart = null
  261. this.routeEnd = null
  262. this.clearRoute()
  263. }
  264. }