|
|
|
@@ -0,0 +1,359 @@ |
|
|
|
/** |
|
|
|
* @Author: Caven |
|
|
|
* @Date: 2020-01-19 11:21:48 |
|
|
|
*/ |
|
|
|
|
|
|
|
import { Cesium } from '@dc-modules/namespace' |
|
|
|
import { TrackEvent, TrackEventType } from '@dc-modules/event' |
|
|
|
import State from '@dc-modules/state/State' |
|
|
|
import Parse from '@dc-modules/parse/Parse' |
|
|
|
import { Util } from '@dc-modules/utils' |
|
|
|
import { Transform } from '@dc-modules/transform' |
|
|
|
import { heading, distance } from '@dc-modules/math' |
|
|
|
import TrackViewMode from './TrackViewMode' |
|
|
|
|
|
|
|
const DEF_OPTS = { |
|
|
|
showPath: false, |
|
|
|
pathWidth: 1, |
|
|
|
pathMaterial: Cesium.Color.ORANGE.withAlpha(0.8), |
|
|
|
pathLeadTime: 1, |
|
|
|
clampToGround: false, |
|
|
|
clampToTileset: false |
|
|
|
} |
|
|
|
|
|
|
|
class Track { |
|
|
|
constructor(positions, duration, callback, options) { |
|
|
|
this._id = Util.uuid() |
|
|
|
this._bid = undefined |
|
|
|
this._positions = Parse.parsePositions(positions) |
|
|
|
this._duration = duration || 20 |
|
|
|
this._callback = callback |
|
|
|
this._options = { |
|
|
|
...DEF_OPTS, |
|
|
|
...options |
|
|
|
} |
|
|
|
this._controller = undefined |
|
|
|
this._viewed = false |
|
|
|
this._delegate = new Cesium.Entity() |
|
|
|
this._positionIndex = 0 |
|
|
|
this._timeLine = [] |
|
|
|
this._startTime = undefined |
|
|
|
this._endTime = undefined |
|
|
|
this._trackEvent = new TrackEvent() |
|
|
|
this._trackEvent.on(TrackEventType.POST_RENDER, this._onPostRender, this) |
|
|
|
this._trackEvent.on(TrackEventType.ADD, this._onAdd, this) |
|
|
|
this._trackEvent.on(TrackEventType.REMOVE, this._onRemove, this) |
|
|
|
this._state = State.INITIALIZED |
|
|
|
} |
|
|
|
|
|
|
|
get trackId() { |
|
|
|
return this._id |
|
|
|
} |
|
|
|
|
|
|
|
set id(id) { |
|
|
|
this._bid = id |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
get id() { |
|
|
|
return this._bid |
|
|
|
} |
|
|
|
|
|
|
|
set positions(postions) { |
|
|
|
this._positions = Parse.parsePositions(postions) |
|
|
|
this._resetTimeLine() |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
get positions() { |
|
|
|
return this._positions |
|
|
|
} |
|
|
|
|
|
|
|
set duration(duration) { |
|
|
|
this._duration = duration |
|
|
|
this._resetTimeLine() |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
get duration() { |
|
|
|
return this._duration |
|
|
|
} |
|
|
|
|
|
|
|
set startTime(startTime) { |
|
|
|
if (startTime instanceof Date) { |
|
|
|
this._startTime = Cesium.JulianDate.fromDate(startTime) |
|
|
|
} else { |
|
|
|
this._startTime = startTime |
|
|
|
} |
|
|
|
this._resetTimeLine() |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
get startTime() { |
|
|
|
return this._startTime |
|
|
|
} |
|
|
|
|
|
|
|
set viewed(viewed) { |
|
|
|
this._viewed = viewed |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
get viewed() { |
|
|
|
return this._viewed |
|
|
|
} |
|
|
|
|
|
|
|
get trackEvent() { |
|
|
|
return this._trackEvent |
|
|
|
} |
|
|
|
|
|
|
|
get state() { |
|
|
|
return this._state |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* add to entities |
|
|
|
* @param controller |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_onAdd(controller) { |
|
|
|
if (!controller) { |
|
|
|
return false |
|
|
|
} |
|
|
|
this._controller = controller |
|
|
|
this._controller.delegate.add(this._delegate) |
|
|
|
!this._startTime && (this._startTime = Cesium.JulianDate.now()) |
|
|
|
this._state = State.ADDED |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* remove from entities |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_onRemove() { |
|
|
|
if (this._controller) { |
|
|
|
this._controller.delegate.remove(this._delegate) |
|
|
|
} |
|
|
|
this._viewed = false |
|
|
|
this._state = State.REMOVED |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* |
|
|
|
* @param viewer |
|
|
|
* @param viewOption |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_onPostRender({ viewer, viewOption }) { |
|
|
|
if (!this._startTime || !this._endTime) { |
|
|
|
return false |
|
|
|
} |
|
|
|
let now = Cesium.JulianDate.now() |
|
|
|
if (Cesium.JulianDate.lessThan(now, this._endTime)) { |
|
|
|
if (this._options.clampToTileset) { |
|
|
|
this._delegate.position = viewer.scene.clampToHeight( |
|
|
|
this._sampledPosition.getValue(now), |
|
|
|
[this._delegate] |
|
|
|
) |
|
|
|
} else { |
|
|
|
this._delegate.position = this._sampledPosition.getValue(now) |
|
|
|
} |
|
|
|
let time = this._timeLine[this._positionIndex] |
|
|
|
if (time) { |
|
|
|
let timeDiff = Cesium.JulianDate.secondsDifference(now, time) |
|
|
|
if (timeDiff >= 0 && timeDiff <= 1) { |
|
|
|
let position = this._positions[this._positionIndex] || undefined |
|
|
|
if (position) { |
|
|
|
let mat = Cesium.Matrix3.fromQuaternion( |
|
|
|
this._delegate.orientation.getValue(now) |
|
|
|
) |
|
|
|
let mat4 = Cesium.Matrix4.fromRotationTranslation( |
|
|
|
mat, |
|
|
|
this._sampledPosition.getValue(now) |
|
|
|
) |
|
|
|
let hpr = Cesium.Transforms.fixedFrameToHeadingPitchRoll(mat4) |
|
|
|
position.heading = Cesium.Math.toDegrees(hpr.heading) |
|
|
|
position.pitch = Cesium.Math.toDegrees(hpr.pitch) |
|
|
|
position.roll = Cesium.Math.toDegrees(hpr.roll) |
|
|
|
} |
|
|
|
this._callback && |
|
|
|
this._callback( |
|
|
|
position, |
|
|
|
this._positionIndex + 1 === this._positions.length |
|
|
|
) |
|
|
|
this._positionIndex += 1 |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
this._setCameraView(viewer, viewOption) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets camera position |
|
|
|
* @param viewer |
|
|
|
* @param viewOption |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_setCameraView(viewer, viewOption) { |
|
|
|
if (!this._viewed) { |
|
|
|
return false |
|
|
|
} |
|
|
|
let now = Cesium.JulianDate.now() |
|
|
|
if (Cesium.JulianDate.greaterThan(now, this._endTime)) { |
|
|
|
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY) |
|
|
|
viewer.delegate.trackedEntity && |
|
|
|
(viewer.delegate.trackedEntity = undefined) |
|
|
|
this._viewed = false |
|
|
|
} else { |
|
|
|
let p = this._sampledPosition.getValue(now) |
|
|
|
let next_p = this._sampledPosition.getValue( |
|
|
|
Cesium.JulianDate.addSeconds(now, 1 / 60, new Cesium.JulianDate()) |
|
|
|
) |
|
|
|
if (p && next_p) { |
|
|
|
if ( |
|
|
|
viewOption?.mode === TrackViewMode.TRACKED && |
|
|
|
viewer.delegate?.trackedEntity?.id !== this._delegate?.id |
|
|
|
) { |
|
|
|
viewer.delegate.trackedEntity = this._delegate |
|
|
|
} else if (viewOption?.mode === TrackViewMode.FP) { |
|
|
|
viewer.camera.lookAt( |
|
|
|
p, |
|
|
|
new Cesium.HeadingPitchRange( |
|
|
|
heading(p, next_p), |
|
|
|
Cesium.Math.toRadians(viewOption?.pitch || 0), |
|
|
|
viewOption?.range || 10 |
|
|
|
) |
|
|
|
) |
|
|
|
} else if (viewOption?.mode === TrackViewMode.TP) { |
|
|
|
viewer.camera.lookAt( |
|
|
|
p, |
|
|
|
new Cesium.HeadingPitchRange( |
|
|
|
0, |
|
|
|
Cesium.Math.toRadians(viewOption?.pitch || -90), |
|
|
|
viewOption?.range || 1000 |
|
|
|
) |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* |
|
|
|
* @param params |
|
|
|
* @returns {boolean} |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_resetTimeLine(params) { |
|
|
|
if (!this._startTime || !this._duration || !this._positions?.length) { |
|
|
|
return false |
|
|
|
} |
|
|
|
let interval = 0 |
|
|
|
let v = distance(this._positions) / this._duration |
|
|
|
this._timeLine = this._positions.map((item, index, arr) => { |
|
|
|
if (index !== 0) { |
|
|
|
interval += distance([arr[index - 1], item]) / v |
|
|
|
} |
|
|
|
return Cesium.JulianDate.addSeconds( |
|
|
|
this._startTime, |
|
|
|
interval, |
|
|
|
new Cesium.JulianDate() |
|
|
|
) |
|
|
|
}) |
|
|
|
if (params?.stopTime && params?.duration) { |
|
|
|
this._duration += params.duration |
|
|
|
this._timeLine = this._timeLine.map(item => { |
|
|
|
if (Cesium.JulianDate.greaterThan(item, params.stopTime)) { |
|
|
|
item = Cesium.JulianDate.addSeconds( |
|
|
|
item, |
|
|
|
params.stopTime, |
|
|
|
new Cesium.JulianDate() |
|
|
|
) |
|
|
|
} |
|
|
|
return item |
|
|
|
}) |
|
|
|
} |
|
|
|
this._sampledPosition = new Cesium.SampledPositionProperty() |
|
|
|
this._sampledPosition.addSamples( |
|
|
|
this._timeLine, |
|
|
|
Transform.transformWGS84ArrayToCartesianArray(this._positions) |
|
|
|
) |
|
|
|
this._sampledPosition.forwardExtrapolationType = |
|
|
|
Cesium.ExtrapolationType.HOLD |
|
|
|
this._sampledPosition.setInterpolationOptions({ |
|
|
|
interpolationDegree: 5, |
|
|
|
interpolationAlgorithm: Cesium.HermitePolynomialApproximation |
|
|
|
}) |
|
|
|
this._delegate.orientation = new Cesium.VelocityOrientationProperty( |
|
|
|
this._sampledPosition |
|
|
|
) |
|
|
|
this._endTime = this._timeLine[this._timeLine.length - 1] |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Adds Position |
|
|
|
* @param position |
|
|
|
* @param duration |
|
|
|
* @returns {Track} |
|
|
|
*/ |
|
|
|
addPosition(position, duration) { |
|
|
|
this._positions.push(Parse.parsePosition(position)) |
|
|
|
this._duration += duration |
|
|
|
this._resetTimeLine() |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets model |
|
|
|
* @param modelPath |
|
|
|
* @param style |
|
|
|
* @returns {Track} |
|
|
|
*/ |
|
|
|
setModel(modelPath, style) { |
|
|
|
this._delegate.model = { |
|
|
|
...style, |
|
|
|
uri: modelPath, |
|
|
|
heightReference: this._options.clampToGround |
|
|
|
? Cesium.HeightReference.CLAMP_TO_GROUND |
|
|
|
: Cesium.HeightReference.NONE |
|
|
|
} |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets billboard |
|
|
|
* @param icon |
|
|
|
* @param style |
|
|
|
* @returns {Track} |
|
|
|
*/ |
|
|
|
setBillboard(icon, style) { |
|
|
|
this._delegate.billboard = { |
|
|
|
...style, |
|
|
|
image: icon, |
|
|
|
heightReference: this._options.clampToGround |
|
|
|
? Cesium.HeightReference.CLAMP_TO_GROUND |
|
|
|
: Cesium.HeightReference.NONE |
|
|
|
} |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets label |
|
|
|
* @param text |
|
|
|
* @param style |
|
|
|
* @returns {Track} |
|
|
|
*/ |
|
|
|
setLabel(text, style) { |
|
|
|
this._delegate.label = { |
|
|
|
...style, |
|
|
|
text: text, |
|
|
|
heightReference: this._options.clampToGround |
|
|
|
? Cesium.HeightReference.CLAMP_TO_GROUND |
|
|
|
: Cesium.HeightReference.NONE |
|
|
|
} |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
setPath() {} |
|
|
|
} |
|
|
|
|
|
|
|
export default Track |