enter.js 46 KB

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