Bläddra i källkod

add @dc-modules/roaming

tags/2.0.0
Caven Chen 4 år sedan
förälder
incheckning
f62b15be4f

+ 238
- 0
modules/roaming/RoamingController.js Visa fil

@@ -0,0 +1,238 @@
/**
* @Author: Caven
* @Date: 2020-04-01 10:36:36
*/

import { RoamingEventType } from '@dc-modules/event'

const { Cesium } = DC.Namespace

class RoamingController {
constructor(viewer) {
this._viewer = viewer
this._roamingLayer = new Cesium.CustomDataSource('roaming-layer')
viewer.dataSources.add(this._roamingLayer)
this._postUpdateRemoveCallback = undefined
this._startTime = undefined
this._cache = {}
this._activePath = undefined
this._viewMode = undefined
this._viewOption = {}
}

get startTime() {
return this._startTime
}

get roamingLayer() {
return this._roamingLayer.entities
}

/**
* @private
*/
_onPostUpdate(scene, time) {
Object.keys(this._cache).forEach(key => {
let path = this._cache[key]
path.roamingEvent &&
path.roamingEvent.fire(RoamingEventType.POST_UPDATE, {
currentTime: time,
viewMode: this._viewMode,
viewOption: this._viewOption
})
})
}

/**
*
* @private
*/
_addPostUpdateListener() {
this._postUpdateRemoveCallback && this._postUpdateRemoveCallback()
this._postUpdateRemoveCallback = this._viewer.scene.postUpdate.addEventListener(
this._onPostUpdate,
this
)
}

/**
* Sets time range
* @param startTime
* @returns {RoamingController}
*/
setStartTime(startTime) {
if (!startTime || !(startTime instanceof Date)) {
throw new Error('RoamingController: the start time invalid ')
}
this._startTime = Cesium.JulianDate.fromDate(startTime)
return this
}

/**
* Starts play all path
* @returns {RoamingController}
*/
play() {
this._viewer.clock.shouldAnimate = true
this._viewer.clock.currentTime = this._startTime || Cesium.JulianDate.now()
this._addPostUpdateListener()
return this
}

/**
*
*/
pause() {
this._viewer.clock.shouldAnimate = false
this._viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY)
this._viewer.delegate.trackedEntity = undefined
this._postUpdateRemoveCallback && this._postUpdateRemoveCallback()
this._postUpdateRemoveCallback = undefined
return this
}

/**
*
*/
restore() {
this._viewer.clock.shouldAnimate = true
this._postUpdateRemoveCallback && this._postUpdateRemoveCallback()
this._postUpdateRemoveCallback = this._viewer.scene.postUpdate.addEventListener(
this._onPostUpdate,
this
)
this._addPostUpdateListener()
return this
}

/**
*
* @param speed
* @returns {RoamingController}
*/
changeSpeed(speed) {
this._viewer.clock.multiplier = speed
return this
}

/**
* Adds a path
* @param path
* @returns {RoamingController}
*/
addPath(path) {
if (
path &&
path.roamingEvent &&
!Object(this._cache).hasOwnProperty(path.id)
) {
path.roamingEvent.fire(RoamingEventType.ADD, this)
this._cache[path.id] = path
}
return this
}

/**
* Returns a path
* @param id
* @returns {*|undefined}
*/
getPath(id) {
return this._cache[id] || undefined
}

/**
* removes a path
* @param path
* @returns {RoamingController}
*/
removePath(path) {
if (
path &&
Object(this._cache).hasOwnProperty(path.id) &&
path.roamingEvent
) {
path.roamingEvent.fire(RoamingEventType.REMOVE, this)
delete this._cache[path.id]
}
return this
}

/**
*
* @returns {RoamingController}
*/
clearPath() {
Object.keys(this._cache).forEach(key => {
let path = this._cache[key]
path && this.removePath(path)
})
return this
}

/**
*
* @param path
* @param viewMode
* @param viewOption
* @returns {RoamingController}
*/
trackedPath(path, viewMode, viewOption = {}) {
if (!this._cache[path.id]) {
throw new Error('RoamingController: path does not added ')
}
this._viewMode = viewMode
this._viewOption = viewOption
if (this._activePath && this._activePath.id === path.id) {
return this
}
if (this._activePath && this._activePath.roamingEvent) {
this._activePath.roamingEvent.fire(RoamingEventType.RELEASE, path.id)
}
this._activePath = path
if (this._activePath && this._activePath.roamingEvent) {
this._activePath.roamingEvent.fire(
RoamingEventType.ACTIVE,
this._activePath.id
)
}
return this
}

/**
*
* @param path
* @returns {RoamingController}
*/
releasePath(path) {
if (!this._cache[path.id]) {
throw new Error('RoamingController: path does not added ')
}
if (path && path.isActive && path.roamingEvent) {
path.roamingEvent.fire(RoamingEventType.RELEASE, path.id)
}
this._activePath = undefined
this._viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY)
this._viewer.delegate.trackedEntity = undefined
return this
}

