
export class Roaming {
constructor(viewer, options) {
this.viewer = viewer;
this.updateOptionsParams(options);
this.entity = undefined;
this.start = undefined;
this.stop = undefined;
this.isPlay = true;
this.addRoamingHandler();
}
init(options) {
this.removeRoaming();
this.updateOptionsParams(options);
const result = this.loadData(this.data);
if (result && (typeof result === 'object' || typeof result === 'function') && typeof result.then === 'function') {
result.then((sections) => {
const data = sections.path;
this.createRoaming(data);
});
} else {
this.createRoaming(result);
}
}
updateOptionsParams(options) {
this.view = options.view;
this.model = options.model || {};
this.time = options.time;
this.data = options.data;
this.multiplier = options.speed || 10;
this.isPathShow = Cesium.defined(options.isPathShow) ? options.isPathShow : true;
this.multiplier = options.speed || 10;
}
createRoaming(data) {
if (data && Array.isArray(data)) {
const positions = this.processData(data);
this.property = this.computeRoamingLineProperty(positions, this.time);
this.createEntity(this.property, this.start, this.stop, this.isPathShow);
this.controlMouseEvent();
}
}
loadData(url) {
let data;
if (Cesium.defined(url) && typeof url === 'string') {
data = Cesium.Resource.fetchJson(url);
} else {
data = url;
}
return data;
}
processData(data) {
const positions = [];
data.forEach((position) => {
const car3Position = Cesium.Cartesian3.fromDegrees(position[0], position[1], position[2]);
positions.push(car3Position);
});
return positions;
}
computeRoamingLineProperty(coordinates, time) {
const property = new Cesium.SampledPositionProperty();
const coordinatesLength = coordinates.length;
const tempTime = time - (time % coordinatesLength);
const increment = tempTime / coordinatesLength;
const start = Cesium.JulianDate.now();
const stop = Cesium.JulianDate.addSeconds(start, tempTime, new Cesium.JulianDate());
this.start = start;
this.stop = stop;
this.setClockTime(start, stop, this.multiplier);
for (let i = 0; i < coordinatesLength; i += 1) {
const time1 = Cesium.JulianDate.addSeconds(start, i * increment, new Cesium.JulianDate());
const position = coordinates[i];
property.addSample(time1, position);
}
return property;
}
setClockTime(start, stop, multiplier) {
this.viewer.clock.startTime = start.clone();
this.viewer.clock.stopTime = stop.clone();
this.viewer.clock.currentTime = start.clone();
this.viewer.clock.multiplier = multiplier;
this.viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
this.viewer.clock.clockStep = Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER;
}
createEntity(position, start, stop, isPathShow) {
this.entity = this.viewer.entities.add({
availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
start,
stop,
})]),
position,
orientation: new Cesium.VelocityOrientationProperty(position),
model: {
uri: this.model.url,
minimumPixelSize: 64,
maximumSize: 128,
maximumScale: 200,
show: true,
silhouetteColor: Cesium.Color.WHITE,
debugWireframe: false,
debugShowBoundingVolume: false,
scale: 20,
runAnimations: true,
...this.model,
},
path: {
resolution: 1,
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.1,
color: Cesium.Color.YELLOW,
}),
width: 10,
show: isPathShow,
},
});
this.entity.position.setInterpolationOptions({
interpolationDegree: 5,
interpolationAlgorithm: Cesium.LagrangePolynomialApproximation,
});
this.addSceneEvent((time) => {
this.getRoamingPosition(time);
});
}
setRoamingPathVisibility(visible) {
if (this.entity) {
this.entity.path.show = visible;
}
this.isPathShow = visible;
}
setRoamingModelVisibility(visible) {
if (this.entity) {
this.entity.model.show = visible;
}
}
setCameraPosition(position, options) {
if (position) {
this.position2 = this.cartesian3ToWGS84(position);
let heading = 0;
if (this.position1) {
heading = this.bearing(this.position1.latitude, this.position1.longitude,
this.position2.latitude, this.position2.longitude);
}
this.position1 = this.cartesian3ToWGS84(position);
if (position) {
const dynamicHeading = Cesium.Math.toRadians(heading);
const pitch = Cesium.Math.toRadians(options.pitch || -20.0);
const range = options.range || 2000.0;
this.viewer.camera.lookAt(position, new Cesium.HeadingPitchRange(dynamicHeading, pitch, range));
}
}
}
bearing(startLat, startLng, destLat, destLng) {
startLat = this.toRadians(startLat);
startLng = this.toRadians(startLng);
destLat = this.toRadians(destLat);
destLng = this.toRadians(destLng);
const y = Math.sin(destLng - startLng) * Math.cos(destLat);
const x = Math.cos(startLat) * Math.sin(destLat) - Math.sin(startLat) * Math.cos(destLat) * Math.cos(destLng - startLng);
const brng = Math.atan2(y, x);
const brngDgr = this.toDegrees(brng);
return (brngDgr + 360) % 360;
}
cartesian3ToWGS84(point) {
const cartographic = Cesium.Cartographic.fromCartesian(point);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
const lng = Cesium.Math.toDegrees(cartographic.longitude);
const alt = cartographic.height;
return {
longitude: lng,
latitude: lat,
height: alt,
};
}
addSceneEvent(callback) {
if (this.handler instanceof Function) {
this.handler();
this.handler = null;
}
this.handler = this.viewer.scene.preRender.addEventListener((scene, time) => {
callback(time);
});
}
getRoamingPosition(time) {
if (this.entity) {
const position = this.entity.position.getValue(time);
this.setCameraPosition(position, this.view || {});
}
}
addRoamingHandler() {
if (!this.roamingHandler) {
this.roamingHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
}
}
controlMouseEvent() {
this.cancelMouseEvent();
this.addRoamingHandler();
this.roamingHandler.setInputAction(() => {
this.pauseOrContinue(!this.isPlay);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
this.roamingHandler.setInputAction(() => {
this.pauseOrContinue(this.isPlay);
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
}
cancelMouseEvent() {
if (this.roamingHandler && !this.roamingHandler.isDestroyed()) {
this.roamingHandler.destroy();
this.roamingHandler = null;
}
}
pauseOrContinue(state) {
if (state) {
if (!this.handler && this.entity) {
this.addSceneEvent((time) => {
this.getRoamingPosition(time);
});
}
} else if (this.handler) {
this.handler();
this.handler = null;
this.viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
}
this.viewer.clock.shouldAnimate = state;
}
changeRoamingSpeed(value) {
this.viewer.clock.multiplier = value;
}
removeRoaming() {
if (this.entity !== undefined) {
if (this.handler instanceof Function) {
this.handler();
this.handler = null;
}
this.viewer.entities.remove(this.entity);
this.data = null;
this.cancelMouseEvent();
this.viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
this.entity = null;
}
}
}