index.js 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012
  1. import mitt from 'mitt'
  2. import axios from 'axios' //{ axios } from '@/api'
  3. export const enter = (dom, isLocal) => {
  4. Potree.settings.isOfficial = true //标记为正式、非测试版本
  5. //Potree.fileServer = axios
  6. Potree.settings.libsUrl = './lib/'
  7. const tagLimitDis = 8;
  8. Potree.settings.showCompass = true
  9. Potree.settings.compassDom = dom.querySelector('#direction')
  10. let {THREE} = Potree.mergeEditStart(dom)
  11. let MergeEditor = viewer.modules.MergeEditor
  12. let sceneBus = mitt()
  13. viewer.addEventListener('camera_changed', e => {
  14. var camera = e.viewport.camera
  15. var pos = camera.position
  16. if (e.viewport.name == 'MainView') {
  17. sceneBus.emit('cameraChange', { x: pos.x, y: pos.y, z: pos.z, rotate: camera.rotation })
  18. }
  19. })
  20. viewer.addEventListener('webglError', e => {
  21. console.error('viewer webglError: ' + e)
  22. sceneBus.emit('webglError', { msg: e.msg })
  23. })
  24. window.THREE = THREE
  25. //isLocal = false
  26. let autoLoads = []
  27. let readyToAddModel
  28. let maxLoadingCount = /* isLocal ? 1 : */2; //正在加载模型的最大数目
  29. const units = { 1: 'metric', 2: 'imperial' }
  30. let getMeasureType = function (type, unit=1) {
  31. let info
  32. switch (type) {
  33. case 'free':
  34. info = { measureType: 'Distance' }
  35. break
  36. case 'area':
  37. info = { measureType: 'Area' }
  38. break
  39. case 'vertical':
  40. info = { measureType: 'Ver Distance' }
  41. break
  42. default:
  43. console.error('无此 measure type')
  44. }
  45. info.unit = units[unit]
  46. return info
  47. }
  48. let getMeasureFunction = function (measure, bus) {
  49. measure.addEventListener('highlight',(e)=>{
  50. //console.log('3d->2d highlight',e.state)
  51. bus.emit('highlight', e.state)
  52. })
  53. measure.addEventListener('marker_dropped',(e)=>{//拖拽结束后发送changeCallBack
  54. if (measure.parent) {
  55. //未被删除
  56. bus.emit('update',[
  57. measure.dataset_points.map(p=>p.clone()) ,
  58. measure.points_datasets
  59. ])
  60. }
  61. })
  62. return {
  63. /* quit: () => {
  64. Potree.Log('quit结束且删除: ' + measure.id, '#00c7b2')
  65. viewer.dispatchEvent({ type: 'cancel_insertions', remove: true, measure })
  66. }, //触发结束。退出测量模式,清除之前操作 */
  67. destroy: () => {
  68. viewer.dispatchEvent({ type: 'cancel_insertions', remove: true, measure })
  69. viewer.scene.removeMeasurement(measure)
  70. },
  71. /* getPoints: () => {
  72. return measure.points
  73. },
  74. getDatasetLocations: () => {
  75. return measure.dataset_points
  76. },
  77. getDatasets: () => {
  78. return measure.points_datasets
  79. },
  80. getDatasetId: () => {
  81. return measure.datasetId
  82. }, */
  83. getArea: () => {
  84. return measure.area //{value:area, string:..}
  85. },
  86. getDistance: () => {
  87. if (measure.points.length < 2) return 0
  88. var value = measure.points[0].distanceTo(measure.points[1])
  89. return {
  90. value, //米
  91. string: viewer.unitConvert.convert(value, 'distance', void 0, measure.unitSystem, 0.1, true),
  92. }
  93. },
  94. /* changeUnit: unit => {
  95. //公制|英制 , 1 | 2 单位
  96. measure.setUnitSystem(units[unit])
  97. },
  98. toDataURL: (width, height) => {
  99. //截图
  100. isScreenshoting = true
  101. var promise = viewer.startScreenshot({ type: 'measure', measurement: measure, hideMarkers: true }, width, height)
  102. promise.done(() => {
  103. isScreenshoting = false
  104. })
  105. return promise
  106. }, */
  107. //手动开启或关闭:
  108. show: () => {
  109. viewer.updateVisible(measure, 'inListByUser', true)
  110. },
  111. hide: () => {
  112. viewer.updateVisible(measure, 'inListByUser', false)
  113. },
  114. fly(){
  115. let result = viewer.focusOnObject(measure , 'measure', 1200 )
  116. return result.msg ? result.msg : result.promise
  117. //返回值 1 deferred 表示即将位移 2 'posNoChange' 表示已在最佳位置 3 'tooFar' 表示距离最佳位置太远
  118. },
  119. changeSelect(isHight){
  120. console.log('2d->3d isHight ',isHight)
  121. measure.setSelected(isHight, 'byList')
  122. },
  123. }
  124. }
  125. let sdk = {
  126. sceneBus,
  127. getPositionByScreen(pos2d, hopeModelId ){//通过屏幕坐标获取真实坐标 . hopeModelId: 如果指定了模型,优先返回hopeModelId上的intersect
  128. console.log('getPositionByScreen',hopeModelId)
  129. hopeModelId = null
  130. let worldPos, localPos, modelId, intersect
  131. let Handler = viewer.inputHandler
  132. let reGet = ()=>{//不使用当前鼠标所在位置的intersect,单独算
  133. pos2d.clientX = pos2d.x
  134. pos2d.clientY = pos2d.y
  135. pos2d.onlyGetIntersect = true
  136. pos2d.whichPointcloud = true
  137. if(hopeModelId != void 0){//隐藏其他的模型
  138. let models = MergeEditor.getAllObjects()
  139. models.forEach(model=>{
  140. viewer.updateVisible(model, 'forPick', model.dataset_id == hopeModelId)
  141. })
  142. }
  143. let intersect2 = Handler.onMouseMove(pos2d)
  144. if(hopeModelId != void 0){//恢复
  145. let models = MergeEditor.getAllObjects()
  146. models.forEach(model=>{
  147. viewer.updateVisible(model, 'forPick', true)
  148. })
  149. }
  150. if(intersect2 && intersect2.location){
  151. intersect = intersect2
  152. }
  153. }
  154. if (pos2d && pos2d.inDrag) {
  155. reGet()
  156. } else {
  157. intersect = Handler.intersect
  158. if(intersect){
  159. modelId = intersect.pointcloud ? intersect.pointcloud.dataset_id : intersect.object.dataset_id
  160. if(hopeModelId != void 0 && modelId != hopeModelId){
  161. reGet()
  162. }
  163. }
  164. }
  165. if (intersect && intersect.location) {
  166. modelId = intersect.pointcloud ? intersect.pointcloud.dataset_id : intersect.object.dataset_id
  167. /* if(hopeModelId != void 0 && modelId != hopeModelId){
  168. return null
  169. } */
  170. worldPos = intersect.location.clone()
  171. localPos = Potree.Utils.datasetPosTransform({ toDataset: true, datasetId:modelId, position:worldPos })
  172. } else return null
  173. return { worldPos, modelId, localPos }
  174. },
  175. getScreenByPosition(pos3d, modelId, canShelter/* , disToCameraLimit */){//通过模型局部坐标获取屏幕坐标
  176. let isLocal = modelId != void 0
  177. pos3d = new THREE.Vector3().copy(pos3d)
  178. let worldPos = isLocal ? Potree.Utils.datasetPosTransform({ fromDataset: true, datasetId: modelId, position:pos3d}) : pos3d
  179. if(!worldPos)return
  180. if(canShelter){
  181. if(viewer.inputHandler.ifBlockedByIntersect(worldPos, 0.1, true)) return {trueSide:false};
  182. }
  183. var viewport = viewer.mainViewport
  184. var camera = viewport.camera
  185. var dom = viewer.renderArea
  186. if(tagLimitDis != void 0){
  187. if(camera.position.distanceTo(worldPos) > tagLimitDis)return false
  188. }
  189. //console.log('getScreenByPoint ' + pos3d.toArray())
  190. return Potree.Utils.getPos2d(worldPos, camera, dom, viewport)
  191. },
  192. screenshot: (width, height) => {
  193. //截图
  194. var promise = viewer.startScreenshot({ type: 'default' }, width, height)
  195. promise.done(() => {
  196. })
  197. return promise
  198. },
  199. getPose() {//获取当前点位和朝向
  200. const camera = viewer.scene.getActiveCamera()
  201. const target = viewer.scene.view.getPivot().clone()
  202. const position = viewer.scene.view.position.clone()
  203. console.log('getPose',position, target)
  204. return { position, target }
  205. },
  206. comeTo(o = {}) {
  207. console.log('comeTo',o.position, o.target)
  208. //飞到某个点
  209. if(o.modelId){
  210. ['position','target'].forEach(e=>{
  211. if(o[e]){
  212. o[e] = Potree.Utils.datasetPosTransform({ fromDataset: true, datasetId: o.modelId, position:o[e]})
  213. }
  214. })
  215. }
  216. if(o.distance){
  217. let position = o.target || o.position
  218. return viewer.focusOnObject({ position}, 'tag', null,{distance:o.distance} ).promise
  219. }
  220. let deferred = $.Deferred()
  221. viewer.scene.view.setView($.extend({},o, {
  222. duration: o.dur,
  223. callback:()=>{
  224. o.callback && o.callback()
  225. deferred.resolve(true)
  226. }
  227. }))
  228. return deferred.promise()
  229. },
  230. /* getPose(o={}) {
  231. //获取相对于第一个数据集的初始画面。(当数据集校准后,如果初始画面设置在被修改的数据集上,且该数据集非初始数据集的话,还是会偏移的)
  232. var deferred = o.deferred || $.Deferred();
  233. console.log('getPose')
  234. if(viewer.mainViewport.view.isFlying()){
  235. let f = ()=>{
  236. this.getPose(o)
  237. viewer.mainViewport.view.removeEventListener('flyingDone', f)
  238. }
  239. viewer.mainViewport.view.addEventListener('flyingDone', f) //once
  240. o.deferred = deferred
  241. return deferred.promise()
  242. }
  243. var camera = viewer.scene.getActiveCamera()
  244. var rotation = camera.rotation
  245. var pos_In_dataset = Potree.Utils.datasetPosTransform({ toDataset: true, position: camera.position.clone(), datasetId: Potree.settings.originDatasetId })
  246. var rot_In_dataset = Potree.Utils.datasetRotTransform({ toDataset: true, rotation, getRotation: true, datasetId: Potree.settings.originDatasetId }) //拿第一个数据集
  247. var view = viewer.scene.view.clone()
  248. view.rotation = rot_In_dataset //获取yaw pitch
  249. var pose = {
  250. //displayMode: Potree.settings.displayMode,
  251. position: pos_In_dataset,
  252. yaw: view.yaw,
  253. pitch: view.pitch,
  254. displayMode : Potree.settings.displayMode,
  255. panoSid: viewer.images360.currentPano.sid
  256. }
  257. //return pose
  258. setTimeout(()=>{
  259. deferred.resolve(pose)
  260. console.log('getPose resolve',pose)
  261. },1)
  262. return deferred.promise()
  263. },
  264. setPose(o = {}, duration=0) {
  265. //设置相机位置和朝向
  266. var deferred = o.deferred || $.Deferred();
  267. console.warn('setPose 初始画面', o)
  268. var quaternion
  269. let view = viewer.scene.view.clone()
  270. if(viewer.mainViewport.view.isFlying()){
  271. let f = ()=>{
  272. this.setPose(o, duration)
  273. viewer.mainViewport.view.removeEventListener('flyingDone', f)
  274. }
  275. viewer.mainViewport.view.addEventListener('flyingDone', f) //once
  276. o.deferred = deferred
  277. return deferred.promise()
  278. }
  279. var getQuaternion = ()=>{
  280. view.pitch = o.pitch
  281. view.yaw = o.yaw
  282. quaternion = Potree.Utils.datasetRotTransform({ fromDataset: true, rotation: view.rotation, getQuaternion: true, datasetId: Potree.settings.originDatasetId }) //拿第一个数据集
  283. }
  284. viewer.images360.cancelFlyToPano()//防止旧的在之后继续执行
  285. let pano
  286. if(o.panoSid != void 0){//好像都不存这个
  287. pano = viewer.images360.panos.find(e=>e.sid == o.panoSid)
  288. if(pano == void 0)return deferred.reject('没有找到该panoSid').promise()
  289. getQuaternion()
  290. viewer.images360.flyToPano({pano, duration, quaternion},()=>{
  291. deferred.resolve()
  292. })
  293. }else{
  294. if(Potree.settings.displayMode == 'showPanos'){
  295. return deferred.reject('全景模式下不允许设置位置').promise()
  296. }
  297. let position = Potree.Utils.datasetPosTransform({ fromDataset: true, position: o.position, datasetId: Potree.settings.originDatasetId })
  298. //view.position.copy(position)
  299. getQuaternion()
  300. pano = viewer.images360.panos.find(e=>Potree.math.closeTo(e.position, position))
  301. if(pano){//如果原来在某pano上最好也使currentPano为此pano,否则isAtPano会返回false
  302. viewer.images360.flyToPano({pano, duration, quaternion},()=>{
  303. deferred.resolve()
  304. })
  305. }else{
  306. viewer.scene.view.setView({position,quaternion,duration, callback:()=>{
  307. //setTimeout(()=>{
  308. deferred.resolve()
  309. console.log('setPose resolve')
  310. //},1)
  311. } })
  312. viewer.mapViewer.moveTo(position, null, duration) //初始位置在地图居中
  313. }
  314. }
  315. return deferred.promise()
  316. },
  317. */
  318. enterSceneGuide(pathArr){//导览 (不需要修改参数)
  319. let editor = viewer.modules.CamAniEditor
  320. console.log('pathArr',pathArr)
  321. /* type SceneGuidec = {
  322. position: {x,y,z}
  323. target: {x,y,z}
  324. time: number
  325. speed: number //没用到
  326. }
  327. */
  328. console.log('enterSceneGuide',pathArr)
  329. let data = {
  330. duration: pathArr.slice(0,pathArr.length-1).reduce(function(total, currentValue ){return total+currentValue.time}, 0), //总时长(要去掉最后一个,因为已到终点,该点time无意义)
  331. points: pathArr,
  332. useDurSlice:true
  333. }
  334. let animation = editor.createAnimation(data)
  335. //注:最多只存在一条导览
  336. let bus = mitt()
  337. //播放完成
  338. animation.addEventListener('playDone', () => {
  339. bus.emit('playComplete')
  340. })
  341. //切换点
  342. animation.addEventListener('updateCurrentIndex', e => {
  343. bus.emit('changePoint', e.currentIndex + 1)
  344. })
  345. return {
  346. bus,
  347. play() {
  348. MergeEditor.selectModel(null)
  349. animation.play()
  350. },
  351. pause() {
  352. animation.pause()
  353. },
  354. clear() {
  355. //删除
  356. editor.removeAnimation(animation)
  357. },
  358. }
  359. },
  360. //[path1, paht2], { time, speed }
  361. calcPathInfo(paths, info){ //传入的time, speed仅有一个。返回完整的 time, speed
  362. //这一版的control似乎无法在某个位置上改变角度,位置和角度一般都是一起变的,所以先不增加单位更换功能。
  363. let pos1 = new THREE.Vector3().copy(paths[0].position)
  364. let pos2 = new THREE.Vector3().copy(paths[1].position)
  365. let dis = pos1.distanceTo(pos2)
  366. if(info.time != void 0){
  367. info.speed = dis / info.time
  368. }else{
  369. info.time = dis / info.speed
  370. }
  371. return info
  372. },
  373. //scaleRange: { min, max }, opacityRange: { min, max }, bottomRange: { min, max } })
  374. addModel(props){
  375. let bus = mitt()
  376. //console.log('addModel',props)
  377. props.isFirstLoad = isLocal && props.bottom == void 0 //离地高度去掉了这怎么办 // //在编辑时用户添加的
  378. if(props.opacity == void 0) props.opacity = 1
  379. if(props.type == 'obj') props.type = 'glb'
  380. props.scale /= 100
  381. if(!props.isFirstLoad){
  382. if(autoLoads.length == 0){ //首次加载
  383. setTimeout(()=>{
  384. let sizes = autoLoads.map(e=>e.size|| 0 )
  385. console.log('需要请求加载的模型大小为', sizes, '总大小', sizes.reduce(function(total, currentValue ){
  386. let current = parseFloat(currentValue)
  387. return total + ((typeof currentValue == 'number' || currentValue.includes('M')) ? current : current / 1024)
  388. }, 0))
  389. readyToAddModel = true //准备开始加载
  390. startLoad(autoLoads[0])
  391. },30)
  392. }
  393. autoLoads.push(props)
  394. readyToAddModel = false
  395. }else{
  396. readyToAddModel = true
  397. }
  398. let startLoad = (prop)=>{
  399. //if(autoLoads.filter(e=>e.loaded).length>1)return console.log('取消加载', prop), prop.onError()
  400. //return prop.onError()
  401. Potree.addModel(prop, prop.done , prop.progressFun, prop.onError)
  402. prop.loading = true
  403. console.log('-------开始加载 id:', prop.id, 'title:', prop.title, ', filename:',getName(prop.url), prop )
  404. }
  405. let spliceFromArr = (model,loaded)=>{
  406. //let autoLoads.find()
  407. props.loadFinish = true
  408. props.loading = false
  409. if(loaded){
  410. props.loaded = true
  411. props.model = model
  412. }else{
  413. props.error = true
  414. }
  415. let haventLoad = autoLoads.filter(e=>!e.loading && !e.loadFinish);
  416. if( haventLoad[0]){
  417. startLoad(haventLoad[0])
  418. //this.addModel(autoLoads[0])
  419. }else if(autoLoads.filter(e=>!e.loadFinish).length == 0 && autoLoads.filter(e=>e.loaded).length>0 && !props.isFirstLoad){//设置相机位置:当自动开始加载第一个模型时(其余的也跟着自动加载),等这批加载完后;
  420. let autoLoadsDone = autoLoads.filter(e=>e.loaded).map(e=>e.model)
  421. console.log('所有模型加载完毕')
  422. autoLoads.filter(e=>e.loaded && e.show).forEach(e=>e.model.visible = true)
  423. MergeEditor.focusOn(autoLoadsDone, 1000, true, true)
  424. autoLoads.length = 0
  425. }
  426. }
  427. let model
  428. let done = (model_)=>{
  429. model = model_
  430. if(!props.isFirstLoad){
  431. model.visible = false//先不显示,防止卡顿
  432. }
  433. props.opacity < 100 && result.changeOpacity(props.opacity)
  434. model.addEventListener('changeSelect',(e)=>{
  435. bus.emit('changeSelect',e.selected)
  436. })
  437. model.addEventListener('transformChanged',(e)=>{
  438. bus.emit('transformChanged', {
  439. position : model.position.clone(),
  440. scale: model.scale.x * 100,
  441. rotation: model.rotation.clone(),
  442. //bottom: model.btmHeight
  443. })
  444. })
  445. spliceFromArr(model,true)
  446. bus.emit('loadDone')
  447. //console.log('loadDone' )
  448. }
  449. let progressFun = (progress)=>{
  450. bus.emit('loadProgress',progress)
  451. }
  452. let onError = function ( xhr ) {
  453. bus.emit('loadError', xhr)
  454. console.log('loadError!!!!!!!!!', getName(props.url), props.size, xhr)
  455. spliceFromArr(model,false)
  456. }
  457. if(props.type == "glb"){////////////////////////////test
  458. if(props.url.includes('coffeemat')){
  459. props.url = '/lib/potree/resources/models/glb/coffeemat.glb'
  460. }
  461. //props.url += '5'
  462. //props.url = 'http://localhost:5173/api/profile/datav1/1537680519838306304/data/glb/cloud_glb_24.glb'
  463. }
  464. props.done = done; props.progressFun = progressFun; props.onError = onError
  465. if(readyToAddModel){
  466. if(autoLoads.filter(e=>e.loading).length<maxLoadingCount ){
  467. startLoad(props)
  468. }
  469. }
  470. let scaleMeasure
  471. let result = {
  472. bus,
  473. changeShow(show){
  474. props.show = show //for autoLoads show model
  475. if(model){
  476. viewer.updateVisible(model, 'changeShow', show)
  477. }
  478. },
  479. changeSelect(state){
  480. if(model){
  481. MergeEditor.selectModel(model, state, true, true)
  482. if(state && viewer.inputHandler.selection[0]){
  483. MergeEditor.transformControls.attach(model) //viewer.transformObject(model); //交换
  484. }
  485. //console.log('changeSelect', props.id, state)
  486. }
  487. },
  488. changeScale(s){
  489. if(model){
  490. s /= 100
  491. model.scale.set(s,s,s)
  492. model.isPointcloud && model.changePointSize(Potree.config.material.realPointSize * s)
  493. model.dispatchEvent("scale_changed")
  494. }
  495. },
  496. changeOpacity(opacity){
  497. if(opacity == void 0)opacity = 100
  498. opacity/=100
  499. let setOp = (mesh)=>{//见笔记:透明物体的材质设置
  500. if(model.isPointcloud){
  501. mesh.changePointOpacity(opacity)
  502. }else{
  503. mesh.material.opacity = opacity
  504. }
  505. if(opacity<1){
  506. mesh.material.transparent = true
  507. mesh.renderOrder = Potree.config.renderOrders.model+1
  508. mesh.material.depthWrite = false
  509. }else{
  510. mesh.material.transparent = false
  511. mesh.renderOrder = Potree.config.renderOrders.model
  512. mesh.material.depthWrite = true
  513. }
  514. }
  515. if(model){
  516. if(model.isPointcloud){
  517. setOp(model)
  518. }else{
  519. model.traverse(e=>e.material && setOp(e, opacity))
  520. }
  521. model.opacity = opacity//记录在最外层
  522. }
  523. },
  524. changeBottom(z){
  525. /* model && MergeEditor.setModelBtmHeight(model,z)
  526. model.dispatchEvent('transformChanged') //改了position */
  527. },
  528. changePosition(pos){//校准取消时执行
  529. //if(MergeEditor.selected == model){
  530. //console.log('pos',pos.x, pos.y, pos.z)
  531. //}
  532. model && model.position.copy(pos)
  533. model.dispatchEvent({type:'position_changed'})
  534. },
  535. changeRotation(rot){//校准取消时执行
  536. //if(MergeEditor.selected == model){
  537. //console.log('rot', rot.x, rot.y, rot.z)
  538. //}
  539. model && model.rotation.setFromVector3(rot)
  540. model.dispatchEvent({type:'rotation_changed'})
  541. },
  542. enterRotateMode(){
  543. if(model){
  544. if(MergeEditor.split){//分屏校准
  545. MergeEditor.setTransformState('rotate')
  546. MergeEditor.transformControls2.attach(model)
  547. MergeEditor.transformControls2.mode = 'rotate'
  548. }
  549. MergeEditor.transformControls.attach(model)
  550. MergeEditor.transformControls.mode = 'rotate'
  551. }
  552. },
  553. enterMoveMode(){
  554. if(model){
  555. if(MergeEditor.split){//分屏校准
  556. MergeEditor.setTransformState('translate')
  557. MergeEditor.transformControls2.attach(model)
  558. MergeEditor.transformControls2.mode = 'translate'
  559. }
  560. MergeEditor.transformControls.attach(model)
  561. MergeEditor.transformControls.mode = 'translate'
  562. }
  563. },
  564. leaveTransform(){
  565. if(MergeEditor.split){//分屏校准
  566. MergeEditor.setTransformState(null)
  567. }else{
  568. MergeEditor.transformControls.detach()
  569. MergeEditor.transformControls2.detach()
  570. }
  571. },
  572. enterAlignment(){//开始校准
  573. MergeEditor.enterSplit()
  574. result.leaveTransform()
  575. //console.log('enterAlignment',model.position, model.rotation)
  576. let bus = new mitt()
  577. /* MergeEditor.transformControls.attach(model)
  578. MergeEditor.transformControls.mode = 'translate' */
  579. return {
  580. bus
  581. }
  582. },
  583. leaveAlignment(){
  584. //console.log('leaveAlignment',model.position, model.rotation)
  585. MergeEditor.leaveSplit()
  586. MergeEditor.transformControls.detach()
  587. },
  588. enterScaleSet(){//设置比例
  589. let bus = new mitt()
  590. let length , measureBuilded ;
  591. viewer.outlinePass.selectedObjects = []
  592. if(!Potree.Utils.isInsideFrustum(model.boundingBox.clone().applyMatrix4(model.matrixWorld), viewer.scene.getActiveCamera())){
  593. MergeEditor.focusOn(model, 600 )
  594. }
  595. MergeEditor.getAllObjects().forEach(m=>{//隐藏其他的模型
  596. if(m!=model) viewer.updateVisible(m, 'enterScaleSet', false)
  597. })
  598. let setScale = ()=>{
  599. if(length == void 0 || !measureBuilded )return
  600. let vec = new THREE.Vector3().subVectors(viewer.mainViewport.camera.position, scaleMeasure.points[1])
  601. let s = length / (scaleMeasure.points[0].distanceTo(scaleMeasure.points[1]))
  602. result.changeScale(model.scale.x * s*100)
  603. /* setTimeout(()=>{
  604. viewer.focusOnObject(scaleMeasure , 'measure', 500)
  605. },1) */
  606. let newCamPos = new THREE.Vector3().addVectors(scaleMeasure.points[1], vec.multiplyScalar(s))
  607. viewer.scene.view.setView({position:newCamPos, target:scaleMeasure.getCenter(), duration:0, callback:()=>{
  608. //更改target到measure中心的好处就是可以让相机绕measure中心转,坏处是每次更改都会变一下画面
  609. }
  610. })
  611. }
  612. return {
  613. bus,
  614. setLength(v){
  615. if(!v)return
  616. length = v
  617. setScale()
  618. },
  619. startMeasure(){
  620. if(scaleMeasure){
  621. viewer.dispatchEvent({ type: 'cancel_insertions', remove: true, measure:scaleMeasure })
  622. viewer.scene.removeMeasurement(scaleMeasure)
  623. }
  624. measureBuilded = false
  625. scaleMeasure = viewer.measuringTool.startInsertion(
  626. {measureType: "Distance", unit: "metric"},
  627. () => {
  628. //done:
  629. //bus.emit('end' ) //完成
  630. measureBuilded = true
  631. setScale()
  632. },
  633. () => {
  634. //cancel
  635. //bus.emit('quit') //删除
  636. }
  637. )
  638. scaleMeasure.addEventListener('marker_dropped',(e)=>{//拖拽结束后发送changeCallBack
  639. if (scaleMeasure.parent) {
  640. //未被删除
  641. measureBuilded && setScale()
  642. }
  643. })
  644. }
  645. }
  646. },
  647. leaveScaleSet(){
  648. if(scaleMeasure){
  649. viewer.dispatchEvent({ type: 'cancel_insertions', remove: true, measure:scaleMeasure })
  650. viewer.scene.removeMeasurement(scaleMeasure)
  651. scaleMeasure = null
  652. }
  653. viewer.outlinePass.selectedObjects = [model];
  654. MergeEditor.getAllObjects().forEach(m=>{//恢复其他的模型
  655. if(m!=model) viewer.updateVisible(m, 'enterScaleSet', true)
  656. })
  657. },
  658. destroy(){
  659. model && MergeEditor.removeModel(model)
  660. }
  661. }
  662. return result
  663. },
  664. //测量线的点都附着于各个模型,当模型变化时,点跟着变化。
  665. // 新的测量创建方法,传入type 返回新测量对象
  666. startMeasure(type){
  667. // 寻创建的测量对象有上面绘画测量对象的所有方法
  668. const bus = mitt()
  669. let info = getMeasureType(type)
  670. let measure = viewer.measuringTool.startInsertion(
  671. info,
  672. () => {
  673. //done:
  674. /* bus.emit('submit', {
  675. dataset_points: measure.dataset_points.map(p=>p.clone()) ,
  676. points_datasets: measure.points_datasets
  677. } ) //完成 */
  678. bus.emit('submit')
  679. bus.emit('update',[
  680. measure.dataset_points.map(p=>p.clone()) ,
  681. measure.points_datasets
  682. ])
  683. },
  684. () => {
  685. //cancel
  686. bus.emit('cancel'/* , ret */) //删除
  687. }
  688. )
  689. Potree.Log('startMeasure: ' + measure.id, '#00c7b2')
  690. /* let cancel = ()=>{
  691. Potree.Log('clear删除: ' + measure.id, '#00c7b2')
  692. viewer.dispatchEvent({ type: 'cancel_insertions', remove: true, measure })
  693. viewer.scene.removeMeasurement(measure)
  694. } */
  695. let result = {
  696. bus,
  697. ...getMeasureFunction(measure, bus),
  698. }
  699. /* StartMeasure = Measure & {
  700. // 多了cancel 取消测量的事件,没有参数
  701. // 多了invalidPoint 当用户测量了无效点时的事件,抛出无效原因
  702. bus: Emitter<{ cancel: void; invalidPoint: string }>
  703. } */
  704. return result
  705. },
  706. // 绘画测量线(非新增使用)
  707. // type = 'free' (自由) || 'vertical' (垂直) || 'area' (面积)
  708. // positions 点数组 构成如下 [{ point: {x,y,z}, modelId: 1 }]
  709. drawMeasure(type, dataset_points, points_datasets){
  710. // 返回测量对象有如下
  711. const bus = mitt()
  712. let info = getMeasureType(type /* , unit */)
  713. //info.points = positions
  714. info.dataset_points = dataset_points
  715. info.points_datasets = points_datasets
  716. //info.sid = sid
  717. info.bus = bus
  718. let measure = viewer.measuringTool.createMeasureFromData(info)
  719. if(!measure)return {bus}
  720. Potree.Log('drawMeasure由数据新建: ' + measure.id, '#00c7b2')
  721. let result = {
  722. bus,
  723. setPositions(dataset_points, points_datasets){//用于恢复measure的点,不会修改点的个数
  724. measure.dataset_points = dataset_points.map(e=>{
  725. return e && new THREE.Vector3().copy(e)
  726. })
  727. measure.points_datasets = points_datasets
  728. measure.points = measure.dataset_points.map((p,i)=>{
  729. return Potree.Utils.datasetPosTransform({fromDataset:true, datasetId:measure.points_datasets[i], position: p})
  730. })
  731. measure.getPoint2dInfo(measure.points)
  732. measure.update({ifUpdateMarkers:true})
  733. measure.setSelected(false)//隐藏edgelabel
  734. },
  735. ...getMeasureFunction(measure, bus),
  736. }
  737. return result
  738. },
  739. addTag(info){//加热点
  740. let bus = mitt()
  741. let tag
  742. let done = ()=>{
  743. bus.emit('added')
  744. bus.emit('update', {position: tag.position.clone(), normal:o.normal.clone(), modelId:tag.root.dataset_id } )
  745. tag = tag_
  746. tag.spot.addEventListener('mouseover',()=>{
  747. bus.emit('hoverState',true)
  748. })
  749. tag.spot.addEventListener('mouseout',()=>{
  750. bus.emit('hoverState',false)
  751. })
  752. }
  753. if(!info.position){
  754. viewer.tagTool.startInsertion().done(tag_=>{
  755. done()
  756. })
  757. }else{
  758. info.root = MergeEditor.getAllObjects().find(e=>e.dataset_id == info.modelId)
  759. if(!info.root){
  760. console.error('没有找到该modelId')
  761. }
  762. tag = viewer.tagTool.createTagFromData(info)
  763. done()
  764. }
  765. let result = {
  766. bus,
  767. getScreenPos(){
  768. let pos3d = new THREE.Vector3().setFromMatrixPosition( tag.matrixWorld )
  769. return sdk.getScreenByPosition(pos3d)
  770. },
  771. show(){
  772. viewer.updateVisible(tag, 'byList', true)
  773. },
  774. hide(){
  775. viewer.updateVisible(tag, 'byList', false)
  776. },
  777. destroy(){
  778. if(tag){
  779. tag.dispose()
  780. }
  781. viewer.dispatchEvent({ type: 'cancel_insertions', remove: true })
  782. },
  783. changeTitle(title){
  784. tag.changeTitle(title)
  785. }
  786. }
  787. return result
  788. }
  789. }
  790. function getName(url){
  791. return url.split('/').pop()
  792. }
  793. console.log('版本: 2022.8.29-1')
  794. return sdk
  795. }
  796. export default enter