/**
*
* @returns {RoamingController}
*/
releaseCamera() {
this._viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY)
this._viewer.delegate.trackedEntity = undefined
if (this._activePath && this._activePath.roamingEvent) {
this._activePath.roamingEvent.fire(
RoamingEventType.RELEASE,
this._activePath.id
)
}
this._activePath = undefined
return this
}
}

export default RoamingController

+ 377
- 0
modules/roaming/RoamingPath.js Visa fil

@@ -0,0 +1,377 @@
/**
* @Author: Caven
* @Date: 2020-01-19 11:21:48
*/

import { RoamingEvent, RoamingEventType } from '@dc-modules/event'
import RoamingViewMode from './RoamingViewMode'

const { Util, State, Transform, Parse } = DC

const { Cesium } = DC.Namespace

const DEF_OPTS = {
showPath: false,
pathWidth: 1,
pathMaterial: Cesium.Color.ORANGE.withAlpha(0.8),
pathLeadTime: 1
}

class RoamingPath {
constructor(id, duration, tickCallback, options) {
this._id = id || Util.uuid()
this._startTime = undefined
this._controller = undefined
this._duration = duration || 0
this._mode = 'speed'
this._delegate = new Cesium.Entity()
this._positions = []
this._sampledPosition = undefined
this._isActive = false
this._tickCallback = tickCallback
this._options = {
...DEF_OPTS,
...options
}
this._positionIndex = 0
this._timeLine = []
this._roamingEvent = new RoamingEvent()
this._roamingEvent.on(
RoamingEventType.POST_UPDATE,
this._onPostUpdate,
this
)
this._roamingEvent.on(RoamingEventType.ADD, this._onAdd, this)
this._roamingEvent.on(RoamingEventType.REMOVE, this._onRemove, this)
this._roamingEvent.on(RoamingEventType.ACTIVE, this._onActive, this)
this._roamingEvent.on(RoamingEventType.RELEASE, this._onRelease, this)
this._state = State.INITIALIZED
}

get id() {
return this._id
}

get roamingEvent() {
return this._roamingEvent
}

get state() {
return this._state
}

get isActive() {
return this._isActive
}

set positions(positions) {
this._positions = Parse.parsePositions(positions)
this._mountPosition()
return this
}

get positions() {
return this._positions
}

set startTime(startTime) {
if (!startTime || !(startTime instanceof Date)) {
throw new Error('Path: the start time invalid ')
}
this._startTime = Cesium.JulianDate.fromDate(startTime)
this._mountPosition()
return this
}

get startTime() {
return this._startTime
}

/**
* add to entities
* @param controller
* @private
*/
_onAdd(controller) {
this._controller = controller
!this._startTime &&
(this._startTime = controller.startTime || Cesium.JulianDate.now())
this._mountPath()
!this._delegate.position && this._mountPosition()
this._mountedHook && this._mountedHook()
this._state = State.ADDED
}

/**
* remove from entities
* @private
*/
_onRemove() {
if (this._controller) {
this._controller.roamingLayer.remove(this._delegate)
this._isActive && this._controller.releaseCamera()
this._isActive = false
this._state = State.REMOVED
}
}

/**
* @param params
* @returns {boolean}
* @private
*/
_onPostUpdate(params) {
let currentTime = params.currentTime
let orientation = this._delegate.orientation.getValue(currentTime)
let timePos = this._timeLine[this._positionIndex]
if (timePos) {
let timeDiff = Cesium.JulianDate.secondsDifference(currentTime, timePos)
if (timeDiff >= 0 && timeDiff <= 1) {
let position = this._positions[this._positionIndex]
if (position && orientation) {
let mat = Cesium.Matrix3.fromQuaternion(orientation)
let mat4 = Cesium.Matrix4.fromRotationTranslation(
mat,
this._delegate.position.getValue(currentTime)
)
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._tickCallback &&
this._tickCallback(
position,
this._positionIndex + 1 === this._positions.length
)
this._positionIndex += 1
}
}
this._isActive &&
this._setCameraView(currentTime, params.viewMode, params.viewOption)
}

/**
* @private
*/
_onActive() {
this._isActive = true
}

/**
*
* @private
*/
_onRelease() {
this._isActive = false
}

/**
* Sets camera position
* @param currentTime
* @param viewMode
* @param viewOption
* @private
*/
_setCameraView(currentTime, viewMode, viewOption) {
let viewer = this._controller._viewer.delegate
let camera = this._controller._viewer.camera
let tickPosition = this._sampledPosition.getValue(currentTime)
let nextTickPosition = this._sampledPosition.getValue(
Cesium.JulianDate.addSeconds(currentTime, 1 / 60, new Cesium.JulianDate())
)
if (tickPosition && nextTickPosition && viewMode) {
if (viewMode === RoamingViewMode.TRACKED) {
viewer.trackedEntity = this._delegate
} else if (viewMode === RoamingViewMode.FP) {
let heading = Cesium.Math.heading(tickPosition, nextTickPosition)
let WGS84TickPosition = Transform.transformCartesianToWGS84(
tickPosition
)
if (!isNaN(viewOption.alt)) {
WGS84TickPosition.alt = viewOption.alt
}
camera.lookAt(
Transform.transformWGS84ToCartesian(WGS84TickPosition),
new Cesium.HeadingPitchRange(
heading,
Cesium.Math.toRadians(viewOption.pitch || 0),
viewOption.range || 10
)
)
} else if (viewMode === RoamingViewMode.TP) {
camera.lookAt(
tickPosition,
new Cesium.HeadingPitchRange(0, -90, viewOption.range || 1000)
)
}
} else {
camera.lookAtTransform(Cesium.Matrix4.IDENTITY)
viewer.trackedEntity = undefined
}
}

/**
* Mounts path
* @private
*/
_mountPath() {
if (this._options.showPath) {
this._delegate.availability = new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({
start: this._startTime,
stop: Cesium.JulianDate.addSeconds(
this._startTime,
this._duration,
new Cesium.JulianDate()
)
})
])
this._delegate.path = {
material: this._options.pathMaterial,
width: this._options.pathWidth,
leadTime: this._options.pathLeadTime
}
}
}

