当前位置:   article > 正文

Cesium 简单航飞线路规划,模拟飞行扫描效果_三维航线网络插件cesium

三维航线网络插件cesium

目录

效果

源码

使用注意

追加说明

参考文档


效果

 动图:

源码

vue2+elementUI+cesium1.97,功能源码已整理到单个文件中。单独运行需要引入cesium、elementUI和turf.js,原理看注释基本都能看懂。上源码:

  1. <template>
  2. <!-- 航线规划 -->
  3. <div class="uvaRoutePlanBox" :class="{ hide: !isShow, show: isShow }">
  4. <div id="cesiumContainerBox" />
  5. <div
  6. id="toolTip"
  7. style="display: none;pointer-events: none;position: fixed;background: rgba(0,0,0,0.5);z-index: 1000;opacity: 0.8;border-radius: 4px;padding: 4px 8px;white-space: nowrap;font-family:黑体;color:white;font-weight: bolder;font-size: 14px;"
  8. />
  9. <div class="body">
  10. <div class="form-item">
  11. <span class="form-label">
  12. 航飞区域
  13. </span>
  14. <div class="form-connect">
  15. <el-button type="primary" style="width:130px;" @click="drawPoly">
  16. 绘制
  17. </el-button>
  18. </div>
  19. </div>
  20. <div class="form-item">
  21. <span class="form-label">航飞间距</span>
  22. <div class="form-connect">
  23. <el-input-number
  24. v-model="hfDistance"
  25. controls-position="right"
  26. :min="10"
  27. :step="10"
  28. @change="distanceHandleChange"
  29. />
  30. </div>
  31. </div>
  32. <div class="form-item">
  33. <div class="form-connect">
  34. <el-button type="primary" @click="beginCalc">
  35. 开始计算
  36. </el-button>
  37. <el-button type="success" @click="moniFly">
  38. 模拟飞行
  39. </el-button>
  40. <el-button type="danger" @click="cleanEntity">清除</el-button>
  41. </div>
  42. </div>
  43. </div>
  44. </div>
  45. </template>
  46. <script>
  47. import * as Cesium from '@assets/Cesium'
  48. import * as turf from '@turf/turf'
  49. var polyArr = [] // 面数据
  50. var jdArrs = [] // 交点集合
  51. export default {
  52. name: 'UvaRoutePlan',
  53. components: {},
  54. props: [],
  55. data() {
  56. return { isShow: true, hfDistance: 100, isFly: false }
  57. },
  58. watch: {},
  59. created() {
  60. this.$nextTick(function() {
  61. this.startInit()
  62. })
  63. },
  64. mounted() {},
  65. methods: {
  66. startInit() {
  67. const key =
  68. '你的token'
  69. Cesium.Ion.defaultAccessToken = key
  70. var viewer = new Cesium.Viewer('cesiumContainerBox', {
  71. imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
  72. url:
  73. 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
  74. }),
  75. geocoder: true,
  76. homeButton: true,
  77. sceneModePicker: true,
  78. baseLayerPicker: true,
  79. navigationHelpButton: true,
  80. shouldAnimate: true,
  81. animation: true,
  82. timeline: true,
  83. fullscreenButton: true,
  84. vrButton: true,
  85. // 关闭点选出现的提示框
  86. selectionIndicator: false,
  87. infoBox: false
  88. })
  89. viewer._cesiumWidget._creditContainer.style.display = 'none' // 隐藏版权
  90. viewer.camera.flyTo({
  91. destination: Cesium.Cartesian3.fromDegrees(
  92. 113.6440552299206,
  93. 34.78411814959118,
  94. 2000
  95. ),
  96. orientation: {
  97. heading: Cesium.Math.toRadians(0.0), // 左右方向
  98. pitch: Cesium.Math.toRadians(-90.0), // 上下方向
  99. roll: Cesium.Math.toRadians(0) // 镜头(屏幕)到定位目标点(实体)的距离
  100. },
  101. duration: 3 // 执行定位动画的时间
  102. })
  103. window.viewer = viewer
  104. },
  105. endClose() {
  106. this.cleanEntity()
  107. },
  108. // 画航飞区域
  109. drawPoly() {
  110. var viewer = window.viewer
  111. this.cleanEntity()
  112. var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
  113. // 鼠标事件
  114. handler = new Cesium.ScreenSpaceEventHandler(
  115. viewer.scene._imageryLayerCollection
  116. )
  117. polyArr = []
  118. var positions = []
  119. var tempPoints = []
  120. var polygon = null
  121. var tooltip = document.getElementById('toolTip')
  122. var cartesian = null
  123. // 鼠标移动事件
  124. handler.setInputAction(function(movement) {
  125. tooltip.style.left = movement.endPosition.x + 3 + 'px'
  126. tooltip.style.top = movement.endPosition.y - 25 + 'px'
  127. tooltip.innerHTML = '<p>单击开始,右击结束</p>'
  128. const ray = viewer.camera.getPickRay(movement.endPosition)
  129. cartesian = viewer.scene.globe.pick(ray, viewer.scene)
  130. if (positions.length >= 2) {
  131. if (!Cesium.defined(polygon)) {
  132. polygon = new PolygonPrimitive(positions)
  133. } else {
  134. positions.pop()
  135. positions.push(cartesian)
  136. }
  137. }
  138. }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
  139. // 左击鼠标事件
  140. handler.setInputAction(function(movement) {
  141. tooltip.style.display = 'block'
  142. tooltip.style.left = movement.position.x + 3 + 'px'
  143. tooltip.style.top = movement.position.y - 25 + 'px'
  144. tooltip.innerHTML = '<p>单击开始,右击结束</p>'
  145. const ray = viewer.camera.getPickRay(movement.position)
  146. cartesian = viewer.scene.globe.pick(ray, viewer.scene)
  147. if (positions.length === 0) {
  148. positions.push(cartesian.clone())
  149. }
  150. // positions.pop();
  151. positions.push(cartesian)
  152. // 在三维场景中添加点
  153. var cartographic = Cesium.Cartographic.fromCartesian(
  154. positions[positions.length - 1]
  155. )
  156. var longitudeString = Cesium.Math.toDegrees(cartographic.longitude)
  157. var latitudeString = Cesium.Math.toDegrees(cartographic.latitude)
  158. var heightString = cartographic.height
  159. tempPoints.push({
  160. lon: longitudeString,
  161. lat: latitudeString,
  162. hei: heightString
  163. })
  164. }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
  165. // 右击鼠标事件
  166. handler.setInputAction(function() {
  167. handler.destroy()
  168. tooltip.style.display = 'none'
  169. positions.pop()
  170. polyArr = positions
  171. }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
  172. var PolygonPrimitive = (function() {
  173. function _(positions) {
  174. this.options = {
  175. name: 'uav-poly',
  176. polygon: {
  177. hierarchy: [],
  178. // perPositionHeight : true,
  179. material: Cesium.Color.fromCssColorString('#fafafa').withAlpha(
  180. 0.5
  181. )
  182. }
  183. }
  184. this.hierarchy = { positions }
  185. this._init()
  186. }
  187. _.prototype._init = function() {
  188. var _self = this
  189. var _update = function() {
  190. return _self.hierarchy
  191. }
  192. // 实时更新polygon.hierarchy
  193. this.options.polygon.hierarchy = new Cesium.CallbackProperty(
  194. _update,
  195. false
  196. )
  197. viewer.entities.add(this.options)
  198. }
  199. return _
  200. })()
  201. },
  202. // 开始计算
  203. beginCalc() {
  204. if (polyArr.length === 0) {
  205. this.$message.warning('未检测到航飞区域')
  206. return
  207. }
  208. var viewer = window.viewer
  209. // 清除之前计算结果entity
  210. this.cesium.removeEntityLikeName(viewer, 'uav-tmp')
  211. var geodesic = Cesium.BoundingRectangle.fromPoints(polyArr) // 外接矩形获取
  212. var rectangle = Cesium.Rectangle.fromCartesianArray(polyArr) // 外接矩形获取
  213. // 把面拆分成线并转换为经纬度格式存储
  214. var polyLines = []
  215. polyArr.map((res, index) => {
  216. var tmp = []
  217. var ellipsoid = viewer.scene.globe.ellipsoid
  218. var cartesian3 = new Cesium.Cartesian3(res.x, res.y, res.z)
  219. var cartographic = ellipsoid.cartesianToCartographic(cartesian3)
  220. var cartesian31 = null
  221. var cartographic1 = null
  222. if (index === polyArr.length - 1) {
  223. // 最后一个点连接顶点
  224. cartesian31 = new Cesium.Cartesian3(
  225. polyArr[0].x,
  226. polyArr[0].y,
  227. polyArr[0].z
  228. )
  229. cartographic1 = ellipsoid.cartesianToCartographic(cartesian31)
  230. tmp.push([
  231. [
  232. Cesium.Math.toDegrees(cartographic.longitude),
  233. Cesium.Math.toDegrees(cartographic.latitude)
  234. ],
  235. [
  236. Cesium.Math.toDegrees(cartographic1.longitude),
  237. Cesium.Math.toDegrees(cartographic1.latitude)
  238. ]
  239. ])
  240. } else {
  241. cartesian31 = new Cesium.Cartesian3(
  242. polyArr[index + 1].x,
  243. polyArr[index + 1].y,
  244. polyArr[index + 1].z
  245. )
  246. cartographic1 = ellipsoid.cartesianToCartographic(cartesian31)
  247. tmp.push([
  248. [
  249. Cesium.Math.toDegrees(cartographic.longitude),
  250. Cesium.Math.toDegrees(cartographic.latitude)
  251. ],
  252. [
  253. Cesium.Math.toDegrees(cartographic1.longitude),
  254. Cesium.Math.toDegrees(cartographic1.latitude)
  255. ]
  256. ])
  257. }
  258. polyLines.push(tmp)
  259. })
  260. // 等高分割矩形
  261. var bool = geodesic.width < geodesic.height
  262. var len = Math.floor(geodesic.height / (this.hfDistance / 2)) // 高度分割数量
  263. var step = rectangle.height / len // 步长
  264. if (bool) {
  265. len = Math.floor(geodesic.width / (this.hfDistance / 2)) // 宽度分割数量
  266. step = rectangle.width / len // 步长
  267. }
  268. jdArrs = [] // 交点集合
  269. // console.log(rectangle, len, step)
  270. for (var i = 0; i < len; i++) {
  271. var tmp = null
  272. if (bool) {
  273. tmp = new Cesium.Rectangle(
  274. rectangle.east - step * (i + 1),
  275. rectangle.south,
  276. rectangle.east - step * i,
  277. rectangle.north
  278. )
  279. } else {
  280. tmp = new Cesium.Rectangle(
  281. rectangle.west,
  282. rectangle.north - step * (i + 1),
  283. rectangle.east,
  284. rectangle.north - step * i
  285. )
  286. }
  287. // 弧度转换为经纬度
  288. var tmpLonLat = this.rectangle2LonLat(tmp)
  289. // 计算交点
  290. var tmpJdarr = []
  291. polyLines.map(res => {
  292. var mb = null
  293. if (bool) {
  294. mb = turf.lineString([
  295. [tmpLonLat[1][0], tmpLonLat[1][1]],
  296. [tmpLonLat[3][0], tmpLonLat[3][1]]
  297. ])
  298. } else {
  299. mb = turf.lineString([
  300. [tmpLonLat[1][0], tmpLonLat[1][1]],
  301. [tmpLonLat[0][0], tmpLonLat[0][1]]
  302. ])
  303. }
  304. var intersects = turf.lineIntersect(turf.lineString(res[0]), mb)
  305. if (intersects.features.length > 0) {
  306. var tmplatlon = intersects.features[0].geometry.coordinates
  307. tmpJdarr.push(tmplatlon)
  308. }
  309. })
  310. // 就近往返
  311. if (i > 0) {
  312. var distance1 = turf.distance(
  313. turf.point(tmpJdarr[0]),
  314. turf.point(jdArrs[jdArrs.length - 1]),
  315. { units: 'kilometers' }
  316. )
  317. var distance2 = turf.distance(
  318. turf.point(tmpJdarr[1]),
  319. turf.point(jdArrs[jdArrs.length - 1]),
  320. { units: 'kilometers' }
  321. )
  322. // console.log(i, distance1, distance2)
  323. if (distance1 > distance2) {
  324. tmpJdarr = tmpJdarr.reverse()
  325. }
  326. }
  327. // 存储交点
  328. tmpJdarr.map(res => {
  329. jdArrs.push(res)
  330. })
  331. }
  332. if (jdArrs[0][0] === jdArrs[1][0] && jdArrs[0][1] === jdArrs[1][1]) {
  333. jdArrs.shift()
  334. }
  335. // 线数据
  336. var linesArrs = []
  337. // 标字
  338. jdArrs.map((res, index) => {
  339. viewer.entities.add({
  340. name: 'uav-tmp-point',
  341. position: Cesium.Cartesian3.fromDegrees(res[0], res[1]),
  342. label: {
  343. text: index + '',
  344. font: '14pt SongTi',
  345. eyeOffset: new Cesium.Cartesian3(0, 0, -100)
  346. }
  347. })
  348. // 存储线数据
  349. linesArrs.push(res[0])
  350. linesArrs.push(res[1])
  351. })
  352. // 画方向线
  353. viewer.entities.add({
  354. name: 'uav-tmp-line',
  355. // corridor polyline
  356. polyline: {
  357. positions: Cesium.Cartesian3.fromDegreesArray(linesArrs),
  358. material: new Cesium.PolylineArrowMaterialProperty(Cesium.Color.RED),
  359. followSurface: true,
  360. width: 10
  361. }
  362. })
  363. },
  364. // 弧度转换为经纬度
  365. rectangle2LonLat(coor) {
  366. const northwest = Cesium.Rectangle.northwest(coor)
  367. const southwest = Cesium.Rectangle.southwest(coor)
  368. const northeast = Cesium.Rectangle.northeast(coor)
  369. const southeast = Cesium.Rectangle.southeast(coor)
  370. const leftTop = [
  371. Cesium.Math.toDegrees(northwest.longitude),
  372. Cesium.Math.toDegrees(northwest.latitude)
  373. ]
  374. const leftBottom = [
  375. Cesium.Math.toDegrees(southwest.longitude),
  376. Cesium.Math.toDegrees(southwest.latitude)
  377. ]
  378. const rightTop = [
  379. Cesium.Math.toDegrees(northeast.longitude),
  380. Cesium.Math.toDegrees(northeast.latitude)
  381. ]
  382. const rightBottom = [
  383. Cesium.Math.toDegrees(southeast.longitude),
  384. Cesium.Math.toDegrees(southeast.latitude)
  385. ]
  386. return [leftTop, rightTop, leftBottom, rightBottom]
  387. },
  388. // 清理entity
  389. cleanEntity() {
  390. var viewer = window.viewer
  391. this.cesium.removeEntityLikeName(viewer, 'uav-')
  392. this.cesium.cleanEntityCollection(viewer, 'uva')
  393. polyArr = []
  394. viewer.trackedEntity = undefined
  395. this.isFly = false
  396. },
  397. // 更改航飞间距触发事件
  398. distanceHandleChange(val) {
  399. this.beginCalc()
  400. // 重置飞行
  401. if (this.isFly) {
  402. this.moniFly()
  403. }
  404. },
  405. // 模拟飞行
  406. moniFly() {
  407. var viewer = window.viewer
  408. var that = this
  409. that.isFly = true
  410. if (polyArr.length === 0) {
  411. this.$message.warning('未检测到航飞区域')
  412. return
  413. }
  414. // 清除上一个动画
  415. this.cesium.cleanEntityCollection(viewer, 'uva')
  416. this.cesium.removeEntityLikeName(viewer, 'uav-tmp-fly')
  417. viewer.trackedEntity = undefined
  418. // 加载新动画
  419. const czml = [
  420. {
  421. id: 'document',
  422. name: 'uva',
  423. version: '1.0',
  424. clock: {
  425. interval: '2022-08-04T10:00:00Z/2022-08-04T15:00:00Z',
  426. currentTime: '2022-08-04T10:00:00Z',
  427. range: 'LOOP_STOP',
  428. multiplier: 10
  429. }
  430. },
  431. {
  432. id: 'path',
  433. name: 'uva-tmp-fly',
  434. description: '<p> 飞行器</p>',
  435. availability: '2022-08-04T10:00:00Z/2022-08-04T15:00:00Z',
  436. path: {
  437. material: {
  438. polylineOutline: {
  439. color: {
  440. rgba: [255, 215, 0, 255]
  441. },
  442. outlineColor: {
  443. rgba: [192, 192, 192, 255]
  444. },
  445. outlineWidth: 5
  446. }
  447. },
  448. width: 8,
  449. leadTime: 10,
  450. // trailTime: 1000,
  451. resolution: 5
  452. },
  453. billboard: {
  454. image:
  455. 'data:image/png;base64,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',
  456. scale: 1.5,
  457. eyeOffset: {
  458. cartesian: [0.0, 0.0, -10.0]
  459. }
  460. },
  461. position: {
  462. epoch: '2022-08-04T10:00:00Z',
  463. cartographicDegrees: []
  464. }
  465. }
  466. ]
  467. var tmp = []
  468. var timesArr = []
  469. var timeTmp = 0
  470. var height = 500 // 飞行高度
  471. var v = 20 // 飞行速度
  472. var yc = 2 // 重复飞行延迟时间 秒
  473. // 手动插值
  474. timesArr.push(0)
  475. tmp.push(0)
  476. tmp.push(jdArrs[0][0])
  477. tmp.push(jdArrs[0][1])
  478. tmp.push(height + Math.random() * 5 + 5)
  479. for (var i = 0; i < jdArrs.length; i++) {
  480. var times = 0
  481. if (i < jdArrs.length - 1) {
  482. var from = turf.point(jdArrs[i])
  483. var to = turf.point(jdArrs[i + 1])
  484. var options = { units: 'kilometers' }
  485. var distance = turf.distance(from, to, options)
  486. times = Math.round((distance * 1000) / v)
  487. timeTmp += times
  488. timesArr.push(timeTmp)
  489. tmp.push(timeTmp)
  490. tmp.push(jdArrs[i + 1][0])
  491. tmp.push(jdArrs[i + 1][1])
  492. tmp.push(height + Math.random() * 5 + 5)
  493. }
  494. }
  495. // 动态配置CZML
  496. // 动画结束时间
  497. var tmpsss = new Date(
  498. new Date(czml[0].clock.currentTime).getTime() +
  499. (timesArr[timesArr.length - 1] + yc) * 1000
  500. ).toISOString()
  501. var str = czml[0].clock.currentTime + '/' + tmpsss
  502. czml[0].clock.interval = str
  503. czml[1].availability = str
  504. czml[1].path.trailTime = timesArr[2]
  505. czml[1].position.cartographicDegrees = tmp
  506. // 加载CZML
  507. var dataSource = viewer.dataSources.add(Cesium.CzmlDataSource.load(czml))
  508. // 加载同步扫描椎体
  509. dataSource
  510. .then(function(dataSource) {
  511. var entity = dataSource.entities.getById('path')
  512. entity.viewFrom = new Cesium.Cartesian3(0.0, -1000.0, 1500.0)
  513. viewer.trackedEntity = entity
  514. var cylinderEntitys = that.addFrustum({
  515. length: 510.0,
  516. topRadius: 0.0,
  517. bottomRadius: that.hfDistance / 2,
  518. color: Cesium.Color.GREEN.withAlpha(0.5)
  519. })
  520. var property = new Cesium.SampledPositionProperty()
  521. for (var ind = 0; ind < timesArr.length; ind++) {
  522. var time = Cesium.JulianDate.addSeconds(
  523. viewer.clock.currentTime,
  524. timesArr[ind],
  525. new Cesium.JulianDate()
  526. )
  527. var position = entity.position.getValue(time)
  528. if (position) {
  529. var cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic(
  530. position
  531. )
  532. var lat = Cesium.Math.toDegrees(cartographic.latitude)
  533. var lng = Cesium.Math.toDegrees(cartographic.longitude)
  534. var hei = cartographic.height / 1.9
  535. property.addSample(
  536. time,
  537. Cesium.Cartesian3.fromDegrees(lng, lat, hei)
  538. )
  539. }
  540. }
  541. cylinderEntitys.position = property
  542. })
  543. .catch(function(error) {
  544. window.alert(error)
  545. })
  546. },
  547. // 创建视锥体
  548. addFrustum(option) {
  549. var viewer = window.viewer
  550. return viewer.entities.add({
  551. name: 'uav-tmp-fly-wxsimple',
  552. position: Cesium.Cartesian3.fromDegrees(114.0, 36.0, 200000.0),
  553. cylinder: {
  554. slices: option.slices,
  555. length: option.length,
  556. topRadius: option.topRadius,
  557. bottomRadius: option.bottomRadius,
  558. material: option.color
  559. }
  560. })
  561. }
  562. }
  563. }
  564. </script>
  565. <style lang="scss" scoped>
  566. .show {
  567. display: block;
  568. }
  569. .uvaRoutePlanBox {
  570. width: 100vw;
  571. height: 100vh;
  572. }
  573. /* 可视域 */
  574. #cesiumContainer {
  575. width: 100%;
  576. height: 100%;
  577. }
  578. .body {
  579. position: fixed;
  580. right: calc(100% - 300px);
  581. top: 166px;
  582. z-index: 999;
  583. width: 300px;
  584. text-align: center;
  585. background: rgba(0, 0, 0, 0.6);
  586. padding: 15px;
  587. color: #fff;
  588. }
  589. .form-item {
  590. margin: 5px;
  591. .form-label {
  592. display: inline-block;
  593. width: 100px;
  594. text-align: center;
  595. font-size: 16px;
  596. font-weight: bold;
  597. }
  598. .form-connect {
  599. display: inline-block;
  600. // width: calc(100% - 120px);
  601. }
  602. }
  603. .hide {
  604. display: none;
  605. }
  606. </style>

