enter.js 42 KB

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