SunlightAnalysisCT.vue 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648
  1. <template>
  2. <div
  3. class="ZTGlobal"
  4. style="width: 100%; padding: 1rem 1.1rem 0rem; color: white"
  5. v-loading.fullscreen.lock="loading"
  6. element-loading-text="正在分析中...."
  7. element-loading-spinner="el-icon-loading"
  8. element-loading-background="rgba(0, 0, 0, 0.8)"
  9. >
  10. <el-row :gutter="10">
  11. <el-col :span="24">
  12. <div class="titleHeader">
  13. <h3>参数设置</h3>
  14. </div>
  15. </el-col>
  16. </el-row>
  17. <el-row :gutter="10">
  18. <el-col :span="24">
  19. <el-row :gutter="10" style="display: flex; align-items: center">
  20. <el-col :span="24">
  21. 日 期:
  22. <el-date-picker
  23. size="mini"
  24. v-model="form.selDate"
  25. type="date"
  26. placeholder="选择日期"
  27. >
  28. </el-date-picker>
  29. </el-col>
  30. </el-row>
  31. <el-row :gutter="10" style="display: flex; align-items: center">
  32. <el-col :span="6"> 日照时间范围: </el-col>
  33. <el-col :span="18">
  34. <el-slider
  35. size="mini"
  36. v-model="datavalue"
  37. range
  38. :marks="marks"
  39. :max="24"
  40. @change="datavalueChange"
  41. >
  42. </el-slider>
  43. </el-col>
  44. </el-row>
  45. <el-row :gutter="10" style="display: flex; align-items: center">
  46. <el-col :span="6"> 日照播放速度: </el-col>
  47. <el-col :span="18">
  48. <el-input-number
  49. size="mini"
  50. v-model="Intervalshijian"
  51. :min="1"
  52. :max="100"
  53. ></el-input-number>
  54. </el-col>
  55. </el-row>
  56. <el-row :gutter="10">
  57. <el-col :span="24">
  58. <div class="SaveCenter" style="padding: 0">
  59. <el-button size="mini" type="primary" @click="statrSunlight"
  60. >执行日照效果</el-button
  61. >
  62. <el-button size="mini" type="primary" @click="dqSunlight"
  63. >当前日照</el-button
  64. >
  65. </div>
  66. </el-col>
  67. </el-row>
  68. <el-divider></el-divider>
  69. <!-- <el-row :gutter="10">
  70. <el-col :span="12">
  71. 时间间隔:
  72. <el-input-number
  73. style="width: 50%"
  74. size="mini"
  75. v-model="form.timeInterval"
  76. ></el-input-number>
  77. </el-col>
  78. <el-col :span="12">
  79. 间距(米):
  80. <el-input-number
  81. style="width: 50%"
  82. size="mini"
  83. v-model="form.spacing"
  84. ></el-input-number>
  85. </el-col>
  86. </el-row> -->
  87. <!-- <el-row :gutter="10">
  88. <el-col :span="12" style="text-align: center">
  89. X坐标(度):
  90. <el-input-number
  91. size="mini"
  92. step="0.000001"
  93. v-model="form.x"
  94. @change="XYChange"
  95. ></el-input-number>
  96. </el-col>
  97. <el-col :span="12" style="text-align: center">
  98. Y坐标(度):
  99. <el-input-number
  100. size="mini"
  101. step="0.000001"
  102. v-model="form.y"
  103. @change="XYChange"
  104. ></el-input-number>
  105. </el-col>
  106. </el-row> -->
  107. <!-- <el-row :gutter="10">
  108. <el-col :span="12">
  109. 底部高程(米):
  110. <el-input-number
  111. style="width: 50%"
  112. size="mini"
  113. v-model="form.bottomHeight"
  114. ></el-input-number>
  115. </el-col>
  116. <el-col :span="12">
  117. 拉伸高度(米):
  118. <el-input-number
  119. style="width: 50%"
  120. size="mini"
  121. v-model="form.extrudeHeight"
  122. ></el-input-number>
  123. </el-col>
  124. </el-row> -->
  125. <el-row :gutter="5">
  126. <el-col :span="13">
  127. <!-- 阴影分析时日照时间案范围重合时为时刻阴影,不重合时计算为时间范围内阴影率 -->
  128. 分析高度:
  129. <el-tooltip
  130. class="item"
  131. effect="dark"
  132. content="当分析高度为0时,自动读取绘制范围范围时第一个点的高度值。后续不为0时按设置高度分析。"
  133. placement="top"
  134. >
  135. <el-input-number
  136. size="mini"
  137. v-model="gd"
  138. :min="0"
  139. :max="100"
  140. ></el-input-number>
  141. </el-tooltip>
  142. </el-col>
  143. <el-col :span="11">
  144. <input @change="handleUpload" type="file" style="display:none" id="fileInput" accept=".geojson"></input>
  145. <el-button size="mini" type="primary" @click="inputGeometry"
  146. >导入范围</el-button
  147. >
  148. <el-button size="mini" type="primary" @click="outGeometry"
  149. >导出范围</el-button
  150. >
  151. </el-col>
  152. </el-row>
  153. </el-col>
  154. </el-row>
  155. <!-- <el-row :gutter="10" v-if="multiViewportMode > 1">
  156. <el-col :span="24">
  157. 选择分析视口:<el-radio-group
  158. v-model="radio"
  159. v-for="item in multiViewportMode"
  160. :key="item"
  161. >
  162. <el-radio :label="item - 1">窗口{{ item }}</el-radio>
  163. </el-radio-group>
  164. </el-col>
  165. </el-row> -->
  166. <div class="SaveCenter">
  167. <el-row :gutter="10">
  168. <el-col :span="24">
  169. <el-button size="mini" type="primary" @click="onSubmit"
  170. >自定义日照分析</el-button
  171. >
  172. <el-button size="mini" type="primary" @click="onDHSubmit"
  173. >大寒日</el-button
  174. >
  175. <el-button size="mini" type="primary" @click="onDZSubmit"
  176. >冬至日</el-button
  177. >
  178. </el-col>
  179. </el-row>
  180. <el-row :gutter="10">
  181. <el-col :span="24">
  182. <el-tooltip
  183. effect="dark"
  184. content="日照时长结果生成后,调整地图到合适位置,然后导出"
  185. placement="bottom"
  186. >
  187. <el-button
  188. size="mini"
  189. type="primary"
  190. :disabled="sdh.length == 0 ? true : false"
  191. @click="ExportResult"
  192. >导出结果</el-button
  193. >
  194. </el-tooltip>
  195. <el-button size="mini" @click="resetForm">清除</el-button>
  196. </el-col>
  197. </el-row>
  198. </div>
  199. <el-row :gutter="10">
  200. <el-col :span="24">
  201. <el-descriptions border size="mini" :column="2">
  202. <el-descriptions-item
  203. v-for="item in sdh"
  204. :key="item"
  205. :label="item.scS + ' 小时'"
  206. ><div
  207. style="width: 4.5rem; height: 100%"
  208. :style="{ 'background-color': item.fill }"
  209. >
  210. &nbsp;
  211. </div>
  212. </el-descriptions-item>
  213. </el-descriptions>
  214. </el-col>
  215. </el-row>
  216. <!-- <el-row :gutter="10">
  217. <el-col :span="24">
  218. <el-table
  219. size="mini"
  220. :data="tableData"
  221. style="width: 100%"
  222. :highlight-current-row="true"
  223. @row-click="rowClick"
  224. >
  225. <el-table-column prop="heightText" label="高程"> </el-table-column>
  226. <el-table-column prop="sunDate" label="日照时间"> </el-table-column>
  227. <el-table-column
  228. prop="shadowRadioText"
  229. label="日照率"
  230. ></el-table-column>
  231. </el-table>
  232. </el-col>
  233. </el-row> -->
  234. </div>
  235. </template>
  236. <script>
  237. var handlerPolygon = null,
  238. layers = null,
  239. shadowQuery = null,
  240. markedPoints = [];
  241. var sdfff = null;
  242. var czsj = { points1: null, dd1: null };
  243. import {
  244. intersect,
  245. flatten,
  246. envelope,
  247. point,
  248. buffer,
  249. bboxPolygon,
  250. bbox,
  251. square,
  252. destination,
  253. polygon,
  254. featureCollection,
  255. interpolate,
  256. isobands,
  257. area,
  258. isolines,
  259. pointGrid,
  260. invariant
  261. } from "@turf/turf";
  262. // # 引入kriging-contour
  263. import {
  264. getVectorContour,
  265. drawCanvasContour,
  266. } from "kriging-contour/dist/kriging-contour.js";
  267. // import { getSunrise, getSunset } from "sunrise-sunset-js";
  268. import {
  269. cartesian3ToWGS84,
  270. mapQuery,
  271. mercator2lonLat,
  272. undergroundMode,
  273. } from "@/utils/MapHelper/MapHelper.js";
  274. import { v4 as uuidv4 } from "uuid";
  275. import moment from "moment";
  276. export default {
  277. data() {
  278. return {
  279. tooltip: createTooltip(document.body),
  280. form: {
  281. timeInterval: 60,
  282. spacing: 8,
  283. selDate: new Date(),
  284. startTime: 10,
  285. endTime: 14,
  286. bottomHeight: 0,
  287. extrudeHeight: 100,
  288. x: 0,
  289. y: 0,
  290. },
  291. sdh: [
  292. { scS: "0-1", fill: "#313695" },
  293. { scS: "1-2", fill: "#1E90A8" },
  294. { scS: "2-3", fill: "#00B457" },
  295. { scS: "3-4", fill: "#B7FF01" },
  296. { scS: "4-5", fill: "#F2A705" },
  297. { scS: ">=5", fill: "#FF0000" },
  298. ],
  299. loading: false,
  300. datavalue: [10, 14],
  301. positions: [],
  302. points: [],
  303. // layers: null,
  304. // shadowQuery: null,
  305. marks: {
  306. 8: "8点",
  307. 12: {
  308. style: {
  309. color: "#1989FA",
  310. },
  311. label: this.$createElement("strong", "12点"),
  312. },
  313. 20: "20点",
  314. },
  315. tableData: [],
  316. multiViewportMode: 0,
  317. radio: 0,
  318. eids: [],
  319. //记录进入页面时的场景参数
  320. RecordInitializationScene: {},
  321. nIntervId: null,
  322. Intervalshijian: 10,
  323. gd: 0,
  324. geopolygon:null,
  325. ProjectScope:{positions:[]}
  326. };
  327. },
  328. props: {
  329. info: {
  330. type: Object,
  331. default: () => {
  332. return {};
  333. },
  334. },
  335. layerid: {
  336. type: String,
  337. default: "",
  338. },
  339. lydata: {
  340. type: Object,
  341. default: () => {
  342. return {};
  343. },
  344. },
  345. lyoption: {
  346. type: Object,
  347. default: () => {
  348. return {};
  349. },
  350. },
  351. },
  352. computed: {},
  353. mounted() {
  354. this.multiViewportMode = scene.multiViewportMode + 1;
  355. document.oncontextmenu = function (e) {
  356. e.preventDefault();
  357. };
  358. this.init();
  359. },
  360. methods: {
  361. init() {
  362. let scene = viewer.scene;
  363. layers = scene.layers.layerQueue;
  364. this.RecordInitializationScene.shadows = viewer.shadows;
  365. this.RecordInitializationScene.layersshadowType = [];
  366. for (let i = 0; i < layers.length; i++) {
  367. this.RecordInitializationScene.layersshadowType.push({
  368. name: layers[i].name,
  369. shadowType: layers[i].shadowType,
  370. });
  371. }
  372. if (viewer.shadows == false) {
  373. viewer.shadows = true; //开启场景阴影
  374. }
  375. //图层模型设置阴影
  376. for (let i = 0; i < layers.length; i++) {
  377. // if (layers[i].shadowType !== 2) {
  378. layers[i].shadowType = 2;
  379. // layers[i].refresh();
  380. // }
  381. }
  382. this.dqSunlight();
  383. },
  384. /**
  385. * 导出范围
  386. */
  387. outGeometry(){
  388. if(this.geopolygon){
  389. this.exportRaw("绘制范围.geojson",JSON.stringify(this.geopolygon));
  390. }else{
  391. this.$message.warning("请先执行分析后再保存绘制的区域!!!");
  392. }
  393. },
  394. /**
  395. * 点击导入范围
  396. */
  397. inputGeometry() {
  398. var element = document.getElementById('fileInput');
  399. if (element)
  400. element.click();
  401. },
  402. handleUpload(e) {
  403. const file = e.target.files[0];
  404. if (!file) {
  405. return;
  406. }
  407. var that = this;
  408. const reader = new FileReader();
  409. reader.onload = function(e) {
  410. var geojson =JSON.parse(e.target.result);
  411. e.target.files=[];
  412. document.getElementById('fileInput').value = '';
  413. if (!geojson || typeof geojson !== 'object' || geojson.geometry.type!="Polygon") {
  414. that.$message.warning("导入的范围格式错误!!!");
  415. return false;
  416. }
  417. that.addGeometry(geojson);
  418. };
  419. reader.onerror = function(error) {
  420. e.target.files=[];
  421. document.getElementById('fileInput').value = '';
  422. console.error('Error: ', error);
  423. };
  424. reader.readAsText(file);
  425. },
  426. /**
  427. * 导入范围添加图形
  428. */
  429. addGeometry(geojson) {
  430. var that = this;
  431. that.clear();
  432. debugger
  433. var coordinates = geojson.geometry.coordinates;
  434. var positions = [];
  435. that.ProjectScope.positions = [];
  436. for (var i = 0; i < coordinates.length; i++) {
  437. var coor = coordinates[i];
  438. if (coor && coor.length > 0) {
  439. for (var j = 0; j < coor.length; j++) {
  440. var Cartesian3Posit=Cesium.Cartesian3.fromDegrees(
  441. coor[j][0],
  442. coor[j][1],
  443. coor[j][2]
  444. )
  445. that.ProjectScope.positions.push(Cartesian3Posit)
  446. positions.push(coor[j][0])
  447. positions.push(coor[j][1])
  448. }
  449. }
  450. }
  451. viewer.entities.removeById('polygon');
  452. var polygonEntity = new Cesium.Entity({
  453. id: 'polygon',
  454. polygon: {
  455. hierarchy: new Cesium.PolygonHierarchy(
  456. new Cesium.Cartesian3.fromDegreesArray(positions)
  457. ),
  458. // positions: new Cesium.Cartesian3.fromDegreesArray(positions),
  459. material: Cesium.Color.WHITE.withAlpha(0.3),
  460. outline: true,
  461. outlineColor: Cesium.Color.RED,
  462. outlineWidth: 2.0,
  463. },
  464. });
  465. viewer.entities.add(polygonEntity);
  466. viewer.flyTo(polygonEntity,{
  467. offset: {
  468. heading: Cesium.Math.toRadians(0),
  469. pitch: Cesium.Math.toRadians(-90),
  470. range: 220,
  471. },
  472. })
  473. },
  474. fakeClick(obj) {
  475. var ev = document.createEvent("MouseEvents");
  476. ev.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
  477. obj.dispatchEvent(ev);
  478. },
  479. exportRaw(name, data) {
  480. var urlObject = window.URL || window.webkitURL || window;
  481. var export_blob = new Blob([data]);
  482. var save_link = document.createElementNS("http://www.w3.org/1999/xhtml", "a")
  483. save_link.href = urlObject.createObjectURL(export_blob);
  484. save_link.download = name;
  485. this.fakeClick(save_link);
  486. } ,
  487. //自定义日照
  488. onSubmit() {
  489. this.analysis();
  490. },
  491. //大寒日
  492. onDHSubmit() {
  493. this.form.selDate = new Date(new Date().getFullYear() + "-01-20");
  494. this.datavalue = [9, 15];
  495. this.analysis();
  496. },
  497. //冬至日
  498. onDZSubmit() {
  499. // 冬至日期(东八区)的计算公式:(y×d+c)-l
  500. //   公式解读:Y=年数后2位,D=0.2422,L=闰年数,21世纪C=21.94,20世纪=22.60。
  501. //   举例说明:2088年冬至日期=[88×0.2422+21.94]-[88/4]=43-22=21,12月21日冬至。
  502. //   例外:1918年和2021年的计算结果减1日。
  503. let lastTwoDigitsOfYear = moment().format("YY");
  504. let rns = lastTwoDigitsOfYear / 4;
  505. let sjs = 21.94;
  506. let dzr = Math.floor(lastTwoDigitsOfYear * 0.2422 + sjs - rns);
  507. this.form.selDate = new Date(new Date().getFullYear() + "-12-" + dzr);
  508. this.datavalue = [9, 15];
  509. this.analysis();
  510. },
  511. //清空from
  512. resetForm() {
  513. this.ProjectScope.positions=[];
  514. this.clear();
  515. // this.clearmarkedPoints();
  516. },
  517. /**
  518. * 开始分析
  519. */
  520. analysis1() {
  521. let that = this;
  522. that.tableData = [];
  523. if (!handlerPolygon) {
  524. handlerPolygon = new Cesium.DrawHandler(
  525. viewer,
  526. Cesium.DrawMode.Point,
  527. Cesium.ClampMode.Space
  528. );
  529. }
  530. handlerPolygon.activate();
  531. handlerPolygon.activeEvt.addEventListener(function (isActive) {
  532. // if (isActive == true) {
  533. // viewer.enableCursorStyle = false;
  534. // viewer._element.style.cursor = "";
  535. // document.body.classList.add("drawCur");
  536. // } else {
  537. // viewer.enableCursorStyle = true;
  538. // document.body.classList.remove("drawCur");
  539. // }
  540. that.tooltip.setVisible(false);
  541. });
  542. handlerPolygon.movingEvt.addEventListener((windowPosition) => {
  543. that.tooltip.showAt(
  544. windowPosition,
  545. "<p>点击鼠标左键开始选择分析区域</p>"
  546. );
  547. });
  548. handlerPolygon.drawEvt.addEventListener((result) => {
  549. that.resetForm();
  550. // that.clickSunDate();
  551. that.loading = true;
  552. let scene = viewer.scene;
  553. //创建阴影查询对象
  554. if (!shadowQuery) {
  555. shadowQuery = new Cesium.ShadowQueryPoints(scene);
  556. shadowQuery.setVisibleInViewport(that.radio);
  557. shadowQuery.queryPointsEvent.addEventListener(function (e) {
  558. that.tableData = [];
  559. that.loading = false;
  560. e.forEach(function (a) {
  561. var e_cartographic = Cesium.Cartographic.fromCartesian(
  562. a.position
  563. );
  564. var e_shadowRadio = shadowQuery.getShadowRadio(e_cartographic);
  565. var e_longitude = Cesium.Math.toDegrees(e_cartographic.longitude);
  566. var e_latitude = Cesium.Math.toDegrees(e_cartographic.latitude);
  567. var e_height = e_cartographic.height;
  568. let sunForm = {};
  569. sunForm.shadowRadioText =
  570. (Number(e_shadowRadio.toFixed(2)) * 100).toFixed(2) + "%";
  571. sunForm.longitudeText = Number(e_longitude.toFixed(6));
  572. sunForm.latitudeText = Number(e_latitude.toFixed(6));
  573. sunForm.heightText = Number(e_height.toFixed(2));
  574. sunForm.dateScope =
  575. that.datavalue[0] + "时--" + that.datavalue[1] + "时";
  576. if (that.datavalue[0] != that.datavalue[1]) {
  577. sunForm.sunDate =
  578. (
  579. (that.datavalue[1] + 1 - that.datavalue[0]) *
  580. e_shadowRadio
  581. ).toFixed(2) + "小时";
  582. } else {
  583. sunForm.sunDate = "";
  584. }
  585. that.tableData.push(sunForm);
  586. });
  587. });
  588. }
  589. that.tooltip.setVisible(false);
  590. var position = result.object.position;
  591. var cartographic = Cesium.Cartographic.fromCartesian(position);
  592. var longitude = Cesium.Math.toDegrees(cartographic.longitude);
  593. var latitude = Cesium.Math.toDegrees(cartographic.latitude);
  594. var clickPoint = point([longitude, latitude]); //
  595. var buffered = buffer(clickPoint, (that.form.spacing / 2 + 1) / 1000, {
  596. units: "kilometers",
  597. });
  598. that.form.x = longitude;
  599. that.form.y = latitude;
  600. that.points = buffered.geometry.coordinates[0].flat();
  601. //设置分析对象的开始结束时间
  602. var dateValue = that.form.selDate;
  603. var st = new Date(dateValue);
  604. st.setHours(Number(that.form.startTime));
  605. shadowQuery.startTime = Cesium.JulianDate.fromDate(st);
  606. var et = new Date(dateValue);
  607. et.setHours(Number(that.form.endTime));
  608. shadowQuery.endTime = Cesium.JulianDate.fromDate(et);
  609. //设置当前时间
  610. that.setCurrentTime();
  611. shadowQuery.spacing = that.form.spacing;
  612. shadowQuery.timeInterval = that.form.timeInterval;
  613. //设置分析区域、底部高程和拉伸高度
  614. var bh = Number(that.form.bottomHeight);
  615. var eh = Number(that.form.extrudeHeight);
  616. shadowQuery.qureyRegion({
  617. position: that.points,
  618. bottom: bh,
  619. extend: eh,
  620. });
  621. shadowQuery.build();
  622. });
  623. },
  624. analysis() {
  625. let that = this;
  626. that.clear();
  627. that.tableData = [];
  628. if (that.form.startTime == that.form.endTime) {
  629. this.$message.warning("请选择一个日照时间范围区间!!!");
  630. return;
  631. }
  632. if (!handlerPolygon) {
  633. handlerPolygon = new Cesium.DrawHandler(
  634. viewer,
  635. Cesium.DrawMode.Polygon,
  636. 0
  637. );
  638. }
  639. if(that.ProjectScope.positions.length>0){
  640. that.imptAnalysis(that.ProjectScope);
  641. }else{
  642. handlerPolygon.activate();
  643. handlerPolygon.activeEvt.addEventListener(function (isActive) {
  644. // if (isActive == true) {
  645. // // viewer.enableCursorStyle = false;
  646. // // viewer._element.style.cursor = "";
  647. // document.body.classList.add("drawCur");
  648. // } else {
  649. // // viewer.enableCursorStyle = true;
  650. // document.body.classList.remove("drawCur");
  651. // }
  652. that.tooltip.setVisible(false);
  653. });
  654. handlerPolygon.movingEvt.addEventListener((windowPosition) => {
  655. that.tooltip.showAt(
  656. windowPosition,
  657. "<p>点击鼠标左键开始绘制分析区域</p>"
  658. );
  659. });
  660. handlerPolygon.drawEvt.addEventListener((result) => {
  661. // if (sdfff == null) {
  662. // sdfff = result;
  663. // } else {
  664. // result = sdfff;
  665. // }
  666. that.tooltip.setVisible(false);
  667. that.resetForm();
  668. result.object.show = false;
  669. that.imptAnalysis(result.object);
  670. });
  671. }
  672. },
  673. imptAnalysis(polygons){
  674. var that=this;
  675. var polygonsCopy=polygons;
  676. that.loading = true;
  677. let scene = viewer.scene;
  678. // that.gd = 0;
  679. //创建阴影查询对象
  680. if (!shadowQuery) {
  681. shadowQuery = new Cesium.ShadowQueryPoints(scene);
  682. shadowQuery.setVisibleInViewport(that.radio);
  683. shadowQuery.queryPointsEvent.addEventListener(function (e) {
  684. console.log(new Date().getSeconds());
  685. that.tableData = [];
  686. that.loading = false;
  687. let sdsd = [];
  688. for (var index = 0; index < e.length; index++) {
  689. const a = e[index];
  690. var e_cartographic = Cesium.Cartographic.fromCartesian(
  691. a.position
  692. );
  693. var e_shadowRadio = shadowQuery.getShadowRadio(e_cartographic);
  694. var e_longitude = Cesium.Math.toDegrees(e_cartographic.longitude);
  695. var e_latitude = Cesium.Math.toDegrees(e_cartographic.latitude);
  696. var e_height = e_cartographic.height;
  697. let sd = point([e_longitude, e_latitude]);
  698. sd.properties.value = e_shadowRadio;
  699. sdsd.push(sd);
  700. }
  701. console.log(new Date().getSeconds());
  702. let gsd = that.setIsoline(sdsd, polygonsCopy);
  703. var sssssd = [];
  704. // that.sdh = [];
  705. console.log(new Date().getSeconds());
  706. for (
  707. let featuresindex = 0;
  708. featuresindex < gsd.features.length;
  709. featuresindex++
  710. ) {
  711. var element = gsd.features[featuresindex];
  712. if (element.geometry.type == "MultiPolygon") {
  713. // continue;
  714. var polygons =
  715. that.geoJSONMultiPolygonToCesiumPolygons(element);
  716. sssssd.push(polygons);
  717. polygons.forEach((polygonItem) => {
  718. let id = uuidv4();
  719. that.eids.push(id);
  720. viewer.entities.add({
  721. id: id,
  722. polygon: {
  723. hierarchy: polygonItem,
  724. material: new Cesium.Color.fromCssColorString(
  725. element.properties.fill
  726. ).withAlpha(1),
  727. height: that.gd + 3 + featuresindex * 0.1,
  728. outline: false,
  729. // outlineColor: Cesium.Color.BLACK,
  730. // outlineWidth: 2.0,
  731. // classificationType: Cesium.ClassificationType.TERRAIN,
  732. },
  733. });
  734. });
  735. } else {
  736. // continue;
  737. for (
  738. var index = 0;
  739. index < element.geometry.coordinates.length;
  740. index++
  741. ) {
  742. var polygon = element.geometry.coordinates[index];
  743. let ps = polygon.flat();
  744. sssssd.push(ps);
  745. let id = uuidv4();
  746. that.eids.push(id);
  747. viewer.entities.add({
  748. id: id,
  749. polygon: {
  750. hierarchy: Cesium.Cartesian3.fromDegreesArray(ps),
  751. material: new Cesium.Color.fromCssColorString(
  752. element.properties.fill
  753. ).withAlpha(1),
  754. height: that.gd + 3 + featuresindex * 0.1,
  755. outline: false,
  756. // outlineColor: Cesium.Color.BLACK,
  757. // outlineWidth: 2.0,
  758. // classificationType: Cesium.ClassificationType.TERRAIN,
  759. },
  760. });
  761. }
  762. }
  763. }
  764. // var sdfsdfasf = sssssd;
  765. console.log(new Date().getSeconds());
  766. setTimeout(function () {
  767. if (shadowQuery) {
  768. shadowQuery.clear();
  769. shadowQuery.destroy();
  770. shadowQuery = null;
  771. // shadowQuery.qureyRegion({
  772. // position: [0, 0],
  773. // bottom: 0,
  774. // extend: 0,
  775. // });
  776. }
  777. }, 1000);
  778. });
  779. }
  780. let positions = that.positions;
  781. let points = that.points;
  782. // var polygons = result.object;
  783. if (!polygons) {
  784. return;
  785. }
  786. //保存当前范围,为导出准备
  787. var geoposts=[];
  788. polygons.positions.forEach((position) => {
  789. let xy = cartesian3ToWGS84(position);
  790. geoposts.push([xy.lng, xy.lat,xy.alt]);
  791. });
  792. geoposts.push(geoposts[0]);
  793. that.geopolygon=polygon([geoposts]);
  794. // handlerPolygon.polyline.show = false;
  795. positions = [].concat(polygons.positions);
  796. positions = Cesium.arrayRemoveDuplicates(
  797. positions,
  798. Cesium.Cartesian3.equalsEpsilon
  799. );
  800. //遍历多边形,取出所有点
  801. for (var i = 0, len = positions.length; i < len; i++) {
  802. //转化为经纬度,并加入至临时数组
  803. var cartographic = Cesium.Cartographic.fromCartesian(
  804. polygons.positions[i]
  805. );
  806. var longitude = Cesium.Math.toDegrees(cartographic.longitude);
  807. var latitude = Cesium.Math.toDegrees(cartographic.latitude);
  808. if (i == 0) {
  809. if (that.gd == 0) {
  810. that.gd = Math.ceil(cartographic.height);
  811. }
  812. }
  813. points.push(longitude);
  814. points.push(latitude);
  815. }
  816. //设置分析对象的开始结束时间
  817. var dateValue = that.form.selDate;
  818. var st = new Date(dateValue);
  819. st.setHours(Number(that.form.startTime));
  820. shadowQuery.startTime = Cesium.JulianDate.fromDate(st);
  821. var et = new Date(dateValue);
  822. let endTime = 0;
  823. if (that.form.startTime != that.form.endTime) {
  824. endTime = that.form.endTime;
  825. } else {
  826. endTime = that.form.endTime;
  827. }
  828. et.setHours(Number(endTime));
  829. shadowQuery.endTime = Cesium.JulianDate.fromDate(et);
  830. //设置当前时间
  831. that.setCurrentTime();
  832. //设置根据面积计算间隔
  833. var trufpolygons = [];
  834. for (let pindex = 0; pindex < polygons.positions.length; pindex++) {
  835. var pposition = polygons.positions[pindex];
  836. var e_cartographic = Cesium.Cartographic.fromCartesian(pposition);
  837. var e_longitude = Cesium.Math.toDegrees(e_cartographic.longitude);
  838. var e_latitude = Cesium.Math.toDegrees(e_cartographic.latitude);
  839. trufpolygons.push([e_longitude, e_latitude]);
  840. }
  841. if (trufpolygons[0] != trufpolygons[trufpolygons.length - 1]) {
  842. trufpolygons.push(trufpolygons[0]);
  843. }
  844. var polygonPs = polygon([trufpolygons]);
  845. let areaPs = area(polygonPs);
  846. if (areaPs <= 20000) {
  847. that.form.spacing = 10;
  848. } else if (areaPs <= 60000) {
  849. that.form.spacing = 10;
  850. } else if (areaPs <= 100000) {
  851. that.form.spacing = 10;
  852. } else {
  853. that.form.spacing = 10;
  854. }
  855. shadowQuery.spacing = that.form.spacing;
  856. shadowQuery.timeInterval = that.form.timeInterval;
  857. //设置分析区域、底部高程和拉伸高度
  858. var bh = Number(that.gd + 1);
  859. var eh = Number(2);
  860. if (areaPs < 250000) {
  861. shadowQuery.qureyRegion({
  862. position: that.points,
  863. bottom: bh,
  864. extend: eh,
  865. });
  866. shadowQuery.build();
  867. // that.resetForm();
  868. } else {
  869. that.loading = false;
  870. this.$message({
  871. dangerouslyUseHTMLString: true,
  872. message:
  873. "框选范围过大,为确保分析精度,建议以小区为单位<br />请选取小于250000平方米的区域!!!",
  874. type: "warning",
  875. });
  876. if (shadowQuery) {
  877. shadowQuery.clear();
  878. shadowQuery.destroy();
  879. shadowQuery = null;
  880. // shadowQuery.qureyRegion({
  881. // position: [0, 0],
  882. // bottom: 0,
  883. // extend: 0,
  884. // });
  885. }
  886. }
  887. },
  888. ExportResult() {
  889. let that = this;
  890. let entitys = [];
  891. that.eids.forEach((id) => {
  892. let entity = viewer.entities.getById(id);
  893. if (entity) {
  894. entitys.push(entity);
  895. }
  896. });
  897. let box = that.squarePolygon(entitys);
  898. viewer.camera.flyTo({
  899. destination: Cesium.Rectangle.fromDegrees(
  900. box[0][0] + 0.0002,
  901. box[0][1] - 0.0002,
  902. box[2][0] - 0.0002,
  903. box[2][1] + 0.0002
  904. ),
  905. });
  906. setTimeout(function () {
  907. var promise = scene.outputSceneToFile();
  908. Cesium.when(promise, function (base64data) {
  909. that.download(base64data);
  910. });
  911. }, 4000);
  912. },
  913. /**
  914. * 根据图片生成画布
  915. */
  916. convertImageToCanvas(image) {
  917. var canvas = document.createElement("canvas");
  918. canvas.width = image.width;
  919. canvas.height = image.height;
  920. var ctx = canvas.getContext("2d");
  921. ctx.drawImage(image, 0, 0);
  922. this.drawLegends(canvas, ctx);
  923. return canvas;
  924. },
  925. // 绘制图例
  926. drawLegends(canvas, ctx) {
  927. var legends = this.sdh;
  928. var padding = 10; // 图例与边缘的间距
  929. var lineHeight = 30; // 每行图例的高度
  930. var labW = 120;
  931. var x = canvas.width - padding - labW; // 图例的起始X坐标
  932. var y = canvas.height - legends.length * lineHeight - padding; // 图例的起始Y坐标
  933. // 绘制颜色块
  934. ctx.fillStyle = "#ffffff";
  935. ctx.fillRect(
  936. x - padding,
  937. y - padding,
  938. canvas.width - x + padding,
  939. canvas.height - y + padding
  940. );
  941. legends.forEach(function (legend, index) {
  942. // 绘制文本
  943. ctx.fillStyle = "black";
  944. ctx.fillText(
  945. legend.scS + "小时",
  946. x,
  947. y + index * lineHeight + lineHeight / 2
  948. );
  949. // 绘制颜色块
  950. ctx.fillStyle = legend.fill;
  951. ctx.fillRect(
  952. x + (labW / 3) * 2,
  953. y + index * lineHeight,
  954. 30,
  955. lineHeight
  956. );
  957. });
  958. },
  959. /**
  960. * 下载图片
  961. */
  962. download(base64data) {
  963. let that = this;
  964. var image = new Image();
  965. image.src = base64data;
  966. image.onload = function () {
  967. var canvas = that.convertImageToCanvas(image);
  968. var url = canvas.toDataURL("image/jpeg");
  969. var a = document.createElement("a");
  970. var event = new MouseEvent("click");
  971. a.download = new Date().getTime() + ".jpg"; // 指定下载图片的名称
  972. a.href = url;
  973. a.dispatchEvent(event); // 触发超链接的点击事件
  974. };
  975. },
  976. clear() {
  977. viewer.entities.removeById('polygon');
  978. this.geopolygon=null;
  979. // viewer.entities.removeAll();
  980. // this.form.x = 0;
  981. // this.form.y = 0;
  982. this.tableData = [];
  983. if (handlerPolygon) {
  984. handlerPolygon.clear();
  985. handlerPolygon.deactivate();
  986. handlerPolygon = null;
  987. }
  988. this.tooltip.setVisible(false);
  989. if (shadowQuery) {
  990. shadowQuery.clear();
  991. shadowQuery.destroy();
  992. shadowQuery = null;
  993. // shadowQuery.qureyRegion({
  994. // position: [0, 0],
  995. // bottom: 0,
  996. // extend: 0,
  997. // });
  998. }
  999. this.positions = [];
  1000. this.points = [];
  1001. for (let i = 0; i < this.eids.length; i++) {
  1002. viewer.entities.removeById(this.eids[i]);
  1003. }
  1004. // this.sdh = [];
  1005. this.eids = [];
  1006. },
  1007. //结束时日照阴影
  1008. setCurrentTime() {
  1009. var et = this.form.selDate;
  1010. et.setHours(Number(this.form.endTime));
  1011. viewer.clock.currentTime = Cesium.JulianDate.fromDate(et);
  1012. viewer.clock.multiplier = 1;
  1013. viewer.clock.shouldAnimate = false;
  1014. },
  1015. /**
  1016. * 执行日照动画
  1017. */
  1018. statrSunlight() {
  1019. var dateVal = this.form.selDate;
  1020. var startTime = new Date(dateVal);
  1021. var shour = Number(this.form.startTime);
  1022. var ehour = Number(this.form.endTime);
  1023. if (shour > ehour) {
  1024. return;
  1025. }
  1026. var nTimer = 0.0;
  1027. if (this.nIntervId) {
  1028. clearInterval(this.nIntervId);
  1029. }
  1030. debugger;
  1031. this.nIntervId = setInterval(function () {
  1032. if (shour < ehour) {
  1033. startTime.setHours(shour);
  1034. startTime.setMinutes(nTimer);
  1035. viewer.clock.currentTime = Cesium.JulianDate.fromDate(startTime);
  1036. nTimer += 10.0;
  1037. if (nTimer > 60.0) {
  1038. shour += 1.0;
  1039. nTimer = 0.0;
  1040. }
  1041. } else {
  1042. clearInterval(this.nIntervId);
  1043. }
  1044. }, this.Intervalshijian * 10);
  1045. },
  1046. //当前日照效果
  1047. dqSunlight() {
  1048. viewer.clock.currentTime = Cesium.JulianDate.fromDate(new Date());
  1049. viewer.clock.multiplier = 1;
  1050. viewer.clock.shouldAnimate = true;
  1051. },
  1052. //日照列表行被点击
  1053. rowClick(row, column, event) {
  1054. this.clearmarkedPoints();
  1055. var markedPoint = viewer.entities.add(
  1056. new Cesium.Entity({
  1057. point: new Cesium.PointGraphics({
  1058. color: new Cesium.Color(1, 1, 0, 0.5),
  1059. pixelSize: 15,
  1060. }),
  1061. position: Cesium.Cartesian3.fromDegrees(
  1062. row.longitudeText,
  1063. row.latitudeText,
  1064. row.heightText
  1065. ),
  1066. })
  1067. );
  1068. markedPoints.push(markedPoint);
  1069. },
  1070. //清除点击的黄色圆圈
  1071. clearmarkedPoints() {
  1072. for (let i = 0; i < markedPoints.length; i++) {
  1073. viewer.entities.remove(markedPoints[i]);
  1074. }
  1075. markedPoints = [];
  1076. },
  1077. // x或y变化触发
  1078. XYChange() {
  1079. if (!shadowQuery) {
  1080. return;
  1081. }
  1082. this.loading = true;
  1083. let that = this;
  1084. var clickPoint = point([that.form.x, that.form.y]); //
  1085. var buffered = buffer(clickPoint, (that.form.spacing / 2 + 1) / 1000, {
  1086. units: "kilometers",
  1087. });
  1088. that.points = buffered.geometry.coordinates[0].flat();
  1089. //设置分析区域、底部高程和拉伸高度
  1090. var bh = Number(that.form.bottomHeight);
  1091. var eh = Number(that.form.extrudeHeight);
  1092. shadowQuery.qureyRegion({
  1093. position: that.points,
  1094. bottom: bh,
  1095. extend: eh,
  1096. });
  1097. shadowQuery.build();
  1098. },
  1099. // 时间范围变化触发
  1100. datavalueChange(val) {
  1101. if (val[0] == val[1]) {
  1102. this.form.timeInterval = 1;
  1103. } else {
  1104. this.form.timeInterval = 60;
  1105. }
  1106. this.form.startTime = val[0];
  1107. this.form.endTime = val[1];
  1108. },
  1109. setIsoline(turfPoints, polygons) {
  1110. //转换面
  1111. var trufpolygons = [];
  1112. for (var pindex = 0; pindex < polygons.positions.length; pindex++) {
  1113. var pposition = polygons.positions[pindex];
  1114. var e_cartographic = Cesium.Cartographic.fromCartesian(pposition);
  1115. var e_longitude = Cesium.Math.toDegrees(e_cartographic.longitude);
  1116. var e_latitude = Cesium.Math.toDegrees(e_cartographic.latitude);
  1117. trufpolygons.push([e_longitude, e_latitude]);
  1118. }
  1119. if (trufpolygons[0] != trufpolygons[trufpolygons.length - 1]) {
  1120. trufpolygons.push(trufpolygons[0]);
  1121. }
  1122. var polygonPs = polygon([trufpolygons]);
  1123. var sunriseDate = SunriseSunsetJS.getSunrise(
  1124. 18.31723463241332,
  1125. 109.5112252162011,
  1126. this.form.selDate
  1127. );
  1128. var sunsetdate = SunriseSunsetJS.getSunset(
  1129. 18.31723463241332,
  1130. 109.5112252162011,
  1131. this.form.selDate
  1132. );
  1133. //参与计算的日出日落时间
  1134. var jssunriseHours = 0;
  1135. var jssunsetHours = 0;
  1136. //日出时间
  1137. var sunriseHours = sunriseDate.getHours() + sunriseDate.getMinutes() / 60;
  1138. //日落时间
  1139. var sunsetHours = sunsetdate.getHours() + sunsetdate.getMinutes() / 60;
  1140. if (this.datavalue[0] > sunriseHours) jssunriseHours = this.datavalue[0];
  1141. else jssunriseHours = sunriseHours;
  1142. if (this.datavalue[1] > sunsetHours) jssunsetHours = sunsetHours;
  1143. else jssunsetHours = this.datavalue[1];
  1144. //赋值+计算小时数
  1145. for (var index = 0; index < turfPoints.length; index++) {
  1146. var element = turfPoints[index];
  1147. console.log(
  1148. jssunsetHours -
  1149. jssunriseHours +
  1150. "*" +
  1151. element.properties.value +
  1152. "==" +
  1153. (jssunsetHours - jssunriseHours) * element.properties.value
  1154. );
  1155. var time = (jssunsetHours - jssunriseHours) * element.properties.value;
  1156. // if (time > 5) {
  1157. // element["value"] = 5;
  1158. // element.properties.value = 5;
  1159. // } else {
  1160. element["value"] = time;
  1161. element.properties.value = time;
  1162. // }
  1163. }
  1164. // 使用turf.envelope计算包含所有点的最小矩形多边形
  1165. var envelopeP = envelope(featureCollection(turfPoints));
  1166. // var minX,max
  1167. // turfPoints.forEach()
  1168. // 从envelope多边形中提取bbox坐标
  1169. let dd1 = envelopeP.bbox;
  1170. // let dd1 = [107, 36, 180, 38];
  1171. // let dd1 = bbox(sdsd);
  1172. let points1 = {
  1173. type: "FeatureCollection",
  1174. features: turfPoints,
  1175. };
  1176. let levelv = [0, 1, 2, 3, 4, 5];
  1177. let colors = [
  1178. { fill: "#313695" },
  1179. { fill: "#1E90A8" },
  1180. { fill: "#00B457" },
  1181. { fill: "#B7FF01" },
  1182. { fill: "#F2A705" },
  1183. { fill: "#FF0000" },
  1184. { fill: "#FF0000" },
  1185. ];
  1186. // if (czsj.points1 == null) {
  1187. // czsj.points1 = points1;
  1188. // czsj.dd1 = dd1;
  1189. // } else {
  1190. // points1 = czsj.points1;
  1191. // dd1 = czsj.dd1;
  1192. // }
  1193. let kriging_contours = getVectorContour(
  1194. points1,
  1195. "value",
  1196. { model: "spherical", sigma2: 0, alpha: 50 },
  1197. levelv,
  1198. dd1
  1199. );
  1200. function hotcolor(d) {
  1201. let index = levelv.findIndex((item) => item >= d);
  1202. if (index > -1 && index < 6) {
  1203. return colors[index].fill;
  1204. } else {
  1205. return colors[colors.length - 1].fill;
  1206. }
  1207. }
  1208. function sortArea(a, b) {
  1209. return area(b) - area(a);
  1210. }
  1211. //按照面积对图层进行排序,规避turf的一个bug
  1212. kriging_contours.features.sort(sortArea);
  1213. //后面使用要求输入的参数为Feature<Polygon>,而turf.isobands的是 MultiPolygon,需
  1214. var boundaries = flatten(envelopeP); //行政边界
  1215. kriging_contours = flatten(kriging_contours); //等值面边界
  1216. //console.log('kriging_contours:'+JSON.stringify(kriging_contours));
  1217. //根据行政边界裁剪图形,
  1218. //现在放大一些区域边界还是没有充满 后面可以封装成一个插件,在源码里面进行canvas clip 剪辑只显示的geojson区域,其余的栅格部分不显示
  1219. let features = []; //裁剪后的结果集
  1220. // kriging_contours.features.forEach(function (feature1) {
  1221. // boundaries.features.forEach(function (feature2) {
  1222. // let intersection = null;
  1223. // try {
  1224. // intersection = intersect(feature1, feature2);
  1225. // } catch (e) {
  1226. // try {
  1227. // //色斑图绘制之后,可能会生成一些非法 Polygon
  1228. // //解决的方法通常就是做一次 turf.buffer() 操作,这样可以把一些小的碎片 Polygon 清理掉。
  1229. // feature1 = buffer(feature1, 0);
  1230. // intersection = intersect(feature1, feature2);
  1231. // } catch (e) {
  1232. // intersection = feature1; //实在裁剪不了就不裁剪了,根据业务需求自行决定
  1233. // }
  1234. // }
  1235. // if (intersection != null) {
  1236. // intersection.properties = feature1.properties;
  1237. // // intersection.properties.fill = hotcolor(feature1.properties.value);
  1238. // intersection.id = (Math.random() * 100000).toFixed(0);
  1239. // features.push(intersection);
  1240. // }
  1241. // });
  1242. // });
  1243. var polygonPs = polygon([trufpolygons]);
  1244. kriging_contours.features.forEach(function (feature1) {
  1245. // polygonPs.features.forEach(function (feature2) {
  1246. let inFeature = null;
  1247. try {
  1248. inFeature = intersect(feature1, polygonPs);
  1249. } catch (e) {
  1250. try {
  1251. //色斑图绘制之后,可能会生成一些非法 Polygon
  1252. //解决的方法通常就是做一次 turf.buffer() 操作,这样可以把一些小的碎片 Polygon 清理掉。
  1253. feature1 = buffer(feature1, 0);
  1254. inFeature = intersect(feature1, polygonPs);
  1255. } catch (e) {
  1256. inFeature = feature1; //实在裁剪不了就不裁剪了,根据业务需求自行决定
  1257. }
  1258. }
  1259. if (inFeature != null) {
  1260. inFeature.properties = feature1.properties;
  1261. // intersection.properties.fill = hotcolor(feature1.properties.value);
  1262. inFeature.id = (Math.random() * 100000).toFixed(0);
  1263. features.push(inFeature);
  1264. }
  1265. // });
  1266. });
  1267. let intersection = featureCollection(features);
  1268. intersection.features.forEach((element) => {
  1269. element.properties.fill = hotcolor(element.properties.contour_value);
  1270. });
  1271. // function zdx(a, b) {
  1272. // return a.properties.contour_value - b.properties.contour_value;
  1273. // }
  1274. // intersection.features.sort(zdx);
  1275. // let features = []; //裁剪后的结果集
  1276. // intersection.features = features;
  1277. return intersection;
  1278. },
  1279. /**
  1280. * @property {Array} features 关键点集合
  1281. */
  1282. setIsoline1111(features) {
  1283. // 准备工作,创建 options
  1284. // const breaks = [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1];
  1285. const breaks = [0];
  1286. for (
  1287. var index = 1;
  1288. index < this.datavalue[1] - this.datavalue[0] + 1;
  1289. index++
  1290. ) {
  1291. breaks.push(index * (1 / (this.datavalue[1] - this.datavalue[0])));
  1292. }
  1293. // breaks.push(2);
  1294. let breaksProperties = [];
  1295. for (var index = 0; index < breaks.length; index++) {
  1296. // let time1 = Math.ceil(
  1297. // (this.datavalue[1] - this.datavalue[0]) * breaks[index]
  1298. // );
  1299. let time1 = (this.datavalue[1] - this.datavalue[0]) * breaks[index];
  1300. switch (time1) {
  1301. case 0:
  1302. breaksProperties.push(this.sdh[0]);
  1303. break;
  1304. case 1:
  1305. breaksProperties.push(this.sdh[1]);
  1306. break;
  1307. case 2:
  1308. breaksProperties.push(this.sdh[2]);
  1309. break;
  1310. case 3:
  1311. breaksProperties.push(this.sdh[3]);
  1312. break;
  1313. case 4:
  1314. breaksProperties.push(this.sdh[4]);
  1315. break;
  1316. default:
  1317. breaksProperties.push(this.sdh[5]);
  1318. break;
  1319. }
  1320. }
  1321. const interpolateOptions = {
  1322. gridType: "points",
  1323. property: "value",
  1324. units: "degrees",
  1325. weight: 50,
  1326. };
  1327. const isobandsOptions = {
  1328. zProperty: "value",
  1329. // commonProperties: {
  1330. // "fill-opacity": 0.5,
  1331. // },
  1332. breaksProperties: breaksProperties,
  1333. };
  1334. // 准备工作结束
  1335. // 将散点合并成要素集
  1336. const points = featureCollection(features);
  1337. // 使用反向距离加权(IDW)方法进行运算
  1338. const grid = interpolate(
  1339. points,
  1340. this.form.spacing * 0.00001,
  1341. interpolateOptions
  1342. );
  1343. // 根据参与分级的属性和分级的数组计算出等值面
  1344. const isobandsData = isobands(grid, breaks, isobandsOptions);
  1345. const intersection = featureCollection(isobandsData.features);
  1346. return intersection;
  1347. },
  1348. /**
  1349. * 计算边界
  1350. */
  1351. squarePolygon(entitys) {
  1352. const polygons = [
  1353. /* ... 多边形数组 ... */
  1354. ];
  1355. entitys.forEach((entity) => {
  1356. let positions = entity.polygon.hierarchy.getValue().positions;
  1357. let posts = [];
  1358. positions.forEach((position) => {
  1359. let xy = cartesian3ToWGS84(position);
  1360. posts.push([xy.lng, xy.lat]);
  1361. });
  1362. let thispolygon = polygon([posts]);
  1363. polygons.push(thispolygon);
  1364. });
  1365. // 初始化边界框变量
  1366. let minX = Infinity,
  1367. minY = Infinity,
  1368. maxX = -Infinity,
  1369. maxY = -Infinity;
  1370. // 遍历每个多边形,计算其边界框,并更新最小/最大坐标
  1371. polygons.forEach((polygon) => {
  1372. const thisbbox = bbox(polygon);
  1373. minX = Math.min(minX, thisbbox[0]);
  1374. minY = Math.min(minY, thisbbox[1]);
  1375. maxX = Math.max(maxX, thisbbox[2]);
  1376. maxY = Math.max(maxY, thisbbox[3]);
  1377. });
  1378. // 计算正方形的边长
  1379. const sideLength = Math.max(maxX - minX, maxY - minY);
  1380. // 创建正方形的四个角点
  1381. const squareCoords = [
  1382. [minX, minY],
  1383. [minX + sideLength, minY],
  1384. [minX + sideLength, minY + sideLength],
  1385. [minX, minY + sideLength],
  1386. [minX, minY], // 闭合多边形
  1387. ];
  1388. // // 使用Turf.js创建正方形多边形
  1389. // const squarePolygon = polygon([squareCoords]);
  1390. return squareCoords;
  1391. },
  1392. geoJSONMultiPolygonToCesiumPolygons11(multiPolygon) {
  1393. let polygonsHierarchy = [];
  1394. multiPolygon.geometry.coordinates.forEach((polygon) => {
  1395. let rings = [];
  1396. polygon.forEach((ring) => {
  1397. let cartesianPoints = ring.map((coordinates) => {
  1398. return Cesium.Cartesian3.fromDegrees(
  1399. coordinates[0],
  1400. coordinates[1]
  1401. );
  1402. });
  1403. rings.push(cartesianPoints);
  1404. });
  1405. polygonsHierarchy.push(rings);
  1406. });
  1407. return polygonsHierarchy;
  1408. },
  1409. geoJSONMultiPolygonToCesiumPolygons(multiPolygon) {
  1410. // 假设multiPolygon是一个有效的多边形数组
  1411. let polygonsHierarchy = [];
  1412. // {
  1413. // // Cesium.PolygonHierarchy
  1414. // positions: point3ds[0],
  1415. // holes: holes, // Cesium.PolygonHierarchy 数组
  1416. // }
  1417. multiPolygon.geometry.coordinates.forEach((polygon) => {
  1418. var polygons = { positions: [] };
  1419. if (polygon.length > 1) {
  1420. polygons.holes = [];
  1421. }
  1422. polygon.forEach((element, i) => {
  1423. if (i == 0) {
  1424. polygons.positions = Cesium.Cartesian3.fromDegreesArray(
  1425. element.flat()
  1426. );
  1427. } else {
  1428. polygons.holes.push({
  1429. positions: Cesium.Cartesian3.fromDegreesArray(element.flat()),
  1430. });
  1431. }
  1432. });
  1433. // 创建PolygonHierarchy结构
  1434. polygonsHierarchy.push(polygons);
  1435. });
  1436. return polygonsHierarchy;
  1437. },
  1438. },
  1439. watch: {
  1440. "form.selDate": function (newValue) {
  1441. if (!shadowQuery) {
  1442. return;
  1443. }
  1444. this.loading = true;
  1445. let st = new Date(newValue);
  1446. st.setHours(this.form.startTime);
  1447. let et = new Date(newValue);
  1448. et.setHours(this.form.endTime);
  1449. shadowQuery.startTime = Cesium.JulianDate.fromDate(st);
  1450. shadowQuery.endTime = Cesium.JulianDate.fromDate(et);
  1451. },
  1452. "form.startTime": function (newValue) {
  1453. if (!shadowQuery) {
  1454. return;
  1455. }
  1456. this.loading = true;
  1457. let thisdate = new Date(this.form.selDate);
  1458. var st = thisdate;
  1459. st.setHours(Number(newValue));
  1460. shadowQuery.startTime = Cesium.JulianDate.fromDate(st);
  1461. },
  1462. "form.endTime": function (newValue) {
  1463. if (!shadowQuery) {
  1464. return;
  1465. }
  1466. this.loading = true;
  1467. let thisdate = new Date(this.form.selDate);
  1468. var et = thisdate;
  1469. et.setHours(Number(newValue));
  1470. shadowQuery.endTime = Cesium.JulianDate.fromDate(et);
  1471. },
  1472. "form.timeInterval": function (newValue) {
  1473. if (!shadowQuery) {
  1474. return;
  1475. }
  1476. this.loading = true;
  1477. shadowQuery.timeInterval = Number(newValue);
  1478. shadowQuery.build();
  1479. },
  1480. "form.spacing": function (newValue) {
  1481. if (!shadowQuery) {
  1482. return;
  1483. }
  1484. this.loading = true;
  1485. shadowQuery.spacing = Number(newValue);
  1486. shadowQuery.build();
  1487. },
  1488. "form.bottomHeight": function (newValue) {
  1489. if (!shadowQuery) {
  1490. return;
  1491. }
  1492. this.loading = true;
  1493. var bh = Number(newValue);
  1494. var eh = Number(this.form.extrudeHeight);
  1495. shadowQuery.qureyRegion({
  1496. position: this.points,
  1497. bottom: bh,
  1498. extend: eh,
  1499. });
  1500. shadowQuery.build();
  1501. },
  1502. "form.extrudeHeight": function (newValue) {
  1503. if (!shadowQuery) {
  1504. return;
  1505. }
  1506. this.loading = true;
  1507. var bh = Number(this.form.bottomHeight);
  1508. var eh = Number(newValue);
  1509. shadowQuery.qureyRegion({
  1510. position: this.points,
  1511. bottom: bh,
  1512. extend: eh,
  1513. });
  1514. shadowQuery.build();
  1515. },
  1516. },
  1517. beforeDestroy() {
  1518. document.oncontextmenu = null;
  1519. this.clear();
  1520. this.clearmarkedPoints();
  1521. if (shadowQuery) {
  1522. shadowQuery.clear();
  1523. shadowQuery.destroy();
  1524. shadowQuery = null;
  1525. }
  1526. if (handlerPolygon) {
  1527. handlerPolygon.deactivate();
  1528. }
  1529. handlerPolygon = undefined;
  1530. this.dqSunlight();
  1531. let scene = viewer.scene;
  1532. layers = scene.layers.layerQueue;
  1533. viewer.shadows = this.RecordInitializationScene.shadows;
  1534. //图层模型还原阴影
  1535. for (let i = 0; i < layers.length; i++) {
  1536. var shadowType = this.RecordInitializationScene.layersshadowType.find(
  1537. (c) => c.name == layers[i].name
  1538. );
  1539. if (shadowType) {
  1540. if (layers[i].shadowType != shadowType.shadowType) {
  1541. layers[i].shadowType = shadowType.shadowType;
  1542. layers[i].refresh();
  1543. }
  1544. }
  1545. }
  1546. },
  1547. };
  1548. </script>
  1549. <style lang="scss">
  1550. @import "@/../../zt.scss";
  1551. </style>
  1552. <style lang="scss" scoped>
  1553. .el-card {
  1554. border: 0px solid #02a7f0;
  1555. }
  1556. .el-form-item {
  1557. margin-bottom: 0;
  1558. }
  1559. .slider_padding {
  1560. padding: 0rem 0.5rem;
  1561. }
  1562. </style>