使用注意

1、cesium引用切换为自己的引用。

2、this.cesium.removeEntityLikeName 和 this.cesium.cleanEntityCollection报错。

  1. /**
  2. * 根据名称删除DataSources
  3. * @param {*} name
  4. */
  5. export function cleanEntityCollection(viewer, key) {
  6. var tmp = viewer.dataSources.getByName(key)
  7. if (tmp.length > 0) {
  8. tmp.map(res => {
  9. viewer.dataSources.remove(res)
  10. })
  11. }
  12. }
  13. /**
  14. * 根据name获取entity
  15. *
  16. * */
  17. export function getEntityLikeName(viewer, name) {
  18. if (name) {
  19. var entities = viewer.entities.values
  20. var findEntities = []
  21. for (var i = 0; i < entities.length; i++) {
  22. var entity = entities[i]
  23. // console.log(entity);
  24. if (entity.name && entity.name.indexOf(name) !== -1) {
  25. findEntities.push(entity)
  26. }
  27. }
  28. return findEntities
  29. } else {
  30. return []
  31. }
  32. }
  33. /**
  34. * 根据类似name移除entity
  35. *
  36. * */
  37. export function removeEntityLikeName(viewer, name) {
  38. if (name) {
  39. var cleanEntities = getEntityLikeName(viewer, name)
  40. // 清除
  41. cleanEntities.map(res => {
  42. viewer.entities.removeById(res.id)
  43. })
  44. } else {
  45. viewer.entities.removeAll()
  46. }
  47. }

3、this.$message 报错可将 this.$message.warning删除或换成alert弹窗或其他提示方法。

追加说明

        由于很多人咨询配置环境问题,现配置一份简单的vue的框架。cesium引入采用cdn,npm i 和npm run dev 即可运行。

源码地址:

uav: Cesium 简单航飞线路规划,模拟飞行扫描效果 - Gitee.com

参考文档

数据计算参考:

GET START | Turf.js中文网 (fenxianglu.cn)

飞行效果参考:

CZML Path - Cesium Sandcastle

相关方法参考:

Viewer - Cesium Documentation

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/694840
推荐阅读
相关标签
  

闽ICP备14008679号