Alignment.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. import * as THREE from "../../../libs/three.js/build/three.module.js";
  2. import SplitScreen from "../../utils/SplitScreen"
  3. import math from "../../utils/math"
  4. import {EventDispatcher} from "../../EventDispatcher.js";
  5. var Alignment = {
  6. SplitScreen,
  7. handleState:null, //操作状态 'translate'|'rotate'
  8. bus: new THREE.EventDispatcher(),
  9. init:function(){
  10. let rotateInfo
  11. viewer.fpControls.addEventListener("transformPointcloud",(e)=>{
  12. if(e.pointcloud.dataset_id == Potree.settings.originDatasetId){//禁止手动移动初始数据集
  13. return this.bus.dispatchEvent('forbitMoveOriginDataset')
  14. }
  15. if(this.handleState == 'translate'){
  16. Alignment.translate(e.pointcloud,e.moveVec)
  17. }else if(this.handleState == 'rotate'){
  18. let center = e.pointcloud.translateUser //移动到的位置就是中心
  19. if(!rotateInfo){
  20. rotateInfo = {
  21. orientationUser : e.pointcloud.orientationUser,
  22. vecStart : new THREE.Vector3().subVectors(e.intersectStart, center).setZ(0),
  23. pointcloud: e.pointcloud
  24. }
  25. }else{
  26. let vec = new THREE.Vector3().subVectors(e.intersectPoint, center).setZ(0)
  27. let angle = math.getAngle(rotateInfo.vecStart,vec,'z')
  28. let diffAngle = rotateInfo.orientationUser + angle - rotateInfo.pointcloud.orientationUser
  29. Alignment.rotate(rotateInfo.pointcloud, null, diffAngle)
  30. }
  31. }
  32. })
  33. viewer.fpControls.addEventListener("end",(e)=>{
  34. rotateInfo = null
  35. })
  36. // cursor:
  37. let updateCursor = (e)=>{
  38. if(e.drag)return //仅在鼠标不按下时更新:
  39. let handleState = Alignment.handleState
  40. if(e.hoverViewport.alignment && handleState && e.hoverViewport.alignment[handleState]){
  41. if(handleState == 'translate'){
  42. if( e.intersectPoint && e.intersectPoint.location ){
  43. viewer.dispatchEvent({
  44. type : "CursorChange", action : "add", name:"movePointcloud"
  45. })
  46. }else{
  47. viewer.dispatchEvent({
  48. type : "CursorChange", action : "remove", name:"movePointcloud"
  49. })
  50. }
  51. }else if(handleState == 'rotate'){
  52. if( e.intersectPoint && e.intersectPoint.location ){
  53. viewer.dispatchEvent({
  54. type : "CursorChange", action : "add", name:"rotatePointcloud"
  55. })
  56. }else{
  57. viewer.dispatchEvent({
  58. type : "CursorChange", action : "remove", name:"rotatePointcloud"
  59. })
  60. }
  61. }
  62. }else{
  63. //清空:
  64. viewer.dispatchEvent({
  65. type : "CursorChange", action : "remove", name:"movePointcloud"
  66. })
  67. viewer.dispatchEvent({
  68. type : "CursorChange", action : "remove", name:"rotatePointcloud"
  69. })
  70. }
  71. }
  72. viewer.addEventListener('global_mousemove',updateCursor)
  73. viewer.addEventListener('global_drop',updateCursor)//拖拽结束
  74. },
  75. setMatrix : function(pointcloud){
  76. var vec1 = pointcloud.position //position为数据集内部的偏移,在navvis中对应的是dataset.pointCloudSceneNode的children[0].position
  77. var vec2 = pointcloud.translateUser
  78. var angle = pointcloud.orientationUser
  79. var pos1Matrix = new THREE.Matrix4().setPosition(vec1);//先移动到点云本身应该在的初始位置(在4dkk里和其他应用中都是在这个位置的,也能和漫游点对应上)
  80. var rotMatrix = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0,0,1), angle)//再旋转
  81. var pos2Matrix = new THREE.Matrix4().setPosition(vec2);//最后是平移
  82. var matrix = new THREE.Matrix4().multiplyMatrices(pos2Matrix, rotMatrix);
  83. pointcloud.transformMatrix = matrix.clone();//为该数据集的变化矩阵。 对应navvis的m2w_
  84. pointcloud.transformInvMatrix.copy(matrix).invert()
  85. pointcloud.rotateMatrix = rotMatrix
  86. pointcloud.rotateInvMatrix.copy(rotMatrix).invert()
  87. pointcloud.panos.forEach(e=>e.transformByPointcloud())
  88. matrix = new THREE.Matrix4().multiplyMatrices(matrix, pos1Matrix);
  89. pointcloud.matrix = matrix;
  90. //pointcloud.matrixWorldNeedsUpdate = true //更新matrixWorld (非计算,直接赋值)
  91. pointcloud.updateMatrixWorld(true)
  92. if(this.editing){
  93. Alignment.changeCallBack && Alignment.changeCallBack();
  94. }
  95. if(pointcloud.spriteNodeRoot){
  96. pointcloud.spriteNodeRoot.matrixWorld.copy(pointcloud.matrixWorld)//.multiplyMatrices(pointcloud.matrixWorld, pointcloud.matrixWorld);
  97. }
  98. //viewer.updateModelBound();
  99. pointcloud.updateBound()
  100. },
  101. rotate:function(pointcloud, deg, angle){//假设点云位移position后0,0,0就是它的中心了(根据navvis观察这样做是绕同一个点旋转的)
  102. var angle = angle != void 0 ? angle : THREE.Math.degToRad(deg) //正逆负顺
  103. pointcloud.orientationUser += angle
  104. Alignment.setMatrix(pointcloud)
  105. },
  106. translate:function(pointcloud, vec){
  107. pointcloud.translateUser.add(vec)
  108. Alignment.setMatrix(pointcloud)
  109. },
  110. saveTemp:function(){//记录最近一次保存后的状态,便于恢复
  111. this.originData = viewer.scene.pointclouds.map(e=>{
  112. return {
  113. id : e.dataset_id,
  114. orientationUser : e.orientationUser,
  115. translateUser : e.translateUser.clone(),
  116. }
  117. } )
  118. },
  119. enter:function(){
  120. this.saveTemp()
  121. SplitScreen.splitScreen4Views({alignment:true})
  122. viewer.images360.panos.forEach(pano=>{
  123. viewer.updateVisible(pano.mapMarker, 'split4Screens', false)
  124. })
  125. viewer.viewports.find(e=>e.name == 'mapViewport').alignment = {rotate:true,translate:true};
  126. viewer.viewports.find(e=>e.name == 'Right').alignment = {translate:true};
  127. viewer.viewports.find(e=>e.name == 'Back').alignment = {translate:true};
  128. this.editing = true
  129. viewer.updateFpVisiDatasets()
  130. },
  131. leave:function(){
  132. this.switchHandle(null)
  133. this.originData.forEach(e=>{//恢复
  134. var pointcloud = viewer.scene.pointclouds.find(p=>p.dataset_id == e.id)
  135. this.translate(pointcloud, new THREE.Vector3().subVectors(e.translateUser , pointcloud.translateUser))
  136. this.rotate(pointcloud, null, e.orientationUser - pointcloud.orientationUser)
  137. })
  138. SplitScreen.recoverFrom4Views()
  139. viewer.images360.panos.forEach(pano=>{
  140. viewer.updateVisible(pano.mapMarker, 'split4Screens', true)
  141. })
  142. this.editing = false
  143. viewer.updateFpVisiDatasets()
  144. }
  145. ,
  146. switchHandle:function(state){
  147. this.handleState = state
  148. //清空:
  149. viewer.dispatchEvent({
  150. type : "CursorChange", action : "remove", name:"movePointcloud"
  151. })
  152. viewer.dispatchEvent({
  153. type : "CursorChange", action : "remove", name:"rotatePointcloud"
  154. })
  155. },
  156. save: function(){//保存所有数据集的位置和旋转
  157. let callback = ()=>{//保存成功后
  158. this.saveTemp();
  159. //需要修改 测量线的position。漫游点已经实时修改了
  160. viewer.scene.measurements.forEach(e=>e.transformByPointcloud())
  161. viewer.images360.updateCube(viewer.bound)
  162. }
  163. var data = viewer.scene.pointclouds.map(e=>{
  164. let pos = viewer.transform.lonlatToLocal.inverse(e.translateUser.clone())
  165. return {
  166. id: e.dataset_id,
  167. orientation : e.orientationUser,
  168. location:[pos.x, pos.y, pos.z],
  169. //transformMatrix: e.transformMatrix.elements,
  170. }
  171. })
  172. //data = JSON.stringify(data)
  173. //test: 退出后保留结果
  174. if(!Potree.settings.isOfficial){
  175. callback()
  176. }
  177. return {data, callback}
  178. }
  179. }
  180. /*
  181. 关于控制点:
  182. 两个控制点只能打在同一个数据集上。传输这两个点的4dkk中的本地坐标和经纬度,后台算出该数据集的旋转平移,
  183. 然后其他数据集绕该数据集旋转,并保持相对位置不变。
  184. */
  185. export {Alignment}