/**
* Mounts Position
* @private
*/
_mountPosition() {
if (
!this._startTime ||
!this._duration ||
!this._positions ||
!this._positions.length
) {
return false
}

let interval = 0
if (this._mode === 'speed') {
let v = Cesium.Math.distance(this._positions) / this._duration
this._timeLine = this._positions.map((item, index, arr) => {
if (index !== 0) {
interval += Cesium.Math.distance([arr[index - 1], item]) / v
}
return Cesium.JulianDate.addSeconds(
this._startTime,
interval,
new Cesium.JulianDate()
)
})
} else {
let len = this._positions.length
let interval = (this._duration - (this._duration % len)) / len
this._timeLine = this._positions.map((item, index) => {
return Cesium.JulianDate.addSeconds(
this._startTime,
index * interval,
new Cesium.JulianDate()
)
})
}
this._sampledPosition = new Cesium.SampledPositionProperty()
this._sampledPosition.addSamples(
this._timeLine,
Transform.transformWGS84ArrayToCartesianArray(this._positions)
)
this._delegate.position = this._sampledPosition
this._delegate.position.setInterpolationOptions({
interpolationDegree: 1,
interpolationAlgorithm: Cesium.LinearApproximation
})
this._delegate.orientation = new Cesium.VelocityOrientationProperty(
this._sampledPosition
)
}

/**
* Mounted Hook
* @private
*/
_mountedHook() {
this._controller.roamingLayer.add(this._delegate)
}

/**
* Sets positions
* @param positions
* @returns {RoamingPath}
*/
setPositions(positions) {
this._positions = Parse.parsePositions(positions)
this._mountPosition()
return this
}

/**
* Adds Position
* @param position
* @param duration
* @returns {RoamingPath}
*/
addPosition(position, duration) {
this._positions.push(Parse.parsePosition(position))
this._duration += duration
this._mountPosition()
return this
}

/**
* Sets mode
* @param mode
* @returns {RoamingPath}
*/
setMode(mode) {
this._mode = mode
this._mountPosition()
return this
}

/**
* Sets model
* @param modelPath
* @param style
* @returns {RoamingPath}
*/
setModel(modelPath, style) {
this._delegate.model = {
...style,
uri: modelPath
}
return this
}

/**
* Sets billboard
* @param icon
* @param style
* @returns {RoamingPath}
*/
setBillboard(icon, style) {
this._delegate.billboard = {
...style,
image: icon
}
return this
}

/**
* Sets label
* @param text
* @param style
* @returns {RoamingPath}
*/
setLabel(text, style) {
this._delegate.label = {
...style,
text: text
}
return this
}
}

export default RoamingPath

+ 13
- 0
modules/roaming/RoamingViewMode.js Visa fil

@@ -0,0 +1,13 @@
/**
* @Author: Caven
* @Date: 2020-08-05 10:51:13
*/

const RoamingViewMode = {
FP: '1',
TP: '2',
TRACKED: 'track',
FREE: 'free'
}

export default RoamingViewMode

+ 8
- 0
modules/roaming/index.js Visa fil

@@ -0,0 +1,8 @@
/**
* @Author: Caven
* @Date: 2020-04-13 09:32:31
*/

export { default as RoamingViewMode } from './RoamingViewMode'
export { default as RoamingPath } from './RoamingPath'
export { default as RoamingController } from './RoamingController'

Laddar…
Avbryt
Spara