enter.js 39 KB

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