vue-cesium
Version:
Vue 3.x components for CesiumJS.
357 lines (353 loc) • 13.8 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
"use strict";
class CameraFlightPath {
static createTween(scene, options) {
const { Cartesian2, Cartesian3, defaultValue, defined, DeveloperError, EasingFunction, Math: CesiumMath, SceneMode } = Cesium;
options = defaultValue(options, {});
let destination = options.destination;
if (!defined(scene)) {
throw new DeveloperError("scene is required.");
}
if (!defined(destination)) {
throw new DeveloperError("destination is required.");
}
const mode = scene.mode;
if (mode === SceneMode.MORPHING) {
return emptyFlight();
}
const convert = defaultValue(options.convert, true);
const projection = scene.mapProjection;
const ellipsoid = projection.ellipsoid;
const maximumHeight = options.maximumHeight;
const flyOverLongitude = options.flyOverLongitude;
const flyOverLongitudeWeight = options.flyOverLongitudeWeight;
const pitchAdjustHeight = options.pitchAdjustHeight;
let easingFunction = options.easingFunction;
if (convert && mode !== SceneMode.SCENE3D) {
ellipsoid.cartesianToCartographic(destination, scratchCartographic);
destination = projection.project(scratchCartographic, scratchDestination);
}
const camera = scene.camera;
const transform = options.endTransform;
if (defined(transform)) {
camera._setTransform(transform);
}
let duration = options.duration;
if (!defined(duration)) {
duration = Math.ceil(Cartesian3.distance(camera.position, destination) / 1e6) + 2;
duration = Math.min(duration, 3);
}
const heading = defaultValue(options.heading, 0);
const pitch = defaultValue(options.pitch, -CesiumMath.PI_OVER_TWO);
const roll = defaultValue(options.roll, 0);
const controller = scene.screenSpaceCameraController;
controller.enableInputs = false;
const complete = wrapCallback(controller, options.complete);
const cancel = wrapCallback(controller, options.cancel);
const frustum = camera.frustum;
let empty = scene.mode === SceneMode.SCENE2D;
empty = empty && Cartesian2.equalsEpsilon(camera.position, destination, CesiumMath.EPSILON6);
empty = empty && CesiumMath.equalsEpsilon(Math.max(frustum.right - frustum.left, frustum.top - frustum.bottom), destination.z, CesiumMath.EPSILON6);
empty = empty || scene.mode !== SceneMode.SCENE2D && Cartesian3.equalsEpsilon(destination, camera.position, CesiumMath.EPSILON10);
empty = empty && CesiumMath.equalsEpsilon(CesiumMath.negativePiToPi(heading), CesiumMath.negativePiToPi(camera.heading), CesiumMath.EPSILON10) && CesiumMath.equalsEpsilon(CesiumMath.negativePiToPi(pitch), CesiumMath.negativePiToPi(camera.pitch), CesiumMath.EPSILON10) && CesiumMath.equalsEpsilon(CesiumMath.negativePiToPi(roll), CesiumMath.negativePiToPi(camera.roll), CesiumMath.EPSILON10);
if (empty) {
return emptyFlight(complete, cancel);
}
const updateFunctions = new Array(4);
updateFunctions[SceneMode.SCENE2D] = createUpdate2D;
updateFunctions[SceneMode.SCENE3D] = createUpdate3D;
updateFunctions[SceneMode.COLUMBUS_VIEW] = createUpdateCV;
if (duration <= 0) {
const newOnComplete = function() {
const update2 = updateFunctions[mode](
scene,
1,
destination,
heading,
pitch,
roll,
maximumHeight,
flyOverLongitude,
flyOverLongitudeWeight,
pitchAdjustHeight
);
update2({ time: 1 });
if (typeof complete === "function") {
complete();
}
};
return emptyFlight(newOnComplete, cancel);
}
const update = updateFunctions[mode](
scene,
duration,
destination,
heading,
pitch,
roll,
maximumHeight,
flyOverLongitude,
flyOverLongitudeWeight,
pitchAdjustHeight
);
if (!defined(easingFunction)) {
const startHeight = camera.positionCartographic.height;
const endHeight = mode === SceneMode.SCENE3D ? ellipsoid.cartesianToCartographic(destination).height : destination.z;
if (startHeight > endHeight && startHeight > 11500) {
easingFunction = EasingFunction.CUBIC_OUT;
} else {
easingFunction = EasingFunction.QUINTIC_IN_OUT;
}
}
return {
duration,
easingFunction,
startObject: {
time: 0
},
stopObject: {
time: duration
},
update,
complete,
cancel
};
}
}
function getAltitude(frustum, dx, dy) {
const { PerspectiveFrustum, PerspectiveOffCenterFrustum } = Cesium;
let near;
let top;
let right;
if (frustum instanceof PerspectiveFrustum) {
const tanTheta = Math.tan(0.5 * frustum.fovy);
near = frustum.near;
top = frustum.near * tanTheta;
right = frustum.aspectRatio * top;
return Math.max(dx * near / right, dy * near / top);
} else if (frustum instanceof PerspectiveOffCenterFrustum) {
near = frustum.near;
top = frustum.top;
right = frustum.right;
return Math.max(dx * near / right, dy * near / top);
}
return Math.max(dx, dy);
}
const scratchCart = {};
const scratchCart2 = {};
function createPitchFunction(startPitch, endPitch, heightFunction, pitchAdjustHeight) {
const { defined, Math: CesiumMath } = Cesium;
if (defined(pitchAdjustHeight) && heightFunction(0.5) > pitchAdjustHeight) {
const startHeight = heightFunction(0);
const endHeight = heightFunction(1);
const middleHeight = heightFunction(0.5);
const d1 = middleHeight - startHeight;
const d2 = middleHeight - endHeight;
return function(time) {
const altitude = heightFunction(time);
if (time <= 0.5) {
const t1 = (altitude - startHeight) / d1;
return CesiumMath.lerp(startPitch, -CesiumMath.PI_OVER_TWO, t1);
}
const t2 = (altitude - endHeight) / d2;
return CesiumMath.lerp(-CesiumMath.PI_OVER_TWO, endPitch, 1 - t2);
};
}
return function(time) {
return CesiumMath.lerp(startPitch, endPitch, time);
};
}
function createHeightFunction(camera, destination, startHeight, endHeight, optionAltitude) {
const { Cartesian3, defined, Math: CesiumMath } = Cesium;
let altitude = optionAltitude;
const maxHeight = Math.max(startHeight, endHeight);
if (!defined(altitude)) {
const start = camera.position;
const end = destination;
const up = camera.up;
const right = camera.right;
const frustum = camera.frustum;
const diff = Cartesian3.subtract(start, end, scratchCart);
const verticalDistance = Cartesian3.magnitude(Cartesian3.multiplyByScalar(up, Cartesian3.dot(diff, up), scratchCart2));
const horizontalDistance = Cartesian3.magnitude(Cartesian3.multiplyByScalar(right, Cartesian3.dot(diff, right), scratchCart2));
altitude = Math.min(getAltitude(frustum, verticalDistance, horizontalDistance) * 0.2, 1e9);
}
if (maxHeight < altitude) {
const power = 8;
const factor = 1e6;
const s = -Math.pow((altitude - startHeight) * factor, 1 / power);
const e = Math.pow((altitude - endHeight) * factor, 1 / power);
return function(t) {
const x = t * (e - s) + s;
return -Math.pow(x, power) / factor + altitude;
};
}
return function(t) {
return CesiumMath.lerp(startHeight, endHeight, t);
};
}
function adjustAngleForLERP(startAngle, endAngle) {
const { Math: CesiumMath } = Cesium;
if (CesiumMath.equalsEpsilon(startAngle, CesiumMath.TWO_PI, CesiumMath.EPSILON11)) {
startAngle = 0;
}
if (endAngle > startAngle + Math.PI) {
startAngle += CesiumMath.TWO_PI;
} else if (endAngle < startAngle - Math.PI) {
startAngle -= CesiumMath.TWO_PI;
}
return startAngle;
}
const scratchStart = {};
function createUpdateCV(scene, duration, destination, heading, pitch, roll, optionAltitude) {
const { Cartesian2, Cartesian3, Math: CesiumMath } = Cesium;
const camera = scene.camera;
const start = Cartesian3.clone(camera.position, scratchStart);
const startPitch = camera.pitch;
const startHeading = adjustAngleForLERP(camera.heading, heading);
const startRoll = adjustAngleForLERP(camera.roll, roll);
const heightFunction = createHeightFunction(camera, destination, start.z, destination.z, optionAltitude);
function update(value) {
const time = value.time / duration;
camera.setView({
orientation: {
heading: CesiumMath.lerp(startHeading, heading, time),
pitch: CesiumMath.lerp(startPitch, pitch, time),
roll: CesiumMath.lerp(startRoll, roll, time)
}
});
Cartesian2.lerp(start, destination, time, camera.position);
camera.position.z = heightFunction(time);
}
return update;
}
function useLongestFlight(startCart, destCart) {
const { Math: CesiumMath } = Cesium;
if (startCart.longitude < destCart.longitude) {
startCart.longitude += CesiumMath.TWO_PI;
} else {
destCart.longitude += CesiumMath.TWO_PI;
}
}
function useShortestFlight(startCart, destCart) {
const { Math: CesiumMath } = Cesium;
const diff = startCart.longitude - destCart.longitude;
if (diff < -CesiumMath.PI) {
startCart.longitude += CesiumMath.TWO_PI;
} else if (diff > CesiumMath.PI) {
destCart.longitude += CesiumMath.TWO_PI;
}
}
const scratchStartCart = {};
const scratchEndCart = {};
function createUpdate3D(scene, duration, destination, heading, pitch, roll, optionAltitude, optionFlyOverLongitude, optionFlyOverLongitudeWeight, optionPitchAdjustHeight) {
const { Cartesian3, Cartographic, defined, Math: CesiumMath } = Cesium;
const camera = scene.camera;
const projection = scene.mapProjection;
const ellipsoid = projection.ellipsoid;
const startCart = Cartographic.clone(camera.positionCartographic, scratchStartCart);
const startPitch = camera.pitch;
const startHeading = adjustAngleForLERP(camera.heading, heading);
const startRoll = adjustAngleForLERP(camera.roll, roll);
const destCart = ellipsoid.cartesianToCartographic(destination, scratchEndCart);
startCart.longitude = CesiumMath.zeroToTwoPi(startCart.longitude);
destCart.longitude = CesiumMath.zeroToTwoPi(destCart.longitude);
let useLongFlight = false;
if (defined(optionFlyOverLongitude)) {
const hitLon = CesiumMath.zeroToTwoPi(optionFlyOverLongitude);
const lonMin = Math.min(startCart.longitude, destCart.longitude);
const lonMax = Math.max(startCart.longitude, destCart.longitude);
const hitInside = hitLon >= lonMin && hitLon <= lonMax;
if (defined(optionFlyOverLongitudeWeight)) {
const din = Math.abs(startCart.longitude - destCart.longitude);
const dot = CesiumMath.TWO_PI - din;
const hitDistance = hitInside ? din : dot;
const offDistance = hitInside ? dot : din;
if (hitDistance < offDistance * optionFlyOverLongitudeWeight && !hitInside) {
useLongFlight = true;
}
} else if (!hitInside) {
useLongFlight = true;
}
}
if (useLongFlight) {
useLongestFlight(startCart, destCart);
} else {
useShortestFlight(startCart, destCart);
}
const heightFunction = createHeightFunction(camera, destination, startCart.height, destCart.height, optionAltitude);
const pitchFunction = createPitchFunction(startPitch, pitch, heightFunction, optionPitchAdjustHeight);
function isolateUpdateFunction() {
const startLongitude = startCart.longitude;
const destLongitude = destCart.longitude;
const startLatitude = startCart.latitude;
const destLatitude = destCart.latitude;
return function update(value) {
const time = value.time / duration;
const position = Cartesian3.fromRadians(
CesiumMath.lerp(startLongitude, destLongitude, time),
CesiumMath.lerp(startLatitude, destLatitude, time),
heightFunction(time),
scene.globe.ellipsoid
);
camera.setView({
destination: position,
orientation: {
heading: CesiumMath.lerp(startHeading, heading, time),
pitch: pitchFunction(time),
roll: CesiumMath.lerp(startRoll, roll, time)
}
});
};
}
return isolateUpdateFunction();
}
function createUpdate2D(scene, duration, destination, heading, pitch, roll, optionAltitude) {
const { Cartesian2, Cartesian3, Math: CesiumMath } = Cesium;
const camera = scene.camera;
const start = Cartesian3.clone(camera.position, scratchStart);
const startHeading = adjustAngleForLERP(camera.heading, heading);
const startHeight = camera.frustum.right - camera.frustum.left;
const heightFunction = createHeightFunction(camera, destination, startHeight, destination.z, optionAltitude);
function update(value) {
const time = value.time / duration;
camera.setView({
orientation: {
heading: CesiumMath.lerp(startHeading, heading, time)
}
});
Cartesian2.lerp(start, destination, time, camera.position);
const zoom = heightFunction(time);
const frustum = camera.frustum;
const ratio = frustum.top / frustum.right;
const incrementAmount = (zoom - (frustum.right - frustum.left)) * 0.5;
frustum.right += incrementAmount;
frustum.left -= incrementAmount;
frustum.top = ratio * frustum.right;
frustum.bottom = -frustum.top;
}
return update;
}
const scratchCartographic = {};
const scratchDestination = {};
function emptyFlight(complete, cancel) {
return {
startObject: {},
stopObject: {},
duration: 0,
complete,
cancel
};
}
function wrapCallback(controller, cb) {
function wrapped() {
if (typeof cb === "function") {
cb();
}
controller.enableInputs = true;
}
return wrapped;
}
exports["default"] = CameraFlightPath;
//# sourceMappingURL=CameraFlightPath.js.map