您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

RoamingPath.js 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. /**
  2. * @Author: Caven
  3. * @Date: 2020-01-19 11:21:48
  4. */
  5. import { Cesium } from '@dc-modules/namespace'
  6. import { RoamingEvent, RoamingEventType } from '@dc-modules/event'
  7. import State from '@dc-modules/state/State'
  8. import Parse from '@dc-modules/parse/Parse'
  9. import { Util } from '@dc-modules/utils'
  10. import { Transform } from '@dc-modules/transform'
  11. import RoamingViewMode from './RoamingViewMode'
  12. const DEF_OPTS = {
  13. showPath: false,
  14. pathWidth: 1,
  15. pathMaterial: Cesium.Color.ORANGE.withAlpha(0.8),
  16. pathLeadTime: 1
  17. }
  18. class RoamingPath {
  19. constructor(id, duration, tickCallback, options) {
  20. this._id = id || Util.uuid()
  21. this._startTime = undefined
  22. this._controller = undefined
  23. this._duration = duration || 0
  24. this._mode = 'speed'
  25. this._delegate = new Cesium.Entity()
  26. this._positions = []
  27. this._sampledPosition = undefined
  28. this._isActive = false
  29. this._tickCallback = tickCallback
  30. this._options = {
  31. ...DEF_OPTS,
  32. ...options
  33. }
  34. this._positionIndex = 0
  35. this._timeLine = []
  36. this._roamingEvent = new RoamingEvent()
  37. this._roamingEvent.on(
  38. RoamingEventType.POST_UPDATE,
  39. this._onPostUpdate,
  40. this
  41. )
  42. this._roamingEvent.on(RoamingEventType.ADD, this._onAdd, this)
  43. this._roamingEvent.on(RoamingEventType.REMOVE, this._onRemove, this)
  44. this._roamingEvent.on(RoamingEventType.ACTIVE, this._onActive, this)
  45. this._roamingEvent.on(RoamingEventType.RELEASE, this._onRelease, this)
  46. this._state = State.INITIALIZED
  47. }
  48. get id() {
  49. return this._id
  50. }
  51. get roamingEvent() {
  52. return this._roamingEvent
  53. }
  54. get state() {
  55. return this._state
  56. }
  57. get isActive() {
  58. return this._isActive
  59. }
  60. set positions(positions) {
  61. this._positions = Parse.parsePositions(positions)
  62. this._mountPosition()
  63. return this
  64. }
  65. get positions() {
  66. return this._positions
  67. }
  68. set startTime(startTime) {
  69. if (!startTime || !(startTime instanceof Date)) {
  70. throw new Error('Path: the start time invalid ')
  71. }
  72. this._startTime = Cesium.JulianDate.fromDate(startTime)
  73. this._mountPosition()
  74. return this
  75. }
  76. get startTime() {
  77. return this._startTime
  78. }
  79. /**
  80. * add to entities
  81. * @param controller
  82. * @private
  83. */
  84. _onAdd(controller) {
  85. this._controller = controller
  86. !this._startTime &&
  87. (this._startTime = controller.startTime || Cesium.JulianDate.now())
  88. this._mountPath()
  89. !this._delegate.position && this._mountPosition()
  90. this._mountedHook && this._mountedHook()
  91. this._state = State.ADDED
  92. }
  93. /**
  94. * remove from entities
  95. * @private
  96. */
  97. _onRemove() {
  98. if (this._controller) {
  99. this._controller.roamingLayer.remove(this._delegate)
  100. this._isActive && this._controller.releaseCamera()
  101. this._isActive = false
  102. this._state = State.REMOVED
  103. }
  104. }
  105. /**
  106. * @param params
  107. * @returns {boolean}
  108. * @private
  109. */
  110. _onPostUpdate(params) {
  111. let currentTime = params.currentTime
  112. let orientation = this._delegate.orientation.getValue(currentTime)
  113. let timePos = this._timeLine[this._positionIndex]
  114. if (timePos) {
  115. let timeDiff = Cesium.JulianDate.secondsDifference(currentTime, timePos)
  116. if (timeDiff >= 0 && timeDiff <= 1) {
  117. let position = this._positions[this._positionIndex]
  118. if (position && orientation) {
  119. let mat = Cesium.Matrix3.fromQuaternion(orientation)
  120. let mat4 = Cesium.Matrix4.fromRotationTranslation(
  121. mat,
  122. this._delegate.position.getValue(currentTime)
  123. )
  124. let hpr = Cesium.Transforms.fixedFrameToHeadingPitchRoll(mat4)
  125. position.heading = Cesium.Math.toDegrees(hpr.heading)
  126. position.pitch = Cesium.Math.toDegrees(hpr.pitch)
  127. position.roll = Cesium.Math.toDegrees(hpr.roll)
  128. }
  129. this._tickCallback &&
  130. this._tickCallback(
  131. position,
  132. this._positionIndex + 1 === this._positions.length
  133. )
  134. this._positionIndex += 1
  135. }
  136. }
  137. this._isActive &&
  138. this._setCameraView(currentTime, params.viewMode, params.viewOption)
  139. }
  140. /**
  141. * @private
  142. */
  143. _onActive() {
  144. this._isActive = true
  145. }
  146. /**
  147. *
  148. * @private
  149. */
  150. _onRelease() {
  151. this._isActive = false
  152. }
  153. /**
  154. * Sets camera position
  155. * @param currentTime
  156. * @param viewMode
  157. * @param viewOption
  158. * @private
  159. */
  160. _setCameraView(currentTime, viewMode, viewOption) {
  161. let viewer = this._controller._viewer.delegate
  162. let camera = this._controller._viewer.camera
  163. let tickPosition = this._sampledPosition.getValue(currentTime)
  164. let nextTickPosition = this._sampledPosition.getValue(
  165. Cesium.JulianDate.addSeconds(currentTime, 1 / 60, new Cesium.JulianDate())
  166. )
  167. if (tickPosition && nextTickPosition && viewMode) {
  168. if (viewMode === RoamingViewMode.TRACKED) {
  169. viewer.trackedEntity = this._delegate
  170. } else if (viewMode === RoamingViewMode.FP) {
  171. let heading = Cesium.Math.heading(tickPosition, nextTickPosition)
  172. let WGS84TickPosition = Transform.transformCartesianToWGS84(
  173. tickPosition
  174. )
  175. if (!isNaN(viewOption.alt)) {
  176. WGS84TickPosition.alt = viewOption.alt
  177. }
  178. camera.lookAt(
  179. Transform.transformWGS84ToCartesian(WGS84TickPosition),
  180. new Cesium.HeadingPitchRange(
  181. heading,
  182. Cesium.Math.toRadians(viewOption.pitch || 0),
  183. viewOption.range || 10
  184. )
  185. )
  186. } else if (viewMode === RoamingViewMode.TP) {
  187. camera.lookAt(
  188. tickPosition,
  189. new Cesium.HeadingPitchRange(0, -90, viewOption.range || 1000)
  190. )
  191. }
  192. } else {
  193. camera.lookAtTransform(Cesium.Matrix4.IDENTITY)
  194. viewer.trackedEntity = undefined
  195. }
  196. }
  197. /**
  198. * Mounts path
  199. * @private
  200. */
  201. _mountPath() {
  202. if (this._options.showPath) {
  203. this._delegate.availability = new Cesium.TimeIntervalCollection([
  204. new Cesium.TimeInterval({
  205. start: this._startTime,
  206. stop: Cesium.JulianDate.addSeconds(
  207. this._startTime,
  208. this._duration,
  209. new Cesium.JulianDate()
  210. )
  211. })
  212. ])
  213. this._delegate.path = {
  214. material: this._options.pathMaterial,
  215. width: this._options.pathWidth,
  216. leadTime: this._options.pathLeadTime
  217. }
  218. }
  219. }
  220. /**
  221. * Mounts Position
  222. * @private
  223. */
  224. _mountPosition() {
  225. if (
  226. !this._startTime ||
  227. !this._duration ||
  228. !this._positions ||
  229. !this._positions.length
  230. ) {
  231. return false
  232. }
  233. let interval = 0
  234. if (this._mode === 'speed') {
  235. let v = Cesium.Math.distance(this._positions) / this._duration
  236. this._timeLine = this._positions.map((item, index, arr) => {
  237. if (index !== 0) {
  238. interval += Cesium.Math.distance([arr[index - 1], item]) / v
  239. }
  240. return Cesium.JulianDate.addSeconds(
  241. this._startTime,
  242. interval,
  243. new Cesium.JulianDate()
  244. )
  245. })
  246. } else {
  247. let len = this._positions.length
  248. let interval = (this._duration - (this._duration % len)) / len
  249. this._timeLine = this._positions.map((item, index) => {
  250. return Cesium.JulianDate.addSeconds(
  251. this._startTime,
  252. index * interval,
  253. new Cesium.JulianDate()
  254. )
  255. })
  256. }
  257. this._sampledPosition = new Cesium.SampledPositionProperty()
  258. this._sampledPosition.addSamples(
  259. this._timeLine,
  260. Transform.transformWGS84ArrayToCartesianArray(this._positions)
  261. )
  262. this._delegate.position = this._sampledPosition
  263. this._delegate.position.setInterpolationOptions({
  264. interpolationDegree: 1,
  265. interpolationAlgorithm: Cesium.LinearApproximation
  266. })
  267. this._delegate.orientation = new Cesium.VelocityOrientationProperty(
  268. this._sampledPosition
  269. )
  270. }
  271. /**
  272. * Mounted Hook
  273. * @private
  274. */
  275. _mountedHook() {
  276. this._controller.roamingLayer.add(this._delegate)
  277. }
  278. /**
  279. * Sets positions
  280. * @param positions
  281. * @returns {RoamingPath}
  282. */
  283. setPositions(positions) {
  284. this._positions = Parse.parsePositions(positions)
  285. this._mountPosition()
  286. return this
  287. }
  288. /**
  289. * Adds Position
  290. * @param position
  291. * @param duration
  292. * @returns {RoamingPath}
  293. */
  294. addPosition(position, duration) {
  295. this._positions.push(Parse.parsePosition(position))
  296. this._duration += duration
  297. this._mountPosition()
  298. return this
  299. }
  300. /**
  301. * Sets mode
  302. * @param mode
  303. * @returns {RoamingPath}
  304. */
  305. setMode(mode) {
  306. this._mode = mode
  307. this._mountPosition()
  308. return this
  309. }
  310. /**
  311. * Sets model
  312. * @param modelPath
  313. * @param style
  314. * @returns {RoamingPath}
  315. */
  316. setModel(modelPath, style) {
  317. this._delegate.model = {
  318. ...style,
  319. uri: modelPath
  320. }
  321. return this
  322. }
  323. /**
  324. * Sets billboard
  325. * @param icon
  326. * @param style
  327. * @returns {RoamingPath}
  328. */
  329. setBillboard(icon, style) {
  330. this._delegate.billboard = {
  331. ...style,
  332. image: icon
  333. }
  334. return this
  335. }
  336. /**
  337. * Sets label
  338. * @param text
  339. * @param style
  340. * @returns {RoamingPath}
  341. */
  342. setLabel(text, style) {
  343. this._delegate.label = {
  344. ...style,
  345. text: text
  346. }
  347. return this
  348. }
  349. }
  350. export default RoamingPath