ViewShed.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. <template>
  2. <div v-show="viewshedComb">
  3. <div class="sm-function-module-content">
  4. <div class="sm-point media-hidden"></div>
  5. <label class="sm-function-module-sub-section-setting media-hidden">{{
  6. Resource.ObserverInformation
  7. }}</label>
  8. <div class="sm-function-module-sub-section">
  9. <div class="sm-half">
  10. <label class="sm-function-module-sub-section-caption">{{
  11. Resource.longitude
  12. }}</label>
  13. <input
  14. v-model="viewlongitude"
  15. type="text"
  16. id="viewshed-observation-place-x"
  17. class="sm-input-right"
  18. />
  19. </div>
  20. <div class="sm-half">
  21. <label
  22. class="sm-function-module-sub-section-caption"
  23. style="margin-left: 20px"
  24. >{{ Resource.latitude }}</label
  25. >
  26. <input
  27. v-model="viewlatitude"
  28. type="text"
  29. id="viewshed-observation-place-y"
  30. class="sm-input-right"
  31. />
  32. </div>
  33. <div class="sm-half">
  34. <label class="sm-function-module-sub-section-caption">{{
  35. Resource.altitude
  36. }}</label>
  37. <input
  38. v-model="viewheight"
  39. type="text"
  40. id="viewshed-observation-place-z"
  41. class="sm-input-right"
  42. />
  43. </div>
  44. </div>
  45. <div class="sm-point media-hidden"></div>
  46. <label class="sm-function-module-sub-section-setting media-hidden">{{
  47. Resource.parameterSetting
  48. }}</label>
  49. <div class="sm-function-module-sub-section">
  50. <div class="sm-half">
  51. <label class="sm-function-module-sub-section-caption">{{
  52. Resource.additionalHeight
  53. }}</label>
  54. <input
  55. type="number"
  56. id="addheight"
  57. class="sm-input sm-input-long"
  58. step="0.1"
  59. min="0"
  60. v-model="addheight"
  61. />
  62. </div>
  63. <div class="sm-half">
  64. <label
  65. class="sm-function-module-sub-section-caption"
  66. style="margin-left: 20px"
  67. >{{ Resource.directionAngle }}</label
  68. >
  69. <input
  70. type="number"
  71. id="direction"
  72. class="sm-input sm-input-long"
  73. min="0"
  74. max="360"
  75. step="1.0"
  76. v-model="direction"
  77. />
  78. </div>
  79. <!-- </div>
  80. <div class="sm-function-module-sub-section"> -->
  81. <div class="sm-half">
  82. <label class="sm-function-module-sub-section-caption">{{
  83. Resource.visualRange
  84. }}</label>
  85. <input
  86. type="number"
  87. id="distance"
  88. class="sm-input sm-input-long"
  89. min="1"
  90. step="1"
  91. v-model="distance"
  92. />
  93. </div>
  94. <div class="sm-half">
  95. <label
  96. class="sm-function-module-sub-section-caption"
  97. style="margin-left: 20px"
  98. >{{ Resource.ElevationAngle }}</label
  99. >
  100. <input
  101. type="number"
  102. id="pitch"
  103. class="sm-input sm-input-long"
  104. min="-90"
  105. max="90"
  106. step="1.0"
  107. v-model="pitch"
  108. />
  109. </div>
  110. <!-- </div> -->
  111. <!-- <div> -->
  112. <div class="sm-half">
  113. <label class="sm-function-module-sub-section-caption">{{
  114. Resource.horizontalFov
  115. }}</label>
  116. <input
  117. type="number"
  118. id="horizontalFov"
  119. class="sm-input sm-input-long"
  120. min="1"
  121. max="120"
  122. step="1.0"
  123. title="水平视角"
  124. v-model="horizontalFov"
  125. />
  126. </div>
  127. <div class="sm-half">
  128. <label
  129. class="sm-function-module-sub-section-caption"
  130. style="margin-left: 20px"
  131. >{{ Resource.verticalFov }}</label
  132. >
  133. <input
  134. type="number"
  135. id="verticalFov"
  136. class="sm-input sm-input-long"
  137. min="1"
  138. step="1.0"
  139. title="垂直视角"
  140. v-model="verticalFov"
  141. />
  142. </div>
  143. </div>
  144. <div class="sm-function-module-sub-section">
  145. <div class="sm-point"></div>
  146. <label class="sm-function-module-sub-section-setting">{{
  147. Resource.colorSetting
  148. }}</label>
  149. <div>
  150. <label class="sm-function-module-sub-section-caption">{{
  151. Resource.promptLineColor
  152. }}</label>
  153. <ColorPicker class="sm-colorpicker" v-model="hintLineColor" alpha />
  154. </div>
  155. <div>
  156. <input type="checkbox" checked />
  157. <label class="sm-function-module-sub-section-caption">{{
  158. Resource.visibleColor
  159. }}</label>
  160. <ColorPicker
  161. class="sm-colorpicker"
  162. v-model="visibleAreaColor"
  163. alpha
  164. />
  165. </div>
  166. <div>
  167. <input type="checkbox" checked />
  168. <label class="sm-function-module-sub-section-caption">{{
  169. Resource.invisibleColor
  170. }}</label>
  171. <ColorPicker class="sm-colorpicker" v-model="hiddenAreaColor" alpha />
  172. </div>
  173. <div>
  174. <input type="checkbox" v-model="visibleBody" />
  175. <label class="sm-function-module-sub-section-caption">{{
  176. Resource.displayVisualsBody
  177. }}</label>
  178. <ColorPicker
  179. class="sm-colorpicker"
  180. v-model="visibleBodyColor"
  181. alpha
  182. />
  183. </div>
  184. <div>
  185. <input type="checkbox" v-model="invisibleBody" />
  186. <label class="sm-function-module-sub-section-caption">{{
  187. Resource.displayInvisibleBody
  188. }}</label>
  189. <ColorPicker
  190. class="sm-colorpicker"
  191. v-model="invisibleBodyColor"
  192. alpha
  193. />
  194. </div>
  195. </div>
  196. <!-- <div>
  197. <input type="checkbox" id="visible5" />
  198. <label class="sm-function-module-sub-section-caption">高亮显示可见体</label>
  199. </div>-->
  200. <div class="boxchild">
  201. <el-button type="primary" size="mini" @click="chooseView">
  202. {{ Resource.analyze }}
  203. </el-button>
  204. <el-button type="primary" size="mini" @click="clear">
  205. {{ Resource.eliminate }}
  206. </el-button>
  207. </div>
  208. </div>
  209. </div>
  210. </template>
  211. <script>
  212. let viewshed3D, handler, pointHandler, s3mInstanceColc;
  213. export default {
  214. name: "Sm3dViewshed",
  215. props: {
  216. spatialAnalysisUrl: {
  217. type: String,
  218. },
  219. },
  220. data() {
  221. return {
  222. sharedState: store.state,
  223. spurl: "",
  224. viewlongitude: 0,
  225. viewlatitude: 0,
  226. viewheight: 0,
  227. direction: 1.0,
  228. pitch: 1.0,
  229. addheight: 1.8,
  230. distance: 1.0,
  231. verticalFov: 60,
  232. horizontalFov: 90,
  233. hintLineColor: "rgb(212,202,45)",
  234. visibleAreaColor: "rgb(9,199,112)",
  235. hiddenAreaColor: "rgb(238,114,22)",
  236. visibleBodyColor: "rgb(44,149,197)",
  237. invisibleBodyColor: "rgb(200,0,0)",
  238. visibleBody: false,
  239. invisibleBody: false,
  240. isDestroyFlag: true,
  241. originViewshedObservationPlace: {},
  242. };
  243. },
  244. computed: {
  245. viewshedComb: function () {
  246. return this.sharedState.analysis[1];
  247. },
  248. analysisShow: function () {
  249. return this.sharedState.toolBar[6];
  250. },
  251. },
  252. beforeDestroy() {
  253. if (this.isDestroyFlag && pointHandler) {
  254. if (s3mInstanceColc) {
  255. s3mInstanceColc.destroy();
  256. }
  257. viewshed3D.destroy();
  258. handler.destroy();
  259. pointHandler.deactivate();
  260. viewshed3D = undefined;
  261. handler = undefined;
  262. pointHandler = undefined;
  263. s3mInstanceColc = undefined;
  264. }
  265. },
  266. mounted() {
  267. if (this.analysisShow && this.viewshedComb) {
  268. this.init();
  269. }
  270. },
  271. methods: {
  272. init() {
  273. if (viewshed3D) {
  274. return;
  275. }
  276. // 创建可视域分析对象
  277. scene = viewer.scene;
  278. scene.viewFlag = true;
  279. if (!viewshed3D) {
  280. viewshed3D = new Cesium.ViewShed3D(scene);
  281. }
  282. viewshed3D.hintLineColor = Cesium.Color.fromCssColorString(
  283. this.hintLineColor
  284. );
  285. viewshed3D.visibleAreaColor = Cesium.Color.fromCssColorString(
  286. this.visibleAreaColor
  287. );
  288. viewshed3D.hiddenAreaColor = Cesium.Color.fromCssColorString(
  289. this.hiddenAreaColor
  290. );
  291. let that = this;
  292. handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
  293. // 鼠标移动时间回调
  294. handler.setInputAction(function (e) {
  295. // 若此标记为false,则激活对可视域分析对象的操作
  296. if (!scene.viewFlag) {
  297. //获取鼠标屏幕坐标,并将其转化成笛卡尔坐标
  298. let position = e.endPosition;
  299. let last = scene.pickPosition(position);
  300. //计算该点与视口位置点坐标的距离
  301. let distance = Cesium.Cartesian3.distance(that.viewPosition, last);
  302. if (distance > 0) {
  303. // 将鼠标当前点坐标转化成经纬度
  304. let cartographic = Cesium.Cartographic.fromCartesian(last);
  305. let longitude = Cesium.Math.toDegrees(cartographic.longitude);
  306. let latitude = Cesium.Math.toDegrees(cartographic.latitude);
  307. let height = cartographic.height;
  308. // 通过该点设置可视域分析对象的距离及方向
  309. viewshed3D.setDistDirByPoint([longitude, latitude, height]);
  310. }
  311. }
  312. }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  313. handler.setInputAction(function (e) {
  314. //鼠标右键事件回调,不再执行鼠标移动事件中对可视域的操作
  315. if (!scene.viewFlag) {
  316. scene.viewFlag = true;
  317. that.direction = viewshed3D.direction.toFixed(2);
  318. that.pitch = viewshed3D.pitch.toFixed(2);
  319. that.distance = viewshed3D.distance.toFixed(2);
  320. that.horizontalFov = viewshed3D.horizontalFov;
  321. that.verticalFov = viewshed3D.verticalFov;
  322. }
  323. }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  324. pointHandler = new Cesium.DrawHandler(viewer, Cesium.DrawMode.Point);
  325. pointHandler.drawEvt.addEventListener(function (result) {
  326. let point = result.object;
  327. let position = point.position;
  328. that.viewPosition = position;
  329. // 将获取的点的位置转化成经纬度
  330. let cartographic = Cesium.Cartographic.fromCartesian(position);
  331. let longitude = Cesium.Math.toDegrees(cartographic.longitude);
  332. let latitude = Cesium.Math.toDegrees(cartographic.latitude);
  333. let height = cartographic.height;
  334. that.originViewshedObservationPlace = { longitude, latitude, height };
  335. let additionalHeight = Number(that.addheight);
  336. let heightnew = cartographic.height + additionalHeight;
  337. point.position = Cesium.Cartesian3.fromDegrees(
  338. longitude,
  339. latitude,
  340. heightnew
  341. );
  342. if (scene.viewFlag) {
  343. // 设置视口位置
  344. viewshed3D.viewPosition = [longitude, latitude, heightnew];
  345. viewshed3D.build();
  346. // 将标记置为false以激活鼠标移动回调里面的设置可视域操作
  347. scene.viewFlag = false;
  348. that.viewlongitude = longitude.toFixed(4);
  349. that.viewlatitude = latitude.toFixed(4);
  350. that.viewheight = height.toFixed(2);
  351. }
  352. });
  353. },
  354. chooseView() {
  355. // this.init();
  356. if (pointHandler.active) {
  357. return;
  358. }
  359. this.isDestroyFlag = false; //保留效果
  360. //先清除之前的可视域分析
  361. viewer.entities.removeAll();
  362. viewshed3D.distance = 0.1;
  363. viewer.scene.viewFlag = true;
  364. //激活绘制点类
  365. pointHandler.activate();
  366. },
  367. getVisibleResult() {
  368. if (!viewshed3D) {
  369. return;
  370. }
  371. if (!s3mInstanceColc) {
  372. s3mInstanceColc = new Cesium.S3MInstanceCollection(scene._context);
  373. viewer.scene.primitives.add(s3mInstanceColc);
  374. }
  375. let that = this;
  376. let obj = viewshed3D.getViewshedParameter();
  377. let geometryViewShedBodyvisibleParameter = {
  378. viewerPoint: obj.viewPosition,
  379. point3DsList: obj.point3DList,
  380. radius: obj.distance,
  381. lonlat: true,
  382. viewShedType: "VISIBLEBODY",
  383. };
  384. let url = this.spurl;
  385. // "http://www.supermapol.com/realspace/services/spatialAnalysis-data_all/restjsr/spatialanalyst/geometry/3d/viewshedbody.json";
  386. let queryData = JSON.stringify(geometryViewShedBodyvisibleParameter);
  387. let color = Cesium.Color.fromCssColorString(this.visibleBodyColor);
  388. //先发送POST请求
  389. window.axios
  390. .post(url, queryData)
  391. .then(function (response) {
  392. //再发送一次GET请求 获取到运算结果
  393. window.axios
  394. .get(response.data.newResourceLocation + ".json")
  395. .then(function (response) {
  396. let data = response.data;
  397. //失败 没有内容
  398. if (data.geometry == null) {
  399. return;
  400. }
  401. //将二进制流构建arrayBuffer 添加至S3MInstanceCollection
  402. let u8 = new Uint8Array(data.geometry.model);
  403. let ab = u8.buffer;
  404. //注意 若添加多个模型 请保证各个名称唯一 否则可能引起显示错乱问题
  405. s3mInstanceColc.add(
  406. "resultV",
  407. {
  408. id: 1,
  409. position: Cesium.Cartesian3.fromDegrees(
  410. data.geometry.position.x,
  411. data.geometry.position.y,
  412. data.geometry.position.z
  413. ),
  414. hpr: new Cesium.HeadingPitchRoll(0, 0, 0),
  415. //scale : new Cesium.Cartesian3(39.37007900000045,39.37007900000045,39.37007900000045),
  416. color: color,
  417. //offset : new Cesium.Cartesian3(0,0,690)
  418. },
  419. ab
  420. );
  421. })
  422. .catch(function (error) {
  423. console.log(error);
  424. });
  425. })
  426. .catch(function (error) {
  427. console.log(error);
  428. });
  429. },
  430. getInVisibleResult() {
  431. if (!viewshed3D) {
  432. return;
  433. }
  434. if (!s3mInstanceColc) {
  435. s3mInstanceColc = new Cesium.S3MInstanceCollection(scene._context);
  436. viewer.scene.primitives.add(s3mInstanceColc);
  437. }
  438. let that = this;
  439. let obj = viewshed3D.getViewshedParameter();
  440. let geometryViewShedBodyvisibleParameter = {
  441. viewerPoint: obj.viewPosition,
  442. point3DsList: obj.point3DList,
  443. radius: obj.distance,
  444. lonlat: true,
  445. viewShedType: "HIDDENBODY",
  446. };
  447. let url = this.spurl;
  448. // "http://www.supermapol.com/realspace/services/spatialAnalysis-data_all/restjsr/spatialanalyst/geometry/3d/viewshedbody.json";
  449. let queryData = JSON.stringify(geometryViewShedBodyvisibleParameter);
  450. let color = Cesium.Color.fromCssColorString(this.invisibleBodyColor);
  451. //先发送POST请求
  452. window.axios
  453. .post(url, queryData)
  454. .then(function (response) {
  455. //再发送一次GET请求 获取到运算结果
  456. window.axios
  457. .get(response.data.newResourceLocation + ".json")
  458. .then(function (response) {
  459. let data = response.data;
  460. //失败 没有内容
  461. if (data.geometry == null) {
  462. return;
  463. }
  464. //将二进制流构建arrayBuffer 添加至S3MInstanceCollection
  465. let u8 = new Uint8Array(data.geometry.model);
  466. let ab = u8.buffer;
  467. //注意 若添加多个模型 请保证各个名称唯一 否则可能引起显示错乱问题
  468. s3mInstanceColc.add(
  469. "resultUnV",
  470. {
  471. id: 2,
  472. position: Cesium.Cartesian3.fromDegrees(
  473. data.geometry.position.x,
  474. data.geometry.position.y,
  475. data.geometry.position.z
  476. ),
  477. hpr: new Cesium.HeadingPitchRoll(0, 0, 0),
  478. //scale : new Cesium.Cartesian3(39.37007900000045,39.37007900000045,39.37007900000045),
  479. color: color,
  480. //offset : new Cesium.Cartesian3(0,0,690)
  481. },
  482. ab
  483. );
  484. })
  485. .catch(function (error) {
  486. console.log(error);
  487. });
  488. })
  489. .catch(function (error) {
  490. console.log(error);
  491. });
  492. },
  493. clear() {
  494. this.isDestroyFlag = true; //摧毁标志,释放内存
  495. viewer.entities.removeAll();
  496. scene.viewFlag = true;
  497. pointHandler.clear();
  498. this.viewlongitude = 0;
  499. this.viewlatitude = 0;
  500. this.viewheight = 0;
  501. this.addheight = 1.8;
  502. this.direction = 1.0;
  503. this.pitch = 1.0;
  504. this.distance = 1.0;
  505. this.horizontalFov = 90;
  506. this.verticalFov = 60;
  507. this.hintLineColor = "rgb(212,202,45)";
  508. this.visibleAreaColor = "rgb(9,199,112)";
  509. this.hiddenAreaColor = "rgb(238,114,22)";
  510. this.visibleBodyColor = "rgb(44,149,197)";
  511. this.invisibleBodyColor = "rgb(200,0,0)";
  512. //初始化参数
  513. if (viewshed3D) {
  514. // viewshed3D.clear();
  515. viewshed3D.direction = this.direction;
  516. viewshed3D.pitch = this.pitch;
  517. viewshed3D.distance = this.distance;
  518. viewshed3D.horizontalFov = this.horizontalFov;
  519. viewshed3D.verticalFov = this.verticalFov;
  520. }
  521. this.visibleBody = false;
  522. this.invisibleBody = false;
  523. },
  524. destory() {
  525. if (s3mInstanceColc) {
  526. s3mInstanceColc.destroy();
  527. s3mInstanceColc = undefined;
  528. }
  529. if (viewshed3D) {
  530. viewshed3D.destroy();
  531. viewshed3D = undefined;
  532. }
  533. },
  534. },
  535. watch: {
  536. viewshedComb(val) {
  537. if (val) {
  538. this.init();
  539. }
  540. },
  541. addheight: function (newValue) {
  542. let originViewshedObservationPlace = this.originViewshedObservationPlace;
  543. let longitude = originViewshedObservationPlace.longitude;
  544. let latitude = originViewshedObservationPlace.latitude;
  545. if (newValue === "") {
  546. // 避免删除导致崩溃
  547. newValue = "0.0";
  548. }
  549. let height = originViewshedObservationPlace.height + parseFloat(newValue);
  550. let cartesian = Cesium.Cartesian3.fromDegrees(
  551. longitude,
  552. latitude,
  553. height
  554. );
  555. viewshed3D.viewPosition = [longitude, latitude, height];
  556. },
  557. direction: function (newValue) {
  558. viewshed3D.direction = parseFloat(newValue);
  559. },
  560. distance: function (newValue) {
  561. viewshed3D.distance = parseFloat(newValue);
  562. },
  563. pitch: function (newValue) {
  564. viewshed3D.pitch = parseFloat(newValue);
  565. },
  566. verticalFov: function (newValue) {
  567. viewshed3D.verticalFov = parseFloat(newValue);
  568. },
  569. horizontalFov: function (newValue) {
  570. viewshed3D.horizontalFov = parseFloat(newValue);
  571. },
  572. hintLineColor: function (newValue) {
  573. let color = Cesium.Color.fromCssColorString(newValue);
  574. viewshed3D.hintLineColor = color;
  575. },
  576. visibleAreaColor: function (newValue) {
  577. let color = Cesium.Color.fromCssColorString(newValue);
  578. viewshed3D.visibleAreaColor = color;
  579. },
  580. hiddenAreaColor: function (newValue) {
  581. let color = Cesium.Color.fromCssColorString(newValue);
  582. viewshed3D.hiddenAreaColor = color;
  583. },
  584. visibleBodyColor: function (newValue) {
  585. let color = Cesium.Color.fromCssColorString(newValue);
  586. if (
  587. s3mInstanceColc &&
  588. s3mInstanceColc instanceof Cesium.S3MInstanceCollection
  589. ) {
  590. s3mInstanceColc.getInstance("resultV", 1).updateColor(color);
  591. }
  592. },
  593. invisibleBodyColor: function (newValue) {
  594. let color = Cesium.Color.fromCssColorString(newValue);
  595. if (
  596. s3mInstanceColc &&
  597. s3mInstanceColc instanceof Cesium.S3MInstanceCollection
  598. ) {
  599. s3mInstanceColc.getInstance("resultUnV", 2).updateColor(color);
  600. }
  601. },
  602. visibleBody: function (newValue) {
  603. if (newValue) {
  604. this.getVisibleResult();
  605. } else {
  606. //清除体
  607. if (
  608. s3mInstanceColc &&
  609. s3mInstanceColc instanceof Cesium.S3MInstanceCollection
  610. ) {
  611. s3mInstanceColc.removeCollection("resultV");
  612. }
  613. }
  614. },
  615. invisibleBody: function (newValue) {
  616. console.log(newValue);
  617. if (newValue) {
  618. this.getInVisibleResult();
  619. } else {
  620. //清除体
  621. if (
  622. s3mInstanceColc &&
  623. s3mInstanceColc instanceof Cesium.S3MInstanceCollection
  624. ) {
  625. s3mInstanceColc.removeCollection("resultUnV");
  626. }
  627. }
  628. },
  629. spatialAnalysisUrl: {
  630. immediate: true,
  631. handler: function (val, oldVal) {
  632. if (val) {
  633. this.spurl = val;
  634. }
  635. },
  636. },
  637. },
  638. };
  639. </script>
  640. <style lang="scss" scoped>
  641. @import "ViewShed";
  642. </style>