index.js 38 KB

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