enter.js 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384
  1. import parameter from "./parameter";
  2. import mitt from "mitt";
  3. import {
  4. CoordType
  5. }
  6. from "../../types";
  7. import {
  8. Loading
  9. }
  10. from "@kankan/components/index";
  11. import revision from "./REVISION";
  12. import {
  13. ui18n
  14. }
  15. from "@/lang";
  16. import libTransform from "coordtransform";
  17. //交通版laser 主要适用设备:MatePad Pro 11英寸
  18. const pointMeasureColor = "#3290ff"
  19. const CloneJson = function (data) {
  20. var str = JSON.stringify(data);
  21. return JSON.parse(str);
  22. };
  23. var enter = ({
  24. dom,
  25. mapDom,
  26. number,
  27. //datasetId, //初始数据集
  28. webSite, //废弃,改为用dataset.webBin
  29. isLocal = false,
  30. basePath,
  31. isDebug = false,
  32. mapCompany, // 地图版本 'default' | 'google' default就跟现在一样
  33. axios,
  34. version, //'V3''V4' 废弃,改为从getDataset获取
  35. staticPrefix,
  36. cropArgs,
  37. getFileUrl,
  38. }) => {
  39. let isScreenshoting = false;
  40. let lastSiteModelData;
  41. let page; //所在页面
  42. const sceneBus = mitt();
  43. Potree.settings.isOfficial = true; //标记为正式、非测试版本
  44. Potree.settings.isDebug = isDebug;
  45. //Potree.settings.originDatasetId = datasetId;
  46. /*if (isLocal) {
  47. //本地配置
  48. Potree.settings.isLocal = isLocal;
  49. for (let i in Potree.settings.urls) {
  50. Potree.settings.urls[i] = basePath; //全部替换
  51. }
  52. }
  53. webSite && (Potree.settings.webSite = webSite);
  54. //axios && (Potree.fileServer = axios); //暂时不用,比如vision那里
  55. if (staticPrefix) {
  56. // "/dev/SS-t-4pMXagRDjk"
  57. Potree.settings.isLocal = true;
  58. Potree.settings.urls.prefix1 = Potree.settings.urls.prefix3 = staticPrefix;
  59. Potree.settings.webSite = "wwwroot";
  60. } */
  61. Potree.getFileUrl = getFileUrl //转化为另一种得到url的方法
  62. Potree.start(dom, mapDom, number);
  63. parameter.dom = dom;
  64. parameter.number = number;
  65. parameter.viewer = viewer;
  66. parameter.sceneBus = sceneBus;
  67. //Potree.settings.rotAroundPoint = false; //试验
  68. viewer.fixPoints = []//固定点
  69. sceneBus.on("visible", (v) => {
  70. viewer.visible = v;
  71. /* if(v){
  72. viewer.dispatchEvent('content_changed') //避免白屏
  73. } */
  74. //console.log('sceneBus visible', v)
  75. });
  76. viewer.addEventListener("allLoaded", (e) => {
  77. //全部加载完,除了地图
  78. console.log('emit allLoad')
  79. sceneBus.emit("allLoaded");
  80. });
  81. viewer.addEventListener("webglError", (e) => {
  82. console.error("viewer webglError: " + e);
  83. sceneBus.emit("webglError", {
  84. msg: e.msg
  85. });
  86. });
  87. viewer.addEventListener("viewChanged", (e) => {
  88. sceneBus.emit("viewChange", e.name)
  89. });
  90. let cameraChange = (e) => {
  91. var camera = e.viewport.camera;
  92. var pos = camera.position;
  93. if (e.viewport.name == "MainView") {
  94. let meterPerPixel = viewer.mainViewport.camera.type == 'OrthographicCamera' ? 1 / viewer.mainViewport.camera.zoom : null//原本我设定的每像素代表1米, 然后再除以zoom
  95. //console.log('meterPerPixel', meterPerPixel)
  96. sceneBus.emit("posChange", {
  97. x: pos.x,
  98. y: pos.y,
  99. z: pos.z,
  100. rotate: camera.rotation,
  101. meterPerPixel,
  102. });
  103. }
  104. viewer.fixPoints.forEach(point=>{
  105. point.pos2d = Potree.Utils.getPos2d(point, e.viewport, viewer.renderArea )
  106. })
  107. };
  108. viewer.addEventListener("camera_changed", cameraChange);
  109. viewer.addEventListener("shelterComputed", () => {
  110. cameraChange({
  111. viewport: viewer.mainViewport
  112. });
  113. });
  114. {
  115. Potree.loadingByTex = false;
  116. let delayShow = 400;
  117. let timer;
  118. viewer.addEventListener("loading", (e) => {
  119. //加载的等待页面
  120. if (e.show) {
  121. if (!isScreenshoting) {
  122. //截图时不显示
  123. Potree.loadingByTex = true;
  124. timer && clearTimeout(timer);
  125. timer = setTimeout(() => {
  126. if (Potree.loadingByTex) {
  127. Loading.show();
  128. }
  129. }, delayShow);
  130. }
  131. } else {
  132. Potree.loadingByTex = false;
  133. timer && clearTimeout(timer);
  134. Loading.hide();
  135. }
  136. });
  137. }
  138. let info;
  139. const units = {
  140. 1: "metric",
  141. 2: "imperial"
  142. };
  143. let getMeasureType = function (type, unit) {
  144. switch (type) {
  145. case 'BASE_LINE':
  146. info = {
  147. measureType: "Hor LINE with Text", //带有文字label的线
  148. labelText : '基准线',
  149. isBaseLine : true, //暂时只有基准线是这种measureType
  150. };
  151. break;
  152. case "LINE":
  153. info = {
  154. measureType: "Distance"
  155. };
  156. break;
  157. case "SERIES":
  158. info = {
  159. measureType: "MulDistance"
  160. };
  161. break;
  162. case "AREA":
  163. info = {
  164. measureType: "Area"
  165. };
  166. break;
  167. case "L_LINE":
  168. info = {
  169. measureType: "Hor Distance"
  170. };
  171. break;
  172. case "L_SERIES":
  173. info = {
  174. measureType: "Hor MulDistance"
  175. };
  176. break;
  177. case "L_AREA":
  178. info = {
  179. measureType: "Hor Area"
  180. };
  181. break;
  182. case "L_RECTANGLE":
  183. info = {
  184. measureType: "Hor Rect Area"
  185. };
  186. break;
  187. case "V_LINE":
  188. info = {
  189. measureType: "Ver Distance"
  190. };
  191. break;
  192. case "V_SERIES":
  193. info = {
  194. measureType: "Ver MulDistance"
  195. };
  196. break;
  197. case "V_AREA":
  198. info = {
  199. measureType: "Ver Area"
  200. };
  201. break;
  202. case "V_RECTANGLE":
  203. info = {
  204. measureType: "Ver Rect Area"
  205. };
  206. break;
  207. default:
  208. console.error("无此 measure type", type);
  209. }
  210. info.unit = units[unit];
  211. return info;
  212. };
  213. let getMeasureFunction = function (measure, bus, isShape) {
  214. measure.addEventListener("marker_dropped", (e) => {
  215. //拖拽结束后发送changeCallBack
  216. if (measure.parent) {
  217. //未被删除
  218. isShape ? bus.emit("graphChange", {path:measure.points, center:measure.getCenter()}) : bus.emit("update");
  219. if(measure.isBaseLine){
  220. viewer.dispatchEvent('baseLineChanged')
  221. }
  222. }
  223. });
  224. /* measure.addEventListener("highlight", (e) => {
  225. bus.emit("highlight", e.state);
  226. }); */
  227. measure.addEventListener("selected", (e) => {
  228. bus.emit(isShape ? "selectGraph":"selected", e.state)
  229. isShape && measure.mainPoint.ret.selected(e.state, true)
  230. });
  231. return {
  232. quit: () => {
  233. Potree.Log("quit结束且删除: " + measure.id, {
  234. font: {
  235. color: "#00c7b2"
  236. },
  237. });
  238. viewer.dispatchEvent({
  239. type: "cancel_insertions",
  240. remove: true,
  241. measure,
  242. });
  243. }, //触发结束。退出测量模式,清除之前操作
  244. clear: () => {
  245. //删除
  246. Potree.Log("clear删除: " + measure.id, {
  247. font: {
  248. color: "#00c7b2"
  249. }
  250. });
  251. viewer.dispatchEvent({
  252. type: "cancel_insertions",
  253. remove: true,
  254. measure,
  255. });
  256. viewer.scene.removeMeasurement(measure);
  257. if(measure.isBaseLine){
  258. viewer.dispatchEvent('baseLineRemoved')
  259. }
  260. },
  261. end: () => {
  262. //完成 相当于右键
  263. measure.dispatchEvent({
  264. type: "finish",
  265. measure
  266. });
  267. },
  268. getPoints: () => {
  269. return measure.points;
  270. },
  271. getDatasetLocations: () => {
  272. return measure.dataset_points;
  273. },
  274. getDatasets: () => {
  275. return [1]//measure.points_datasets;
  276. },
  277. getDatasetId: () => {
  278. return 1//measure.datasetId;
  279. },
  280. getArea: () => {
  281. return measure.area; //{value:area, string:..}
  282. },
  283. getDistance: () => {
  284. if (measure.points.length < 2)
  285. return null;
  286. var value = measure.getTotalDistance(); //measure.points[0].distanceTo(measure.points[1])
  287. return {
  288. value, //米
  289. string: viewer.unitConvert.convert(
  290. value,
  291. "distance",
  292. void 0,
  293. measure.unitSystem,
  294. 0.1,
  295. true),
  296. };
  297. },
  298. changeUnit: (unit) => {
  299. //公制|英制 , 1 | 2 单位
  300. measure.setUnitSystem(units[unit]);
  301. },
  302. toDataURL: (width, height) => {
  303. //截图
  304. isScreenshoting = true;
  305. var {
  306. getImagePromise,
  307. finishPromise
  308. } = viewer.startScreenshot({
  309. type: "measure",
  310. measurement: measure,
  311. hideMarkers: true,
  312. ifGetPose: true,
  313. },
  314. width,
  315. height);
  316. finishPromise.done(() => {
  317. isScreenshoting = false;
  318. });
  319. return finishPromise; //getImagePromise.done时是可以getPose的, finishPromise.done时才开始截下一张图
  320. },
  321. //手动开启或关闭:
  322. show: () => {
  323. Potree.Utils.updateVisible(measure, "forceByUser", true);
  324. viewer.dispatchEvent('content_changed')
  325. },
  326. hide: () => {
  327. Potree.Utils.updateVisible(measure, "forceByUser", false);
  328. viewer.dispatchEvent('content_changed')
  329. },
  330. /* highlight: (isHight) => {
  331. measure.setSelected(isHight, "byList");
  332. }, */
  333. selected: (state, dontMoveCamera ) => {
  334. //measure.setSelected(state, "byList");
  335. if(state){
  336. measure.focus({dontMoveCamera})
  337. }else{
  338. measure.dispatchEvent('cancelSelect')
  339. }
  340. },
  341. };
  342. };
  343. let getMeasurePointsInfo = (fixPoint, onlyMoveBasePoint)=>{
  344. let baseLine = viewer.scene.measurements.find(e=>e.isBaseLine && e.points.length == 2)
  345. if(!baseLine){
  346. return console.error('创建失败,因基准线不存在')
  347. }
  348. if(!fixPoint.basePoint){
  349. return //console.log('no basePoint')
  350. }
  351. let fixPoint2d = new THREE.Vector2().copy(fixPoint)
  352. let baselineP12d = new THREE.Vector2().copy(baseLine.points[0])
  353. let baselineP22d = new THREE.Vector2().copy(baseLine.points[1])
  354. let foot1_2d = Potree.math.getFootPoint(fixPoint2d, baselineP12d, baselineP22d)
  355. let minZ = Math.min(fixPoint.basePoint.z, baseLine.points[0].z, fixPoint.z)
  356. let maxZ = Math.max(fixPoint.basePoint.z, baseLine.points[0].z, fixPoint.z)
  357. let foot1_P1 = new THREE.Vector3(foot1_2d.x, foot1_2d.y, fixPoint.z)
  358. let foot1_P2 = new THREE.Vector3(foot1_2d.x, foot1_2d.y, minZ)
  359. let foot1_P3 = new THREE.Vector3(foot1_2d.x, foot1_2d.y, maxZ)
  360. let info = {
  361. disMeasure1:{
  362. points: [new THREE.Vector3().copy(fixPoint), foot1_P1],
  363. guideLinePoints : [foot1_P2, foot1_P3] //垂足上的垂线,从最低点到最高点(包含disMeasure2那一段)
  364. }
  365. }
  366. let basePoint2d = new THREE.Vector2().copy(fixPoint.basePoint)
  367. let anotherPoint2d = new THREE.Vector2().addVectors(basePoint2d, new THREE.Vector2().subVectors(baselineP12d,baselineP22d))//测量线方向上另一点
  368. let foot2_2d = Potree.math.getFootPoint(fixPoint2d, basePoint2d, anotherPoint2d)
  369. let foot2_P1 = new THREE.Vector3(foot2_2d.x, foot2_2d.y, fixPoint.basePoint.z)
  370. let foot2_P2 = new THREE.Vector3(foot1_2d.x, foot1_2d.y, fixPoint.basePoint.z)
  371. info.disMeasure2 = {
  372. points : [new THREE.Vector3().copy(fixPoint.basePoint), foot2_P1],
  373. guideLinePoints : [foot2_P1, foot2_P2/* , foot1_P2 */],
  374. }
  375. fixPoint.bus.emit('measureChange',[
  376. {line: info.disMeasure1.points, dis: info.disMeasure1.points[0].distanceTo(info.disMeasure1.points[1])},
  377. {line: info.disMeasure2.points, dis: info.disMeasure2.points[0].distanceTo(info.disMeasure2.points[1])}
  378. ])
  379. return info
  380. }
  381. let createMeasureForPoint = (fixPoint)=>{
  382. let info = getMeasurePointsInfo(fixPoint)
  383. if(!info)return
  384. let info1 = {//垂直于基准线的水平测量线
  385. measureType : 'Hor Distance', color : pointMeasureColor ,
  386. unableDrag: true,
  387. points: info.disMeasure1.points,
  388. guideLinePoints : info.disMeasure1.guideLinePoints
  389. }
  390. let disMeasure1 = viewer.measuringTool.createMeasureFromData(info1);
  391. let info2 = {//平行于基准线的水平测量线
  392. measureType : 'Hor Distance', color : pointMeasureColor ,
  393. unableDrag: true,
  394. points: info.disMeasure2.points,
  395. guideLinePoints : info.disMeasure2.guideLinePoints
  396. }
  397. let disMeasure2 = viewer.measuringTool.createMeasureFromData(info2);
  398. fixPoint.disMeasure1 = disMeasure1;
  399. fixPoint.disMeasure2 = disMeasure2;
  400. [disMeasure1,disMeasure2].forEach(measure=>{
  401. measure.addEventListener("selected", (e) => {
  402. fixPoint.bus.emit('selectMeasure',e.state)
  403. })
  404. })
  405. }
  406. let removeMeasureForPoint = (fixPoint)=>{
  407. viewer.scene.removeMeasurement(fixPoint.disMeasure1);
  408. viewer.scene.removeMeasurement(fixPoint.disMeasure2);
  409. fixPoint.disMeasure1 = null
  410. fixPoint.disMeasure2 = null
  411. fixPoint.basePoint = null
  412. }
  413. let updateMeasureForPoint = (fixPoint, {onlyBasePoint}={})=>{
  414. let info = getMeasurePointsInfo(fixPoint)
  415. if(!info)return
  416. if(!onlyBasePoint){
  417. fixPoint.disMeasure1.points = info.disMeasure1.points
  418. fixPoint.disMeasure1.update({ifUpdateMarkers:true})
  419. }
  420. fixPoint.disMeasure1.guideLinePoints = info.disMeasure1.guideLinePoints
  421. fixPoint.disMeasure1.updateGuideLines()
  422. fixPoint.disMeasure2.points = info.disMeasure2.points
  423. fixPoint.disMeasure2.update({ifUpdateMarkers:true})
  424. fixPoint.disMeasure2.guideLinePoints = info.disMeasure2.guideLinePoints
  425. fixPoint.disMeasure2.updateGuideLines()
  426. }
  427. var sdk = {
  428. temp: {}, //记录
  429. debug: isDebug,
  430. scene: {
  431. getScreenByPoint(pos, canShelter) {
  432. //通过真实坐标获取DOM坐标
  433. let pos3d = new THREE.Vector3().copy(pos);
  434. if (canShelter) {
  435. if (viewer.ifPointBlockedByIntersect(pos3d)) {
  436. //console.log('shelter')
  437. return {
  438. trueSide: false
  439. };
  440. }
  441. }
  442. var viewport = viewer.mainViewport;
  443. var camera = viewport.camera;
  444. var dom = viewer.renderArea;
  445. //Potree.Log('getScreenByPoint scene' , pos3d.toArray(), {font:{toFixed:2,fontSize:10}})
  446. return Potree.Utils.getPos2d(pos3d, viewport, dom );
  447. },
  448. getPointByScreen(pos2d) {
  449. //获取当前画面鼠标所在位置的三维点(必须是点云点)
  450. let position,
  451. /* datasetId,
  452. dataset_location, */
  453. intersect;
  454. let Handler = viewer.inputHandler;
  455. let needReGet =
  456. !Potree.settings.depTexLocBindDataset &&
  457. Potree.settings.useDepthTex &&
  458. Handler.intersect &&
  459. !Handler.intersect.pointcloud; //如果开启了depTexLocBindDataset,热点就可能使用深度图了,属于该漫游点。全景得到的位置更均匀
  460. if ((pos2d && pos2d.inDrag) || needReGet) {
  461. //不使用当前鼠标所在位置的intersect,单独算
  462. if (!pos2d) {
  463. // needReGet
  464. intersect = Handler.getIntersect({viewport:Handler.hoverViewport, onlyGetIntersect:true, usePointcloud: true}) //数据集多的时候卡顿
  465. intersect = Handler.getIntersect(
  466. Handler.hoverViewport,
  467. true,
  468. null,
  469. null,
  470. true); //数据集多的时候卡顿
  471. } else {
  472. pos2d.clientX = pos2d.x;
  473. pos2d.clientY = pos2d.y;
  474. pos2d.onlyGetIntersect = true;
  475. pos2d.whichPointcloud = !Potree.settings.depTexLocBindDataset;
  476. pos2d.usePointcloud = true // 深度图不准
  477. intersect = Handler.onMouseMove(pos2d);
  478. }
  479. } else {
  480. intersect = Handler.intersect;
  481. }
  482. if (intersect && intersect.location) {
  483. position = intersect.location.clone();
  484. /* datasetId = intersect.pointcloud.dataset_id;
  485. dataset_location = Potree.Utils.datasetPosTransform({
  486. toDataset: true,
  487. pointcloud: intersect.pointcloud,
  488. position,
  489. }); */
  490. } else
  491. return null;
  492. //console.log('getPointByScreen',position )
  493. return {
  494. position,
  495. /* datasetId,
  496. dataset_location */
  497. };
  498. }, //全景模式一直获取会很卡
  499. getPose2() {
  500. const camera = viewer.scene.getActiveCamera();
  501. const target = viewer.scene.view.getPivot();
  502. const position = viewer.scene.view.position;
  503. return {
  504. position,
  505. target
  506. };
  507. },
  508. currentCamera() {
  509. return viewer.scene.getActiveCamera().position.clone();
  510. },
  511. // 切换模式 1 点云 0 全景图
  512. changeMode(v) {
  513. //Potree.settings.displayMode = Potree.settings.displayMode == 'showPointCloud' ? 'showPanos' : 'showPointCloud'
  514. Potree.settings.displayMode = v == 0 ? "showPanos" : "showPointCloud";
  515. },
  516. getCurrentMode() {
  517. return Potree.settings.displayMode == "showPanos" ? 0 : 1;
  518. },
  519. comeToTag(tag) {
  520. let dontLookUp = page == "geoRegistration"; //防止相机在地面以下
  521. return viewer.focusOnObject({
  522. position: new THREE.Vector3().copy(tag)
  523. },
  524. "tag",
  525. null, {
  526. dontLookUp,
  527. maxDis: Potree.config.panoFieldRadius,
  528. checkIntersect: true /*, sameFloor:true */,
  529. }).promise;
  530. },
  531. comeToMeasure(measure) {
  532. let result = viewer.focusOnObject(measure.object, "measure", 1200);
  533. return result.msg ? result.msg : result.promise;
  534. //返回值 1 deferred 表示即将位移 2 'posNoChange' 表示已在最佳位置 3 'tooFar' 表示距离最佳位置太远
  535. //后两种都代表停在原位
  536. },
  537. comeTo(o = {}) {
  538. //飞到某个点 暂时没写全景模式
  539. let deferred = $.Deferred();
  540. viewer.scene.view.setView(
  541. $.extend({}, o, {
  542. duration: o.dur,
  543. callback: () => {
  544. o.callback && o.callback();
  545. deferred.resolve(true);
  546. },
  547. }));
  548. return deferred.promise();
  549. },
  550. /**
  551. * 开始测量
  552. */
  553. startMeasure(type, unit, color) {
  554. const bus = mitt();
  555. let info = getMeasureType(type, unit);
  556. //info.bus = bus
  557. info.color = color
  558. let measure = viewer.measuringTool.startInsertion( info,
  559. () => {
  560. //done:
  561. bus.emit("end", ret); //完成
  562. },
  563. () => {
  564. //cancel
  565. bus.emit("quit", ret); //删除
  566. });
  567. Potree.Log("startMeasure: " + measure.id, {
  568. font: {
  569. color: "#00c7b2"
  570. },
  571. });
  572. viewer.setPointStandardMat(true);
  573. const ret = {
  574. bus,
  575. type,
  576. object: measure,
  577. ...getMeasureFunction(measure, bus),
  578. };
  579. measure.addEventListener("intersectNoPointcloud", () => {
  580. bus.emit("invalidPoint");
  581. });
  582. measure.addEventListener("firstClick", () => {
  583. bus.emit("firstClickMarker");
  584. });
  585. return ret;
  586. },
  587. quitMeasure() {
  588. viewer.setPointStandardMat(false);
  589. },
  590. /**
  591. * 绘画测量点
  592. */
  593. drawMeasure(
  594. type,
  595. unit,
  596. points,
  597. datasetId,
  598. dataset_points,
  599. points_datasets,
  600. sid, color) {
  601. const bus = mitt();
  602. /* if(!viewer.scene.measurements.find(e=>e.isBaseLine)){
  603. type = 'BASE_LINE'
  604. }
  605. */
  606. let info = getMeasureType(type, unit);
  607. info.points = points;
  608. //info.datasetId = datasetId;
  609. info.dataset_points = dataset_points;
  610. info.points_datasets = points_datasets;
  611. info.sid = sid;
  612. info.bus = bus;
  613. info.color = color
  614. let measure = viewer.measuringTool.createMeasureFromData(info);
  615. Potree.Log("drawMeasure由数据新建: " + measure.id, {
  616. font: {
  617. color: "#00c7b2"
  618. },
  619. });
  620. //console.log(info)
  621. /* if(measure.isBaseLine && viewer.mainViewport.camera.type != 'OrthographicCamera'){
  622. Potree.Utils.updateVisible(measure,'enterOrthoView',false)//基准线仅在正交视图可见
  623. } */
  624. const ret = {
  625. // 退出测量模式,清除之前操作
  626. object: measure,
  627. bus,
  628. ...getMeasureFunction(measure, bus),
  629. };
  630. viewer.dispatchEvent({type:'camera_changed', viewport:viewer.mainViewport, changeInfo:{}})//update sprite
  631. return ret;
  632. },
  633. /*
  634. // 创建固定点对象,measure是否是测量模式,
  635. //graph 如果是形状则有形状路径点,如果不是形状则传入pos当前固定点的位置
  636. sdk.scene.createFixPoint({ measure: boolean,
  637. graph: Array<{x,y,z}>, pos: {xyz} })
  638. */
  639. createFixPoint({measure, graph, pos, basePoint}){//创建固定点或多线段
  640. console.log('createFixPoint',measure, graph, pos, basePoint)
  641. let ifDrawVerMeasure = measure//是否绘制垂线
  642. let shape, measureFun, mainPoint = new THREE.Vector3(), bus = mitt();
  643. basePoint && (mainPoint.basePoint = new THREE.Vector3().copy(basePoint))
  644. mainPoint.bus = bus
  645. mainPoint.index11 = Math.random()
  646. const baseLineChanged = ()=>{
  647. updateMeasureForPoint(mainPoint)
  648. }
  649. const setDisplay = (show)=>{
  650. if(graph){
  651. Potree.Utils.updateVisible(shape, "forceByUser", show);
  652. }
  653. if(ifDrawVerMeasure){
  654. Potree.Utils.updateVisible(mainPoint.disMeasure1, "forceByUser", show);
  655. Potree.Utils.updateVisible(mainPoint.disMeasure2, "forceByUser", show);
  656. }
  657. viewer.dispatchEvent('content_changed')
  658. }
  659. if(graph){ //多线段形状
  660. let info = {
  661. measureType : 'MulDistance_shape', color : pointMeasureColor
  662. }
  663. let updateMeasure = ()=>{
  664. if(!shape.isNew){//更新中心点和垂线
  665. mainPoint.copy(shape.getCenter())
  666. updateMeasureForPoint(mainPoint)
  667. }
  668. }
  669. if(graph.length == 0){//开始绘制
  670. shape = viewer.measuringTool.startInsertion( info,
  671. () => {
  672. bus.emit("end", ret); //完成
  673. shape.dispatchEvent('cancelSelect')
  674. ifDrawVerMeasure && (createMeasureForPoint(mainPoint) , updateMeasure())
  675. },
  676. () => {
  677. bus.emit("quit", ret); //删除
  678. });
  679. }else{//已经得到全部点
  680. info.points = graph;
  681. info.sid = Math.random()//sid;
  682. info.bus = bus;
  683. shape = viewer.measuringTool.createMeasureFromData(info);
  684. ifDrawVerMeasure && (createMeasureForPoint(mainPoint) , updateMeasure())
  685. }
  686. ifDrawVerMeasure && bus.on("graphChange",updateMeasure)
  687. measureFun = getMeasureFunction(shape, bus, true)
  688. shape.mainPoint = mainPoint
  689. //和普通MulDistance不同点:选中才能拖拽 非选中时不展示marker (clickSelected);选中后marker是非选中状态, 但是颜色一样
  690. //https://lanhuapp.com/web/#/item/project/stage?tid=de3e5e3e-a489-4b19-862a-7c87ce113467&pid=fa4ff928-d61e-438a-b8ee-f848048b7f52
  691. }else{//固定点
  692. mainPoint.copy(pos)
  693. mainPoint.isFixPoint = true
  694. mainPoint.pos2d = Potree.Utils.getPos2d(mainPoint, viewer.mainViewport, viewer.renderArea )
  695. ifDrawVerMeasure && createMeasureForPoint(mainPoint)
  696. viewer.fixPoints.push(mainPoint)
  697. }
  698. ifDrawVerMeasure && viewer.addEventListener('baseLineChanged',baseLineChanged)
  699. const ret = {
  700. bus,
  701. destroy : ()=>{
  702. console.log('destroy' )
  703. ret.quitMeasure()
  704. if(graph){
  705. measureFun.clear()
  706. }else{
  707. let index = viewer.fixPoints.indexOf(mainPoint)
  708. index > -1 && viewer.fixPoints.splice(index,1)
  709. }
  710. },
  711. quitMeasure(){//退出测量模式,删除测量线. 基准线被删时
  712. console.log('quitMeasure' )
  713. if(ifDrawVerMeasure){
  714. ifDrawVerMeasure = false
  715. removeMeasureForPoint(mainPoint)
  716. viewer.removeEventListener('baseLineChanged',baseLineChanged)
  717. }
  718. },
  719. changePos(pos){//固定点修改
  720. console.log('changePos',pos)
  721. mainPoint.copy(pos)
  722. ifDrawVerMeasure && updateMeasureForPoint(mainPoint)
  723. },
  724. changeBase(pos){//基准点修改
  725. console.log('changeBase',pos)
  726. if(ifDrawVerMeasure){
  727. mainPoint.basePoint.copy(pos)
  728. updateMeasureForPoint(mainPoint,{onlyBasePoint:true})
  729. }
  730. },
  731. graphDrawComplete: measureFun && measureFun.end,
  732. show:()=>{
  733. setDisplay(true)
  734. },
  735. hide:()=>{
  736. setDisplay(false)
  737. },
  738. selected(state, ignoreShape){
  739. //console.error(mainPoint.index11, 'selected', state)
  740. if(graph){
  741. ignoreShape || measureFun.selected(state)
  742. }
  743. if(ifDrawVerMeasure && mainPoint.disMeasure1){
  744. if(state){
  745. mainPoint.disMeasure1.focus({dontMoveCamera:true, dontEmit:true})
  746. mainPoint.disMeasure2.focus({dontMoveCamera:true, dontEmit:true})
  747. }else{
  748. mainPoint.disMeasure1.dispatchEvent('cancelSelect')
  749. mainPoint.disMeasure2.dispatchEvent('cancelSelect')
  750. }
  751. }
  752. }
  753. };
  754. mainPoint.ret = ret
  755. return ret
  756. },
  757. // 开启放大镜
  758. openMagnifier() {
  759. //console.error('开启放大镜')
  760. viewer.magnifier.dispatchEvent({
  761. type: "setEnable",
  762. value: true
  763. });
  764. },
  765. // 关闭放大镜
  766. closeMagnifier() {
  767. //console.error('关闭放大镜')
  768. viewer.magnifier.dispatchEvent({
  769. type: "setEnable",
  770. value: false
  771. });
  772. },
  773. changePointDensity(levelType) {
  774. //点云密度:低中高
  775. Potree.settings.UserPointDensity = levelType;
  776. return {
  777. percent: Potree.config.pointDensity[levelType].maxLevelPercent,
  778. }; //回调需要更改密度百分比滑动条
  779. },
  780. changeDensityPercent(percent) {
  781. //点云密度百分比(细节) percent : 0-1
  782. //console.log('changeDensityPercent ', percent) //有出现过首次加载大于1的情况???
  783. Potree.settings.UserDensityPercent = percent;
  784. viewer.setPointLevels();
  785. },
  786. // 设置far
  787. changeViewRange(num) {
  788. Potree.settings.cameraFar = num;
  789. },
  790. // 设置色彩模式 0 彩色 1 海拔 2 半透明(透明色)
  791. changeColorMode: function (mode) {
  792. const modes = ["rgba", "elevation", "color"];
  793. mode = modes[mode];
  794. //console.log('设置色彩模式 ', mode)
  795. let otherChange = {};
  796. switch (mode) {
  797. case "rgba": //每个点的颜色
  798. otherChange.opacity = 1;
  799. otherChange.size = 0.4 / 4;
  800. break;
  801. case "elevation":
  802. otherChange.opacity = 0.3;
  803. otherChange.size = 0.4 / 4;
  804. break;
  805. case "color": //透明色
  806. //otherChange.color = ''
  807. otherChange.opacity = 0.3;
  808. otherChange.size = 0.4 / 4;
  809. break;
  810. }
  811. viewer.scene.pointclouds.forEach((e) => {
  812. e.material.activeAttributeName = mode;
  813. });
  814. sdk.scene.changePointSize(otherChange.size);
  815. sdk.scene.changePointOpacity(otherChange.opacity);
  816. delete otherChange.color;
  817. return otherChange;
  818. },
  819. // 设置点大小
  820. changePointSize(num) {
  821. viewer.scene.pointclouds.forEach((e) => {
  822. e.changePointSize(num);
  823. });
  824. },
  825. // 设置点透明度
  826. changePointOpacity: function (num) {
  827. //num:0-1 navvis用的是亮度
  828. viewer.scene.pointclouds.forEach((e) => {
  829. e.changePointOpacity(num);
  830. });
  831. },
  832. // 设置点形状 传入参数 1 矩形 2 圆形
  833. changePointShape(shape) {
  834. viewer.scene.pointclouds.forEach((e) => {
  835. e.material.shape =
  836. Potree.PointShape[shape == 1 ? "SQUARE" : "CIRCLE"]; // and PARABOLOID
  837. });
  838. },
  839. // 设置是否强化边缘
  840. changePointEdge(isStrong) {
  841. //console.log('强化边缘', isStrong)
  842. viewer.setEDLEnabled(isStrong);
  843. },
  844. // 设置漫游点位显示
  845. changePanoPoint(show) {
  846. Potree.settings.ifShowMarker = !!show;
  847. },
  848. getDownloadInfo() {
  849. //获取直接下载点云的参数给后台
  850. return viewer.modules.Clip.downloadNoCrop();
  851. },
  852. /* getDataSets() {
  853. //获取所有数据集对象
  854. let datasets = CloneJson(Potree.datasetData);
  855. datasets.forEach((e) => {
  856. var pointcloud = viewer.scene.pointclouds.find( (p) => p.dataset_id == e.id);
  857. e.changeDisplay = function (show) {
  858. Potree.Utils.updateVisible(pointcloud, "datasetSelection", !!show);
  859. pointcloud.panos.forEach((pano) => {
  860. //数据集隐藏时漫游点也隐藏 //还是不隐藏了,仅隐藏点云
  861. Potree.Utils.updateVisible(pano, "pointcloudVisi", show, 0);
  862. });
  863. if (
  864. viewer.modules.SiteModel.editing ||
  865. viewer.modules.Alignment.editing) {
  866. viewer.updateFpVisiDatasets();
  867. }
  868. };
  869. e.changeColor = function (color) {
  870. pointcloud.material.color = color;
  871. };
  872. e.getColor = function () {
  873. return pointcloud.material.color;
  874. };
  875. e.focus = function () {
  876. viewer.modules.Alignment.SplitScreen.focusOnPointCloud(pointcloud);
  877. };
  878. e.flyTo = function () {
  879. return viewer.flyToDataset({
  880. pointcloud
  881. }) || false;
  882. };
  883. e.getAttachPloygon = function () {
  884. //计算完后才会有
  885. return (
  886. pointcloud.belongToEntity && pointcloud.belongToEntity.polygon);
  887. };
  888. });
  889. return datasets;
  890. }, */
  891. screenshot: (width, height) => {
  892. //截图
  893. let meterPerPixel,
  894. isScreenshoting = true;
  895. var {
  896. getImagePromise,
  897. finishPromise
  898. } = viewer.startScreenshot({
  899. type: "default",
  900. hideMarkers:true,
  901. //hideMeasures:true,
  902. },
  903. width,
  904. height);
  905. finishPromise.done(() => {
  906. isScreenshoting = false;
  907. });
  908. if(viewer.mainViewport.camera.type == 'OrthographicCamera'){
  909. meterPerPixel = 1 / viewer.mainViewport.camera.zoom
  910. }
  911. return {finishPromise, meterPerPixel};
  912. },
  913. canTurnToPanoMode(pos) {
  914. /* if(viewer.hasNoPanoDataset){
  915. return
  916. } */
  917. pos = pos ? new THREE.Vector3().copy(pos) : viewer.images360.position;
  918. let pano = viewer.images360.findNearestPano(pos);
  919. if (
  920. pano &&
  921. pano.position.distanceTo(pos) < Potree.config.panoFieldRadius) {
  922. return true;
  923. }
  924. //poschange后会调用这个,如果返回false会变为点云模式,且不会自动变回原先的模式
  925. },
  926. trackScenePos(){// 单击场景某个位置 返回当前三维坐标, 调用时场景不能漫游与选择直到获取完成
  927. let deferred = $.Deferred();
  928. let quit = ()=>{ //取消获取
  929. viewer.removeEventListener('global_click',gotIntersect)
  930. Potree.settings.unableNavigate = false
  931. Potree.settings.unableUseDepTexPick = false
  932. viewer.controls.setEnable(true)
  933. }
  934. let gotIntersect = (e)=>{
  935. if(e.intersect && e.intersect.location){
  936. console.log('quit', e.intersect.location)
  937. quit()
  938. deferred.resolve(e.intersect.location)
  939. }
  940. }
  941. viewer.addEventListener('global_click',gotIntersect)
  942. Potree.settings.unableNavigate = true
  943. Potree.settings.unableUseDepTexPick = true
  944. viewer.controls.setEnable(false)
  945. viewer.scene.measurements.forEach(e=>e.dispatchEvent('cancelSelect')) //避免stopContinue
  946. return {
  947. promise: deferred.promise() , //获取的promise, 获取到了返回三维坐标,没获取到返回null
  948. quit
  949. }
  950. },
  951. getSceneCropSetting(){
  952. let boxData = viewer.modules.Clip.getBoxData()
  953. return {
  954. top : {value:boxData.scaleZ*100, minTop:0, maxTop:10},
  955. scale : {value: boxData.scaleXY*100},
  956. rotate : {value: THREE.Math.radToDeg(boxData.rotAngle)},
  957. //rotByUser : {value:boxData.rotByUser}
  958. }
  959. },
  960. //设置裁剪值
  961. setSceneCropSetting({top,scale,rotate }){
  962. viewer.modules.Clip.boxData = {
  963. scaleZ: top.value/100,
  964. scaleXY: scale.value/100,
  965. rotAngle: THREE.Math.degToRad(rotate.value),
  966. //rotByUser
  967. }
  968. viewer.modules.Clip.setBoxPose()
  969. },
  970. enterCropSetting(){
  971. let Clip = viewer.modules.Clip
  972. Clip.enter()
  973. return {
  974. quit(){
  975. Clip.leave()
  976. },
  977. enterSetScale(){
  978. Clip.box.frameHorizon.visible = true
  979. },
  980. leaveSetScale(){
  981. Clip.box.frameHorizon.visible = false
  982. },
  983. enterSetTop(){
  984. Clip.box.frameVertical.visible = true
  985. },
  986. leaveSetTop(){
  987. Clip.box.frameVertical.visible = false
  988. },
  989. enterSetRotate(){
  990. Clip.box.frameHorizon.visible = true
  991. Clip.box.frameVertical.visible = true
  992. },
  993. leaveSetRotate(){
  994. Clip.box.frameHorizon.visible = false
  995. Clip.box.frameVertical.visible = false
  996. },
  997. }
  998. },
  999. ...parameter.sceneBus,
  1000. },
  1001. transformPoint(point, datasetId, dataset_location) {
  1002. /* //获取由dataset_location转出的position
  1003. var r = datasetId != void 0
  1004. ? Potree.Utils.datasetPosTransform({
  1005. fromDataset: true,
  1006. datasetId,
  1007. position: dataset_location,
  1008. })
  1009. : point;
  1010. return r; */
  1011. return point
  1012. },
  1013. // 坐标转换
  1014. coordTransform: (originType, pos, targetType, datasetId) => {
  1015. // pos 坐标的类型, 当类型为SCREEN时为 { x, y } 其余为 {x, y, z}
  1016. if (pos.z == void 0)
  1017. pos.z = 0; //否则datasetPosTransform NAN 地理注册
  1018. let needMeshLocal;
  1019. if (originType == targetType)
  1020. return pos;
  1021. if (
  1022. originType == CoordType.SCENE_SCREEN ||
  1023. originType == CoordType.MAP_SCREEN) {
  1024. let tool = originType == CoordType.SCENE_SCREEN ? sdk.scene : sdk.map;
  1025. let result = tool.getPointByScreen(pos) || {}; //{ position, datasetId, dataset_location }
  1026. pos = result.position;
  1027. if (!pos)
  1028. return;
  1029. datasetId = result.datasetId;
  1030. originType = CoordType.LOCAL;
  1031. }
  1032. let pointcloud;
  1033. if (datasetId != void 0) {
  1034. pointcloud = viewer.scene.pointclouds.find(
  1035. (p) => p.dataset_id == datasetId);
  1036. }
  1037. if (originType == CoordType.MESH_LOCAL) {
  1038. pos = Potree.Utils.datasetPosTransform({
  1039. fromDataset: true,
  1040. pointcloud,
  1041. position: pos,
  1042. });
  1043. originType = CoordType.LOCAL;
  1044. }
  1045. if (targetType == CoordType.MESH_LOCAL) {
  1046. needMeshLocal = true;
  1047. targetType = CoordType.LOCAL; //先转化为求CoordType.LOCAL
  1048. }
  1049. if (originType == targetType) {
  1050. //for控制点,获取点云未移动前的坐标值。暂且这么写。
  1051. if (needMeshLocal) {
  1052. //var invMatrix = new THREE.Matrix4().getInverse(viewer.scene.pointclouds[0].transformMatrix)
  1053. pos = Potree.Utils.datasetPosTransform({
  1054. toDataset: true,
  1055. pointcloud,
  1056. position: pos,
  1057. });
  1058. }
  1059. return pos;
  1060. }
  1061. //先转成lonlat(高德)
  1062. switch (originType) {
  1063. //EPSG: 4550大地坐标
  1064. case CoordType.EPSE:
  1065. pos = viewer.transform.lonlatTo4550.inverse(pos);
  1066. break;
  1067. //Wgs84 经纬度
  1068. case CoordType.WGS84: //84转高德
  1069. //pos = wgs84ToAMap(pos)
  1070. break;
  1071. // 本地坐标
  1072. case CoordType.LOCAL:
  1073. pos = viewer.transform.lonlatToLocal.inverse(pos);
  1074. }
  1075. // 需要转换成什么类型的坐标
  1076. switch (targetType) {
  1077. case CoordType.SCENE_SCREEN: // 场景屏幕坐标
  1078. pos = sdk.scene.getScreenByPoint(pos);
  1079. break;
  1080. case CoordType.MAP_SCREEN: // 地图屏幕坐标
  1081. pos = sdk.map.getScreenByPoint(pos);
  1082. break;
  1083. //EPSG: 4550大地坐标
  1084. case CoordType.EPSE:
  1085. pos = viewer.transform.lonlatTo4550.forward(pos);
  1086. break;
  1087. //Wgs84 经纬度
  1088. case CoordType.WGS84:
  1089. //pos = aMapToWgs84(pos)
  1090. break;
  1091. //本地坐标
  1092. case CoordType.LOCAL:
  1093. pos = viewer.transform.lonlatToLocal.forward(pos);
  1094. }
  1095. if (needMeshLocal) {
  1096. pos = Potree.Utils.datasetPosTransform({
  1097. toDataset: true,
  1098. pointcloud,
  1099. position: pos,
  1100. });
  1101. }
  1102. return pos;
  1103. },
  1104. enterMeasurement() {
  1105. //进入测量模块
  1106. viewer.setLimitFar(false);
  1107. },
  1108. leaveMeasurement() {
  1109. //退出测量模块
  1110. viewer.setLimitFar(true);
  1111. },
  1112. loadModel(info) {
  1113. info.moveWithPointcloud = true;
  1114. viewer.loadModel(info);
  1115. },
  1116. enterTopView(){
  1117. viewer.navCubeViewer.dispatchEvent('enterTopView')
  1118. },
  1119. leaveTopView(){
  1120. viewer.navCubeViewer.dispatchEvent('leaveTopView')
  1121. },
  1122. destroy(){//重新创建viewer,删了旧的
  1123. viewer.setDisplay(false)
  1124. }
  1125. };
  1126. Potree.sdk = sdk;
  1127. return sdk;
  1128. };
  1129. export default enter;
  1130. /*
  1131. 热点poi加载到的数据中,pos是错误的,只使用dataset_location
  1132. 关于webgl context lost报错:
  1133. 已知有一iphoneX在创建shadowMap后才报错。
  1134. 所以报错的话很可能是代码中的某一句,去除后就会正常。
  1135. =======
  1136. 如果遇到点云只显示一部分,很可能是裁剪范围出错
  1137. */