mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-15 15:52:21 +00:00
refactor(launches,cctv,alpr): take vector maths from src/geo
Launches selection/replay/panel/policy/policyHelpers/state/camera, CCTV geometry/model/projection/navigation/cards/geometryQueue/state and ALPR model/visuals now use src/geo for Math, Cartesian2/3, Cartographic, Matrix3/4, Quaternion and ENU frames. launches/paths.js keeps Cesium (EllipsoidGeodesic). In camera.js, EllipsoidGeodesic, BoundingSphere.fromPoints/union and the BoundingSphere constructor stay on Cesium; the geo Cartographics passed into EllipsoidGeodesic are only read field by field and cloned there (computeProperties). The CCTV plane orientation stays a Cesium Quaternion and plane dimensions a Cesium Cartesian2 (entity ConstantProperty values). launches-layer and alpr-cameras own the src/geo files.
This commit is contained in:
1 parent
ee8b94d987
commit
a915bdb3e5
17 files changed
+215
-214
No files matched your search
@@ -1145,7 +1145,21 @@
|
|||||||
"src/layers/launches/source.js",
|
"src/layers/launches/source.js",
|
||||||
"src/layers/launches/state.js",
|
"src/layers/launches/state.js",
|
||||||
"src/layers/launches/testing.js",
|
"src/layers/launches/testing.js",
|
||||||
"src/data/inputOwnership.js"
|
"src/data/inputOwnership.js",
|
||||||
|
"src/geo/index.js",
|
||||||
|
"src/geo/math.js",
|
||||||
|
"src/geo/ellipsoid.js",
|
||||||
|
"src/geo/cartographic.js",
|
||||||
|
"src/geo/cartesian2.js",
|
||||||
|
"src/geo/cartesian3.js",
|
||||||
|
"src/geo/matrix3.js",
|
||||||
|
"src/geo/matrix4.js",
|
||||||
|
"src/geo/quaternion.js",
|
||||||
|
"src/geo/transforms.js",
|
||||||
|
"src/geo/scaleToGeodeticSurface.js",
|
||||||
|
"src/geo/check.js",
|
||||||
|
"src/geo/debug.js",
|
||||||
|
"src/geo/developerError.js"
|
||||||
],
|
],
|
||||||
"external": ["cesium"]
|
"external": ["cesium"]
|
||||||
},
|
},
|
||||||
@@ -1406,7 +1420,21 @@
|
|||||||
"src/sources/httpBody.js",
|
"src/sources/httpBody.js",
|
||||||
"src/sources/vectorTiles.js",
|
"src/sources/vectorTiles.js",
|
||||||
"src/sources/phaseTiming.js",
|
"src/sources/phaseTiming.js",
|
||||||
"src/layers/alpr/floors.js"
|
"src/layers/alpr/floors.js",
|
||||||
|
"src/geo/index.js",
|
||||||
|
"src/geo/math.js",
|
||||||
|
"src/geo/ellipsoid.js",
|
||||||
|
"src/geo/cartographic.js",
|
||||||
|
"src/geo/cartesian2.js",
|
||||||
|
"src/geo/cartesian3.js",
|
||||||
|
"src/geo/matrix3.js",
|
||||||
|
"src/geo/matrix4.js",
|
||||||
|
"src/geo/quaternion.js",
|
||||||
|
"src/geo/transforms.js",
|
||||||
|
"src/geo/scaleToGeodeticSurface.js",
|
||||||
|
"src/geo/check.js",
|
||||||
|
"src/geo/debug.js",
|
||||||
|
"src/geo/developerError.js"
|
||||||
],
|
],
|
||||||
"external": ["cesium", "@mapbox/vector-tile", "pbf"]
|
"external": ["cesium", "@mapbox/vector-tile", "pbf"]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import * as Cesium from 'cesium';
|
import * as geo from '../../geo/index.js';
|
||||||
import { EARTH_MEAN_RADIUS_M } from './policy.js';
|
import { EARTH_MEAN_RADIUS_M } from './policy.js';
|
||||||
export * from './records.js';
|
export * from './records.js';
|
||||||
|
|
||||||
@@ -12,9 +12,9 @@ export * from './records.js';
|
|||||||
*/
|
*/
|
||||||
export function destinationPointDeg(latDeg, lonDeg, bearingDeg, distanceM) {
|
export function destinationPointDeg(latDeg, lonDeg, bearingDeg, distanceM) {
|
||||||
const angularDistance = distanceM / EARTH_MEAN_RADIUS_M;
|
const angularDistance = distanceM / EARTH_MEAN_RADIUS_M;
|
||||||
const bearing = Cesium.Math.toRadians(bearingDeg);
|
const bearing = geo.math.toRadians(bearingDeg);
|
||||||
const lat1 = Cesium.Math.toRadians(latDeg);
|
const lat1 = geo.math.toRadians(latDeg);
|
||||||
const lon1 = Cesium.Math.toRadians(lonDeg);
|
const lon1 = geo.math.toRadians(lonDeg);
|
||||||
const lat2 = Math.asin(
|
const lat2 = Math.asin(
|
||||||
Math.sin(lat1) * Math.cos(angularDistance) +
|
Math.sin(lat1) * Math.cos(angularDistance) +
|
||||||
Math.cos(lat1) * Math.sin(angularDistance) * Math.cos(bearing),
|
Math.cos(lat1) * Math.sin(angularDistance) * Math.cos(bearing),
|
||||||
@@ -26,8 +26,8 @@ export function destinationPointDeg(latDeg, lonDeg, bearingDeg, distanceM) {
|
|||||||
Math.cos(angularDistance) - Math.sin(lat1) * Math.sin(lat2),
|
Math.cos(angularDistance) - Math.sin(lat1) * Math.sin(lat2),
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
latitude: Cesium.Math.toDegrees(lat2),
|
latitude: geo.math.toDegrees(lat2),
|
||||||
longitude: Cesium.Math.toDegrees(lon2),
|
longitude: geo.math.toDegrees(lon2),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import * as Cesium from 'cesium';
|
import * as geo from '../../geo/index.js';
|
||||||
import { destinationPointDeg } from './model.js';
|
import { destinationPointDeg } from './model.js';
|
||||||
import {
|
import {
|
||||||
DIRECTION_CONE_M,
|
DIRECTION_CONE_M,
|
||||||
@@ -95,13 +95,9 @@ export function directionWedgePositions(record, heightM = 0, heightAt = null) {
|
|||||||
return Number.isFinite(height) ? height : heightM;
|
return Number.isFinite(height) ? height : heightM;
|
||||||
};
|
};
|
||||||
return [
|
return [
|
||||||
Cesium.Cartesian3.fromDegrees(record.longitude, record.latitude, heightM),
|
geo.cartesian3.fromDegrees(record.longitude, record.latitude, heightM),
|
||||||
Cesium.Cartesian3.fromDegrees(left.longitude, left.latitude, corner(left)),
|
geo.cartesian3.fromDegrees(left.longitude, left.latitude, corner(left)),
|
||||||
Cesium.Cartesian3.fromDegrees(
|
geo.cartesian3.fromDegrees(right.longitude, right.latitude, corner(right)),
|
||||||
right.longitude,
|
|
||||||
right.latitude,
|
|
||||||
corner(right),
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
CCTV_FRAME_CANVAS_H,
|
CCTV_FRAME_CANVAS_H,
|
||||||
applyFrameResult,
|
applyFrameResult,
|
||||||
} from '../../data/cctvCards.js';
|
} from '../../data/cctvCards.js';
|
||||||
import * as Cesium from 'cesium';
|
import * as geo from '../../geo/index.js';
|
||||||
import { horizonOccluder } from '../../data/iconOrientation.js';
|
import { horizonOccluder } from '../../data/iconOrientation.js';
|
||||||
import { selectCctvLod, applyEvictionGrace } from '../../data/cctvLod.js';
|
import { selectCctvLod, applyEvictionGrace } from '../../data/cctvLod.js';
|
||||||
import {
|
import {
|
||||||
@@ -85,8 +85,8 @@ export function createCards({ state: layerState, services, parts, source }) {
|
|||||||
}
|
}
|
||||||
const scene = layerState._viewer.scene;
|
const scene = layerState._viewer.scene;
|
||||||
const carto = layerState._viewer.camera.positionCartographic;
|
const carto = layerState._viewer.camera.positionCartographic;
|
||||||
const viewerLat = carto ? Cesium.Math.toDegrees(carto.latitude) : 0;
|
const viewerLat = carto ? geo.math.toDegrees(carto.latitude) : 0;
|
||||||
const viewerLon = carto ? Cesium.Math.toDegrees(carto.longitude) : 0;
|
const viewerLon = carto ? geo.math.toDegrees(carto.longitude) : 0;
|
||||||
// The active camera is excluded from ambient selection ALWAYS (not just
|
// The active camera is excluded from ambient selection ALWAYS (not just
|
||||||
// after its async activation settles). It is published separately in the
|
// after its async activation settles). It is published separately in the
|
||||||
// protected lane below, and grace never applies to it.
|
// protected lane below, and grace never applies to it.
|
||||||
|
|||||||
+13
-16
@@ -1,4 +1,5 @@
|
|||||||
import * as Cesium from 'cesium';
|
import * as Cesium from 'cesium';
|
||||||
|
import * as geo from '../../geo/index.js';
|
||||||
import { createFrustumVolumePrimitive } from '../../data/cctvViewshed.js';
|
import { createFrustumVolumePrimitive } from '../../data/cctvViewshed.js';
|
||||||
import {
|
import {
|
||||||
PROJECTION_VERT_ASPECT,
|
PROJECTION_VERT_ASPECT,
|
||||||
@@ -272,7 +273,7 @@ export function createGeometry({ state: layerState, services, parts, source }) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function frustumCartesians(geometry) {
|
function frustumCartesians(geometry) {
|
||||||
const at = (p) => Cesium.Cartesian3.fromDegrees(p.lon, p.lat, p.alt);
|
const at = (p) => geo.cartesian3.fromDegrees(p.lon, p.lat, p.alt);
|
||||||
return {
|
return {
|
||||||
mount: at(geometry.mount),
|
mount: at(geometry.mount),
|
||||||
capCenter: at(geometry.capCenter),
|
capCenter: at(geometry.capCenter),
|
||||||
@@ -280,7 +281,7 @@ export function createGeometry({ state: layerState, services, parts, source }) {
|
|||||||
tr: at(geometry.corners.tr),
|
tr: at(geometry.corners.tr),
|
||||||
br: at(geometry.corners.br),
|
br: at(geometry.corners.br),
|
||||||
bl: at(geometry.corners.bl),
|
bl: at(geometry.corners.bl),
|
||||||
label: Cesium.Cartesian3.fromDegrees(
|
label: geo.cartesian3.fromDegrees(
|
||||||
geometry.topCenter.lon,
|
geometry.topCenter.lon,
|
||||||
geometry.topCenter.lat,
|
geometry.topCenter.lat,
|
||||||
geometry.topCenter.alt + 1.2,
|
geometry.topCenter.alt + 1.2,
|
||||||
@@ -301,26 +302,22 @@ export function createGeometry({ state: layerState, services, parts, source }) {
|
|||||||
function frustumFrameEcef(camera, atPos) {
|
function frustumFrameEcef(camera, atPos) {
|
||||||
const h = parts.model.toRad(camera.headingDeg);
|
const h = parts.model.toRad(camera.headingDeg);
|
||||||
const p = parts.model.toRad(camera.pitchDeg);
|
const p = parts.model.toRad(camera.pitchDeg);
|
||||||
const enu = Cesium.Transforms.eastNorthUpToFixedFrame(atPos);
|
const enu = geo.transforms.eastNorthUpToFixedFrame(atPos);
|
||||||
const rot = Cesium.Matrix4.getMatrix3(enu, new Cesium.Matrix3());
|
const rot = geo.matrix4.getMatrix3(enu, geo.matrix3.create());
|
||||||
// ENU components: view axis + the perpendicular "up" of the pitched cap.
|
// ENU components: view axis + the perpendicular "up" of the pitched cap.
|
||||||
const dirEnu = new Cesium.Cartesian3(
|
const dirEnu = geo.cartesian3.create(
|
||||||
Math.sin(h) * Math.cos(p),
|
Math.sin(h) * Math.cos(p),
|
||||||
Math.cos(h) * Math.cos(p),
|
Math.cos(h) * Math.cos(p),
|
||||||
Math.sin(p),
|
Math.sin(p),
|
||||||
);
|
);
|
||||||
const upEnu = new Cesium.Cartesian3(
|
const upEnu = geo.cartesian3.create(
|
||||||
-Math.sin(p) * Math.sin(h),
|
-Math.sin(p) * Math.sin(h),
|
||||||
-Math.sin(p) * Math.cos(h),
|
-Math.sin(p) * Math.cos(h),
|
||||||
Math.cos(p),
|
Math.cos(p),
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
dir: Cesium.Matrix3.multiplyByVector(
|
dir: geo.matrix3.multiplyByVector(rot, dirEnu, geo.cartesian3.create()),
|
||||||
rot,
|
up: geo.matrix3.multiplyByVector(rot, upEnu, geo.cartesian3.create()),
|
||||||
dirEnu,
|
|
||||||
new Cesium.Cartesian3(),
|
|
||||||
),
|
|
||||||
up: Cesium.Matrix3.multiplyByVector(rot, upEnu, new Cesium.Cartesian3()),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -462,10 +459,10 @@ export function createGeometry({ state: layerState, services, parts, source }) {
|
|||||||
sampleMeshFloorCells(layerState._viewer?.scene, [point], {
|
sampleMeshFloorCells(layerState._viewer?.scene, [point], {
|
||||||
excludeObjects: excludeObjects.filter(Boolean),
|
excludeObjects: excludeObjects.filter(Boolean),
|
||||||
viewerLat: viewerCarto
|
viewerLat: viewerCarto
|
||||||
? Cesium.Math.toDegrees(viewerCarto.latitude)
|
? geo.math.toDegrees(viewerCarto.latitude)
|
||||||
: undefined,
|
: undefined,
|
||||||
viewerLon: viewerCarto
|
viewerLon: viewerCarto
|
||||||
? Cesium.Math.toDegrees(viewerCarto.longitude)
|
? geo.math.toDegrees(viewerCarto.longitude)
|
||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -623,7 +620,7 @@ export function createGeometry({ state: layerState, services, parts, source }) {
|
|||||||
if (Math.abs(rangeScale - 1) > 0.0001) return; // slider overrides the clamp
|
if (Math.abs(rangeScale - 1) > 0.0001) return; // slider overrides the clamp
|
||||||
try {
|
try {
|
||||||
const mountAlt = parts.ground.groundAltFor(record) + camera.mountHeightM;
|
const mountAlt = parts.ground.groundAltFor(record) + camera.mountHeightM;
|
||||||
const mountPos = Cesium.Cartesian3.fromDegrees(
|
const mountPos = geo.cartesian3.fromDegrees(
|
||||||
camera.lon,
|
camera.lon,
|
||||||
camera.lat,
|
camera.lat,
|
||||||
mountAlt,
|
mountAlt,
|
||||||
@@ -637,7 +634,7 @@ export function createGeometry({ state: layerState, services, parts, source }) {
|
|||||||
}
|
}
|
||||||
const hit = scene.pickFromRay(new Cesium.Ray(mountPos, dir), exclude);
|
const hit = scene.pickFromRay(new Cesium.Ray(mountPos, dir), exclude);
|
||||||
if (!hit?.position) return;
|
if (!hit?.position) return;
|
||||||
const dist = Cesium.Cartesian3.distance(mountPos, hit.position);
|
const dist = geo.cartesian3.distance(mountPos, hit.position);
|
||||||
record.probeClampRangeM = activationProbeClampRange(camera.rangeM, dist);
|
record.probeClampRangeM = activationProbeClampRange(camera.rangeM, dist);
|
||||||
} catch {
|
} catch {
|
||||||
// probe failure → keep the unclamped range
|
// probe failure → keep the unclamped range
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import * as Cesium from 'cesium';
|
import * as geo from '../../geo/index.js';
|
||||||
import {
|
import {
|
||||||
GEO_PROGRESS_NOTIFY_INTERVAL_MS,
|
GEO_PROGRESS_NOTIFY_INTERVAL_MS,
|
||||||
GEO_PROGRESS_NOTIFY_BATCH_LIMIT,
|
GEO_PROGRESS_NOTIFY_BATCH_LIMIT,
|
||||||
@@ -298,10 +298,10 @@ export function createGeometryQueue({
|
|||||||
const active = parts.selection.getActiveRecord();
|
const active = parts.selection.getActiveRecord();
|
||||||
const carto = layerState._viewer?.camera?.positionCartographic;
|
const carto = layerState._viewer?.camera?.positionCartographic;
|
||||||
const refLat = carto
|
const refLat = carto
|
||||||
? Cesium.Math.toDegrees(carto.latitude)
|
? geo.math.toDegrees(carto.latitude)
|
||||||
: (active?.camera.lat ?? 0);
|
: (active?.camera.lat ?? 0);
|
||||||
const refLon = carto
|
const refLon = carto
|
||||||
? Cesium.Math.toDegrees(carto.longitude)
|
? geo.math.toDegrees(carto.longitude)
|
||||||
: (active?.camera.lon ?? 0);
|
: (active?.camera.lon ?? 0);
|
||||||
const pending = layerState._records
|
const pending = layerState._records
|
||||||
.filter((record) => record !== active)
|
.filter((record) => record !== active)
|
||||||
|
|||||||
+23
-20
@@ -1,4 +1,5 @@
|
|||||||
import * as Cesium from 'cesium';
|
import * as Cesium from 'cesium';
|
||||||
|
import * as geo from '../../geo/index.js';
|
||||||
import { staticFrameRefreshMs } from '../../data/cctvLod.js';
|
import { staticFrameRefreshMs } from '../../data/cctvLod.js';
|
||||||
import { frameFetchDue, cardFetchPolicy } from '../../data/cctvCards.js';
|
import { frameFetchDue, cardFetchPolicy } from '../../data/cctvCards.js';
|
||||||
import { DEFAULT_CAMERA_CALIBRATION } from './policy.js';
|
import { DEFAULT_CAMERA_CALIBRATION } from './policy.js';
|
||||||
@@ -13,7 +14,7 @@ export function createModel({ state: layerState, services, parts, source }) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function toRad(deg) {
|
function toRad(deg) {
|
||||||
return Cesium.Math.toRadians(deg);
|
return geo.math.toRadians(deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -283,8 +284,8 @@ export function createModel({ state: layerState, services, parts, source }) {
|
|||||||
const lon2 = lon1 + Math.atan2(y, x);
|
const lon2 = lon1 + Math.atan2(y, x);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
lat: Cesium.Math.toDegrees(lat2),
|
lat: geo.math.toDegrees(lat2),
|
||||||
lon: Cesium.Math.toDegrees(lon2),
|
lon: geo.math.toDegrees(lon2),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,8 +329,8 @@ export function createModel({ state: layerState, services, parts, source }) {
|
|||||||
function currentViewContext() {
|
function currentViewContext() {
|
||||||
const carto = layerState._viewer?.camera?.positionCartographic;
|
const carto = layerState._viewer?.camera?.positionCartographic;
|
||||||
if (!carto) return 'none';
|
if (!carto) return 'none';
|
||||||
const lat = Cesium.Math.toDegrees(carto.latitude);
|
const lat = geo.math.toDegrees(carto.latitude);
|
||||||
const lon = Cesium.Math.toDegrees(carto.longitude);
|
const lon = geo.math.toDegrees(carto.longitude);
|
||||||
const alt = carto.height || 0;
|
const alt = carto.height || 0;
|
||||||
const zoomBucket =
|
const zoomBucket =
|
||||||
alt < 1500
|
alt < 1500
|
||||||
@@ -404,24 +405,26 @@ export function createModel({ state: layerState, services, parts, source }) {
|
|||||||
|
|
||||||
function planeOrientationFor(camera, capCenterPos) {
|
function planeOrientationFor(camera, capCenterPos) {
|
||||||
const frame = parts.geometry.frustumFrameEcef(camera, capCenterPos);
|
const frame = parts.geometry.frustumFrameEcef(camera, capCenterPos);
|
||||||
const right = Cesium.Cartesian3.cross(
|
const right = geo.cartesian3.cross(
|
||||||
frame.dir,
|
frame.dir,
|
||||||
frame.up,
|
frame.up,
|
||||||
new Cesium.Cartesian3(),
|
geo.cartesian3.create(),
|
||||||
);
|
);
|
||||||
const normal = Cesium.Cartesian3.negate(frame.dir, new Cesium.Cartesian3());
|
const normal = geo.cartesian3.negate(frame.dir, geo.cartesian3.create());
|
||||||
const m = new Cesium.Matrix3(
|
// Column-major rotation whose columns are right, up and normal.
|
||||||
right.x,
|
const m = geo.matrix3.create();
|
||||||
frame.up.x,
|
m[0] = right.x;
|
||||||
normal.x,
|
m[1] = right.y;
|
||||||
right.y,
|
m[2] = right.z;
|
||||||
frame.up.y,
|
m[3] = frame.up.x;
|
||||||
normal.y,
|
m[4] = frame.up.y;
|
||||||
right.z,
|
m[5] = frame.up.z;
|
||||||
frame.up.z,
|
m[6] = normal.x;
|
||||||
normal.z,
|
m[7] = normal.y;
|
||||||
);
|
m[8] = normal.z;
|
||||||
return Cesium.Quaternion.fromRotationMatrix(m);
|
// The quaternion becomes an entity's ConstantProperty value, so it stays a
|
||||||
|
// Cesium Quaternion there (that property clones and compares its value).
|
||||||
|
return geo.quaternion.fromRotationMatrix(m, new Cesium.Quaternion());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import * as Cesium from 'cesium';
|
import * as Cesium from 'cesium';
|
||||||
|
import * as geo from '../../geo/index.js';
|
||||||
import { CCTV_FOCUS_RESULT } from './policy.js';
|
import { CCTV_FOCUS_RESULT } from './policy.js';
|
||||||
|
|
||||||
export function createNavigation({
|
export function createNavigation({
|
||||||
@@ -15,8 +16,8 @@ export function createNavigation({
|
|||||||
function nearestCameraIdToViewer() {
|
function nearestCameraIdToViewer() {
|
||||||
const carto = layerState._viewer?.camera?.positionCartographic;
|
const carto = layerState._viewer?.camera?.positionCartographic;
|
||||||
if (!carto || !layerState._records.length) return null;
|
if (!carto || !layerState._records.length) return null;
|
||||||
const lat = Cesium.Math.toDegrees(carto.latitude);
|
const lat = geo.math.toDegrees(carto.latitude);
|
||||||
const lon = Cesium.Math.toDegrees(carto.longitude);
|
const lon = geo.math.toDegrees(carto.longitude);
|
||||||
|
|
||||||
let best = null;
|
let best = null;
|
||||||
for (const record of layerState._records) {
|
for (const record of layerState._records) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { attachCctvVideo } from './videoPlayback.js';
|
import { attachCctvVideo } from './videoPlayback.js';
|
||||||
import * as Cesium from 'cesium';
|
import * as Cesium from 'cesium';
|
||||||
|
import * as geo from '../../geo/index.js';
|
||||||
import {
|
import {
|
||||||
CCTV_PROJECTION_OVERLAY_SOURCE_ID,
|
CCTV_PROJECTION_OVERLAY_SOURCE_ID,
|
||||||
CCTV_PROJECTION_OVERLAY_SOURCE_OPTIONS,
|
CCTV_PROJECTION_OVERLAY_SOURCE_OPTIONS,
|
||||||
@@ -77,7 +78,7 @@ export function createProjection({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (runtime.labelPosition) {
|
if (runtime.labelPosition) {
|
||||||
Cesium.Cartesian3.clone(positions.label, runtime.labelPosition);
|
geo.cartesian3.clone(positions.label, runtime.labelPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,8 +125,8 @@ export function createProjection({
|
|||||||
/** Create the native monitor plane plus its cached host-label presentation. */
|
/** Create the native monitor plane plus its cached host-label presentation. */
|
||||||
|
|
||||||
function createProjectionPlane(record, runtime, geometry, positions) {
|
function createProjectionPlane(record, runtime, geometry, positions) {
|
||||||
runtime.labelPosition ||= new Cesium.Cartesian3();
|
runtime.labelPosition ||= geo.cartesian3.create();
|
||||||
Cesium.Cartesian3.clone(positions.label, runtime.labelPosition);
|
geo.cartesian3.clone(positions.label, runtime.labelPosition);
|
||||||
runtime.cameraId = String(record.camera.id);
|
runtime.cameraId = String(record.camera.id);
|
||||||
runtime.overlayEntry = createCctvProjectionOverlayEntry({
|
runtime.overlayEntry = createCctvProjectionOverlayEntry({
|
||||||
cameraId: runtime.cameraId,
|
cameraId: runtime.cameraId,
|
||||||
@@ -142,7 +143,7 @@ export function createProjection({
|
|||||||
positions.capCenter,
|
positions.capCenter,
|
||||||
),
|
),
|
||||||
plane: {
|
plane: {
|
||||||
plane: new Cesium.Plane(Cesium.Cartesian3.UNIT_Z, 0.0),
|
plane: new Cesium.Plane(geo.cartesian3.UNIT_Z, 0.0),
|
||||||
dimensions: new Cesium.Cartesian2(
|
dimensions: new Cesium.Cartesian2(
|
||||||
geometry.halfW * 2,
|
geometry.halfW * 2,
|
||||||
geometry.halfH * 2,
|
geometry.halfH * 2,
|
||||||
@@ -186,7 +187,7 @@ export function createProjection({
|
|||||||
video: null,
|
video: null,
|
||||||
planeEntity: null,
|
planeEntity: null,
|
||||||
cameraId: String(record.camera.id),
|
cameraId: String(record.camera.id),
|
||||||
labelPosition: new Cesium.Cartesian3(),
|
labelPosition: geo.cartesian3.create(),
|
||||||
overlayEntry: null,
|
overlayEntry: null,
|
||||||
planeMaterial: null,
|
planeMaterial: null,
|
||||||
buffers: null,
|
buffers: null,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import * as Cesium from 'cesium';
|
import * as geo from '../../geo/index.js';
|
||||||
|
|
||||||
export function createState({ services }) {
|
export function createState({ services }) {
|
||||||
const {
|
const {
|
||||||
@@ -74,7 +74,7 @@ export function createState({ services }) {
|
|||||||
|
|
||||||
layerState._activeFocusStyleCount = 0;
|
layerState._activeFocusStyleCount = 0;
|
||||||
|
|
||||||
layerState._scratchFocusScreen = new Cesium.Cartesian2();
|
layerState._scratchFocusScreen = geo.cartesian2.create();
|
||||||
|
|
||||||
// Staggered geometry-load queue state (see startGeometryLoadQueue).
|
// Staggered geometry-load queue state (see startGeometryLoadQueue).
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import * as Cesium from 'cesium';
|
import * as Cesium from 'cesium';
|
||||||
|
import * as geo from '../../geo/index.js';
|
||||||
import {
|
import {
|
||||||
REPLAY_ASCENT_CAMERA_OFFSET_RAD,
|
REPLAY_ASCENT_CAMERA_OFFSET_RAD,
|
||||||
REPLAY_ORBIT_CAMERA_OFFSET_RAD,
|
REPLAY_ORBIT_CAMERA_OFFSET_RAD,
|
||||||
@@ -18,12 +19,12 @@ export function createCamera({ state: layerState, services, parts, source }) {
|
|||||||
if (!path?.length) return fallback;
|
if (!path?.length) return fallback;
|
||||||
const current = parts.paths.samplePath(path, progress);
|
const current = parts.paths.samplePath(path, progress);
|
||||||
const currentCartographic =
|
const currentCartographic =
|
||||||
Cesium.Ellipsoid.WGS84.cartesianToCartographic(current);
|
geo.ellipsoid.WGS84.cartesianToCartographic(current);
|
||||||
if (!currentCartographic) return fallback;
|
if (!currentCartographic) return fallback;
|
||||||
for (const step of [0.01, 0.025, 0.05, 0.1, 0.2]) {
|
for (const step of [0.01, 0.025, 0.05, 0.1, 0.2]) {
|
||||||
const next = parts.paths.samplePath(path, Math.min(1, progress + step));
|
const next = parts.paths.samplePath(path, Math.min(1, progress + step));
|
||||||
const nextCartographic =
|
const nextCartographic =
|
||||||
Cesium.Ellipsoid.WGS84.cartesianToCartographic(next);
|
geo.ellipsoid.WGS84.cartesianToCartographic(next);
|
||||||
if (!nextCartographic) continue;
|
if (!nextCartographic) continue;
|
||||||
const geodesic = new Cesium.EllipsoidGeodesic(
|
const geodesic = new Cesium.EllipsoidGeodesic(
|
||||||
currentCartographic,
|
currentCartographic,
|
||||||
@@ -36,7 +37,7 @@ export function createCamera({ state: layerState, services, parts, source }) {
|
|||||||
// HeadingPitchRange positions the camera opposite its heading vector.
|
// HeadingPitchRange positions the camera opposite its heading vector.
|
||||||
// Passing the forward path heading therefore keeps the camera behind
|
// Passing the forward path heading therefore keeps the camera behind
|
||||||
// the vehicle, with the remaining ascent receding into the scene.
|
// the vehicle, with the remaining ascent receding into the scene.
|
||||||
return Cesium.Math.zeroToTwoPi(geodesic.startHeading);
|
return geo.math.zeroToTwoPi(geodesic.startHeading);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fallback;
|
return fallback;
|
||||||
@@ -49,8 +50,8 @@ export function createCamera({ state: layerState, services, parts, source }) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function replayInitialCameraHeading(path) {
|
function replayInitialCameraHeading(path) {
|
||||||
return Cesium.Math.zeroToTwoPi(
|
return geo.math.zeroToTwoPi(
|
||||||
cameraHeadingForPath(path, 0, Math.PI) + Cesium.Math.PI_OVER_TWO,
|
cameraHeadingForPath(path, 0, Math.PI) + geo.math.PI_OVER_TWO,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,10 +64,10 @@ export function createCamera({ state: layerState, services, parts, source }) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function replayChaseCameraHeading(pathHeading, orbitBlend = 0) {
|
function replayChaseCameraHeading(pathHeading, orbitBlend = 0) {
|
||||||
const blend = Cesium.Math.clamp(Number(orbitBlend) || 0, 0, 1);
|
const blend = geo.math.clamp(Number(orbitBlend) || 0, 0, 1);
|
||||||
return Cesium.Math.zeroToTwoPi(
|
return geo.math.zeroToTwoPi(
|
||||||
pathHeading +
|
pathHeading +
|
||||||
Cesium.Math.lerp(
|
geo.math.lerp(
|
||||||
REPLAY_ASCENT_CAMERA_OFFSET_RAD,
|
REPLAY_ASCENT_CAMERA_OFFSET_RAD,
|
||||||
REPLAY_ORBIT_CAMERA_OFFSET_RAD,
|
REPLAY_ORBIT_CAMERA_OFFSET_RAD,
|
||||||
blend,
|
blend,
|
||||||
@@ -86,17 +87,17 @@ export function createCamera({ state: layerState, services, parts, source }) {
|
|||||||
function smoothReplayCameraHeading(
|
function smoothReplayCameraHeading(
|
||||||
previous,
|
previous,
|
||||||
desired,
|
desired,
|
||||||
maxStepRad = Cesium.Math.toRadians(2),
|
maxStepRad = geo.math.toRadians(2),
|
||||||
) {
|
) {
|
||||||
if (!Number.isFinite(previous)) return Cesium.Math.zeroToTwoPi(desired);
|
if (!Number.isFinite(previous)) return geo.math.zeroToTwoPi(desired);
|
||||||
if (!Number.isFinite(desired)) return Cesium.Math.zeroToTwoPi(previous);
|
if (!Number.isFinite(desired)) return geo.math.zeroToTwoPi(previous);
|
||||||
const delta = Cesium.Math.negativePiToPi(desired - previous);
|
const delta = geo.math.negativePiToPi(desired - previous);
|
||||||
const step = Cesium.Math.clamp(
|
const step = geo.math.clamp(
|
||||||
delta,
|
delta,
|
||||||
-Math.abs(maxStepRad),
|
-Math.abs(maxStepRad),
|
||||||
Math.abs(maxStepRad),
|
Math.abs(maxStepRad),
|
||||||
);
|
);
|
||||||
return Cesium.Math.zeroToTwoPi(previous + step);
|
return geo.math.zeroToTwoPi(previous + step);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -108,7 +109,7 @@ export function createCamera({ state: layerState, services, parts, source }) {
|
|||||||
|
|
||||||
function missionZoomPitch(rangeM) {
|
function missionZoomPitch(rangeM) {
|
||||||
const range = Math.max(0, Number(rangeM) || 0);
|
const range = Math.max(0, Number(rangeM) || 0);
|
||||||
const blend = Cesium.Math.clamp(
|
const blend = geo.math.clamp(
|
||||||
(Math.log(Math.max(range, MISSION_CLOSE_VIEW_RANGE_M)) -
|
(Math.log(Math.max(range, MISSION_CLOSE_VIEW_RANGE_M)) -
|
||||||
Math.log(MISSION_CLOSE_VIEW_RANGE_M)) /
|
Math.log(MISSION_CLOSE_VIEW_RANGE_M)) /
|
||||||
(Math.log(MISSION_GLOBE_VIEW_RANGE_M) -
|
(Math.log(MISSION_GLOBE_VIEW_RANGE_M) -
|
||||||
@@ -116,11 +117,7 @@ export function createCamera({ state: layerState, services, parts, source }) {
|
|||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
return Cesium.Math.lerp(
|
return geo.math.lerp(geo.math.toRadians(-42), -geo.math.PI_OVER_TWO, blend);
|
||||||
Cesium.Math.toRadians(-42),
|
|
||||||
-Cesium.Math.PI_OVER_TWO,
|
|
||||||
blend,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,48 +130,44 @@ export function createCamera({ state: layerState, services, parts, source }) {
|
|||||||
|
|
||||||
function replayCameraView(state, altitudeM) {
|
function replayCameraView(state, altitudeM) {
|
||||||
const altitude = Math.max(0, Number(altitudeM) || 0);
|
const altitude = Math.max(0, Number(altitudeM) || 0);
|
||||||
const localRange = Cesium.Math.clamp(
|
const localRange = geo.math.clamp(
|
||||||
REPLAY_INITIAL_RANGE_M + altitude * 0.7,
|
REPLAY_INITIAL_RANGE_M + altitude * 0.7,
|
||||||
REPLAY_INITIAL_RANGE_M,
|
REPLAY_INITIAL_RANGE_M,
|
||||||
REPLAY_LOCAL_MAX_RANGE_M,
|
REPLAY_LOCAL_MAX_RANGE_M,
|
||||||
);
|
);
|
||||||
const rawContextBlend = Cesium.Math.clamp(
|
const rawContextBlend = geo.math.clamp(
|
||||||
(altitude - 20000) / (REPLAY_CONTEXT_ALTITUDE_END_M - 20000),
|
(altitude - 20000) / (REPLAY_CONTEXT_ALTITUDE_END_M - 20000),
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
const contextBlend =
|
const contextBlend =
|
||||||
rawContextBlend * rawContextBlend * (3 - 2 * rawContextBlend);
|
rawContextBlend * rawContextBlend * (3 - 2 * rawContextBlend);
|
||||||
const contextRange = Cesium.Math.clamp(
|
const contextRange = geo.math.clamp(
|
||||||
180000 + altitude * 3.8,
|
180000 + altitude * 3.8,
|
||||||
MISSION_CLOSE_VIEW_RANGE_M,
|
MISSION_CLOSE_VIEW_RANGE_M,
|
||||||
REPLAY_CONTEXT_MAX_RANGE_M,
|
REPLAY_CONTEXT_MAX_RANGE_M,
|
||||||
);
|
);
|
||||||
const ascentRange = Cesium.Math.lerp(
|
const ascentRange = geo.math.lerp(localRange, contextRange, contextBlend);
|
||||||
localRange,
|
const ascentPitch = geo.math.lerp(
|
||||||
contextRange,
|
geo.math.toRadians(-20),
|
||||||
contextBlend,
|
geo.math.toRadians(-34),
|
||||||
);
|
|
||||||
const ascentPitch = Cesium.Math.lerp(
|
|
||||||
Cesium.Math.toRadians(-20),
|
|
||||||
Cesium.Math.toRadians(-34),
|
|
||||||
contextBlend,
|
contextBlend,
|
||||||
);
|
);
|
||||||
if (state?.ascending) {
|
if (state?.ascending) {
|
||||||
return { range: ascentRange, pitch: ascentPitch };
|
return { range: ascentRange, pitch: ascentPitch };
|
||||||
}
|
}
|
||||||
const rawBlend = Cesium.Math.clamp(
|
const rawBlend = geo.math.clamp(
|
||||||
(Number(state?.phaseProgress) || 0) / REPLAY_ORBIT_PULLBACK_FRACTION,
|
(Number(state?.phaseProgress) || 0) / REPLAY_ORBIT_PULLBACK_FRACTION,
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
const blend = rawBlend * rawBlend * (3 - 2 * rawBlend);
|
const blend = rawBlend * rawBlend * (3 - 2 * rawBlend);
|
||||||
return {
|
return {
|
||||||
range: Cesium.Math.lerp(ascentRange, REPLAY_ORBIT_GLOBE_RANGE_M, blend),
|
range: geo.math.lerp(ascentRange, REPLAY_ORBIT_GLOBE_RANGE_M, blend),
|
||||||
// Keep an oblique tactical view of the complete orbit rather than ending
|
// Keep an oblique tactical view of the complete orbit rather than ending
|
||||||
// in a nadir view. This also prevents the camera from appearing to
|
// in a nadir view. This also prevents the camera from appearing to
|
||||||
// return toward the launch site after insertion.
|
// return toward the launch site after insertion.
|
||||||
pitch: Cesium.Math.lerp(ascentPitch, Cesium.Math.toRadians(-45), blend),
|
pitch: geo.math.lerp(ascentPitch, geo.math.toRadians(-45), blend),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,16 +181,15 @@ export function createCamera({ state: layerState, services, parts, source }) {
|
|||||||
|
|
||||||
function replayOrbitGlobeAnchor(position, orbitBlend = 0) {
|
function replayOrbitGlobeAnchor(position, orbitBlend = 0) {
|
||||||
if (!position) return position;
|
if (!position) return position;
|
||||||
const blend = Cesium.Math.clamp(Number(orbitBlend) || 0, 0, 1);
|
const blend = geo.math.clamp(Number(orbitBlend) || 0, 0, 1);
|
||||||
if (blend <= 0) return Cesium.Cartesian3.clone(position);
|
if (blend <= 0) return geo.cartesian3.clone(position);
|
||||||
const cartographic =
|
const cartographic = geo.ellipsoid.WGS84.cartesianToCartographic(position);
|
||||||
Cesium.Ellipsoid.WGS84.cartesianToCartographic(position);
|
if (!cartographic) return geo.cartesian3.clone(position);
|
||||||
if (!cartographic) return Cesium.Cartesian3.clone(position);
|
|
||||||
const altitude = Math.max(0, cartographic.height || 0);
|
const altitude = Math.max(0, cartographic.height || 0);
|
||||||
return Cesium.Cartesian3.fromRadians(
|
return geo.cartesian3.fromRadians(
|
||||||
cartographic.longitude,
|
cartographic.longitude,
|
||||||
cartographic.latitude,
|
cartographic.latitude,
|
||||||
Cesium.Math.lerp(altitude, altitude * 0.1, blend),
|
geo.math.lerp(altitude, altitude * 0.1, blend),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,15 +208,15 @@ export function createCamera({ state: layerState, services, parts, source }) {
|
|||||||
|
|
||||||
function replayOrbitCameraTarget(vehicleAnchor, frameCenter, orbitBlend = 0) {
|
function replayOrbitCameraTarget(vehicleAnchor, frameCenter, orbitBlend = 0) {
|
||||||
if (!vehicleAnchor) return vehicleAnchor;
|
if (!vehicleAnchor) return vehicleAnchor;
|
||||||
if (!frameCenter) return Cesium.Cartesian3.clone(vehicleAnchor);
|
if (!frameCenter) return geo.cartesian3.clone(vehicleAnchor);
|
||||||
const blend =
|
const blend =
|
||||||
Cesium.Math.clamp(Number(orbitBlend) || 0, 0, 1) *
|
geo.math.clamp(Number(orbitBlend) || 0, 0, 1) *
|
||||||
REPLAY_ORBIT_FRAME_CENTER_BLEND;
|
REPLAY_ORBIT_FRAME_CENTER_BLEND;
|
||||||
return Cesium.Cartesian3.lerp(
|
return geo.cartesian3.lerp(
|
||||||
vehicleAnchor,
|
vehicleAnchor,
|
||||||
frameCenter,
|
frameCenter,
|
||||||
blend,
|
blend,
|
||||||
new Cesium.Cartesian3(),
|
geo.cartesian3.create(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,63 +241,59 @@ export function createCamera({ state: layerState, services, parts, source }) {
|
|||||||
pitch,
|
pitch,
|
||||||
) {
|
) {
|
||||||
if (!position || !tangentPosition || !target) return null;
|
if (!position || !tangentPosition || !target) return null;
|
||||||
const radial = Cesium.Cartesian3.normalize(
|
const radial = geo.cartesian3.normalize(
|
||||||
Cesium.Cartesian3.clone(position),
|
geo.cartesian3.clone(position),
|
||||||
new Cesium.Cartesian3(),
|
geo.cartesian3.create(),
|
||||||
);
|
);
|
||||||
const tangent = Cesium.Cartesian3.subtract(
|
const tangent = geo.cartesian3.subtract(
|
||||||
tangentPosition,
|
tangentPosition,
|
||||||
position,
|
position,
|
||||||
new Cesium.Cartesian3(),
|
geo.cartesian3.create(),
|
||||||
);
|
);
|
||||||
if (Cesium.Cartesian3.magnitudeSquared(tangent) < 1) return null;
|
if (geo.cartesian3.magnitudeSquared(tangent) < 1) return null;
|
||||||
Cesium.Cartesian3.normalize(tangent, tangent);
|
geo.cartesian3.normalize(tangent, tangent);
|
||||||
const orbitNormal = Cesium.Cartesian3.cross(
|
const orbitNormal = geo.cartesian3.cross(
|
||||||
radial,
|
radial,
|
||||||
tangent,
|
tangent,
|
||||||
new Cesium.Cartesian3(),
|
geo.cartesian3.create(),
|
||||||
);
|
);
|
||||||
if (Cesium.Cartesian3.magnitudeSquared(orbitNormal) < 1e-12) return null;
|
if (geo.cartesian3.magnitudeSquared(orbitNormal) < 1e-12) return null;
|
||||||
Cesium.Cartesian3.normalize(orbitNormal, orbitNormal);
|
geo.cartesian3.normalize(orbitNormal, orbitNormal);
|
||||||
|
|
||||||
const distance = Math.max(1, Number(range) || 1);
|
const distance = Math.max(1, Number(range) || 1);
|
||||||
const elevation = Cesium.Math.clamp(
|
const elevation = geo.math.clamp(
|
||||||
Math.abs(Number(pitch) || 0),
|
Math.abs(Number(pitch) || 0),
|
||||||
Cesium.Math.toRadians(5),
|
geo.math.toRadians(5),
|
||||||
Cesium.Math.toRadians(80),
|
geo.math.toRadians(80),
|
||||||
);
|
);
|
||||||
const planeOffset = Cesium.Cartesian3.multiplyByScalar(
|
const planeOffset = geo.cartesian3.multiplyByScalar(
|
||||||
orbitNormal,
|
orbitNormal,
|
||||||
Math.cos(elevation) * distance,
|
Math.cos(elevation) * distance,
|
||||||
new Cesium.Cartesian3(),
|
geo.cartesian3.create(),
|
||||||
);
|
);
|
||||||
const radialOffset = Cesium.Cartesian3.multiplyByScalar(
|
const radialOffset = geo.cartesian3.multiplyByScalar(
|
||||||
radial,
|
radial,
|
||||||
Math.sin(elevation) * distance,
|
Math.sin(elevation) * distance,
|
||||||
new Cesium.Cartesian3(),
|
geo.cartesian3.create(),
|
||||||
);
|
);
|
||||||
const destination = Cesium.Cartesian3.add(
|
const destination = geo.cartesian3.add(
|
||||||
target,
|
target,
|
||||||
planeOffset,
|
planeOffset,
|
||||||
new Cesium.Cartesian3(),
|
geo.cartesian3.create(),
|
||||||
);
|
);
|
||||||
Cesium.Cartesian3.add(destination, radialOffset, destination);
|
geo.cartesian3.add(destination, radialOffset, destination);
|
||||||
const direction = Cesium.Cartesian3.normalize(
|
const direction = geo.cartesian3.normalize(
|
||||||
Cesium.Cartesian3.subtract(target, destination, new Cesium.Cartesian3()),
|
geo.cartesian3.subtract(target, destination, geo.cartesian3.create()),
|
||||||
new Cesium.Cartesian3(),
|
geo.cartesian3.create(),
|
||||||
);
|
);
|
||||||
const radialAlongView = Cesium.Cartesian3.multiplyByScalar(
|
const radialAlongView = geo.cartesian3.multiplyByScalar(
|
||||||
direction,
|
direction,
|
||||||
Cesium.Cartesian3.dot(radial, direction),
|
geo.cartesian3.dot(radial, direction),
|
||||||
new Cesium.Cartesian3(),
|
geo.cartesian3.create(),
|
||||||
);
|
);
|
||||||
const up = Cesium.Cartesian3.normalize(
|
const up = geo.cartesian3.normalize(
|
||||||
Cesium.Cartesian3.subtract(
|
geo.cartesian3.subtract(radial, radialAlongView, geo.cartesian3.create()),
|
||||||
radial,
|
geo.cartesian3.create(),
|
||||||
radialAlongView,
|
|
||||||
new Cesium.Cartesian3(),
|
|
||||||
),
|
|
||||||
new Cesium.Cartesian3(),
|
|
||||||
);
|
);
|
||||||
return { destination, direction, up };
|
return { destination, direction, up };
|
||||||
}
|
}
|
||||||
@@ -321,8 +309,8 @@ export function createCamera({ state: layerState, services, parts, source }) {
|
|||||||
|
|
||||||
function replayOrbitFrameSphere(orbitPath = []) {
|
function replayOrbitFrameSphere(orbitPath = []) {
|
||||||
const earth = new Cesium.BoundingSphere(
|
const earth = new Cesium.BoundingSphere(
|
||||||
Cesium.Cartesian3.ZERO,
|
geo.cartesian3.ZERO,
|
||||||
Cesium.Ellipsoid.WGS84.maximumRadius,
|
geo.ellipsoid.WGS84.maximumRadius,
|
||||||
);
|
);
|
||||||
if (!Array.isArray(orbitPath) || orbitPath.length < 2) return earth;
|
if (!Array.isArray(orbitPath) || orbitPath.length < 2) return earth;
|
||||||
const orbit = Cesium.BoundingSphere.fromPoints(orbitPath);
|
const orbit = Cesium.BoundingSphere.fromPoints(orbitPath);
|
||||||
@@ -351,13 +339,13 @@ export function createCamera({ state: layerState, services, parts, source }) {
|
|||||||
const range = Math.max(0, Number(baseRange) || 0);
|
const range = Math.max(0, Number(baseRange) || 0);
|
||||||
const altitude = Math.max(0, Number(altitudeM) || 0);
|
const altitude = Math.max(0, Number(altitudeM) || 0);
|
||||||
const frameRadius = Math.max(0, Number(frameRadiusM) || 0);
|
const frameRadius = Math.max(0, Number(frameRadiusM) || 0);
|
||||||
const blend = Cesium.Math.clamp(Number(orbitBlend) || 0, 0, 1);
|
const blend = geo.math.clamp(Number(orbitBlend) || 0, 0, 1);
|
||||||
const globeAndVehicleRange = Math.max(
|
const globeAndVehicleRange = Math.max(
|
||||||
range,
|
range,
|
||||||
altitude + Cesium.Ellipsoid.WGS84.maximumRadius * 2.4,
|
altitude + geo.ellipsoid.WGS84.maximumRadius * 2.4,
|
||||||
frameRadius * 3,
|
frameRadius * 3,
|
||||||
);
|
);
|
||||||
return Cesium.Math.lerp(range, globeAndVehicleRange, blend);
|
return geo.math.lerp(range, globeAndVehicleRange, blend);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
cameraHeadingForPath,
|
cameraHeadingForPath,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import * as Cesium from 'cesium';
|
import * as Cesium from 'cesium';
|
||||||
|
import * as geo from '../../geo/index.js';
|
||||||
import {
|
import {
|
||||||
MISSION_CLOSE_VIEW_RANGE_M,
|
MISSION_CLOSE_VIEW_RANGE_M,
|
||||||
MISSION_GLOBE_VIEW_RANGE_M,
|
MISSION_GLOBE_VIEW_RANGE_M,
|
||||||
@@ -360,7 +361,7 @@ export function createPanel({ state: layerState, services, parts, source }) {
|
|||||||
Cesium.JulianDate.now(layerState._declutterTime),
|
Cesium.JulianDate.now(layerState._declutterTime),
|
||||||
);
|
);
|
||||||
const altitudeM = position
|
const altitudeM = position
|
||||||
? Cesium.Cartographic.fromCartesian(position)?.height
|
? geo.cartographic.fromCartesian(position)?.height
|
||||||
: null;
|
: null;
|
||||||
setMissionPanelField(
|
setMissionPanelField(
|
||||||
'[data-mission-distance]',
|
'[data-mission-distance]',
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import * as Cesium from 'cesium';
|
import * as geo from '../../geo/index.js';
|
||||||
|
|
||||||
export const WINDOW_DAYS = 30;
|
export const WINDOW_DAYS = 30;
|
||||||
|
|
||||||
@@ -48,9 +48,9 @@ export const REPLAY_ORBIT_GLOBE_RANGE_M = 18000000;
|
|||||||
|
|
||||||
export const REPLAY_ORBIT_PULLBACK_FRACTION = 0.2;
|
export const REPLAY_ORBIT_PULLBACK_FRACTION = 0.2;
|
||||||
|
|
||||||
export const REPLAY_ASCENT_CAMERA_OFFSET_RAD = Cesium.Math.toRadians(30);
|
export const REPLAY_ASCENT_CAMERA_OFFSET_RAD = geo.math.toRadians(30);
|
||||||
|
|
||||||
export const REPLAY_ORBIT_CAMERA_OFFSET_RAD = Cesium.Math.toRadians(45);
|
export const REPLAY_ORBIT_CAMERA_OFFSET_RAD = geo.math.toRadians(45);
|
||||||
|
|
||||||
export const REPLAY_ORBIT_FRAME_CENTER_BLEND = 0.45;
|
export const REPLAY_ORBIT_FRAME_CENTER_BLEND = 0.45;
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ export const MAX_POST_TLE_RETRIES = 1;
|
|||||||
|
|
||||||
export const POST_TLE_RETRY_DELAY_MS = 1500;
|
export const POST_TLE_RETRY_DELAY_MS = 1500;
|
||||||
|
|
||||||
export const EARTH_ROTATION_RAD_PER_SEC = Cesium.Math.TWO_PI / 86164.0905;
|
export const EARTH_ROTATION_RAD_PER_SEC = geo.math.TWO_PI / 86164.0905;
|
||||||
|
|
||||||
export const PROJECTED_ASCENT_ROTATION_SEC = 600;
|
export const PROJECTED_ASCENT_ROTATION_SEC = 600;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import * as Cesium from 'cesium';
|
import * as Cesium from 'cesium';
|
||||||
|
import * as geo from '../../geo/index.js';
|
||||||
import {
|
import {
|
||||||
SATELLITE_STANDALONE_DEFAULTS,
|
SATELLITE_STANDALONE_DEFAULTS,
|
||||||
LAUNCH_PAD_ZONE_MAX_CAMERA_HEIGHT_M,
|
LAUNCH_PAD_ZONE_MAX_CAMERA_HEIGHT_M,
|
||||||
@@ -226,15 +227,11 @@ export function createPolicyHelpers({
|
|||||||
const range = parts.panel.missionHoverPreviewRange(
|
const range = parts.panel.missionHoverPreviewRange(
|
||||||
layerState._viewer.camera.positionCartographic?.height,
|
layerState._viewer.camera.positionCartographic?.height,
|
||||||
);
|
);
|
||||||
const position = Cesium.Cartesian3.fromDegrees(launch.lon, launch.lat);
|
const position = geo.cartesian3.fromDegrees(launch.lon, launch.lat);
|
||||||
layerState._viewer.camera.flyToBoundingSphere(
|
layerState._viewer.camera.flyToBoundingSphere(
|
||||||
new Cesium.BoundingSphere(position, 0),
|
new Cesium.BoundingSphere(position, 0),
|
||||||
{
|
{
|
||||||
offset: new Cesium.HeadingPitchRange(
|
offset: new Cesium.HeadingPitchRange(0, -geo.math.PI_OVER_TWO, range),
|
||||||
0,
|
|
||||||
-Cesium.Math.PI_OVER_TWO,
|
|
||||||
range,
|
|
||||||
),
|
|
||||||
duration: 0.8,
|
duration: 0.8,
|
||||||
easingFunction: Cesium.EasingFunction.CUBIC_IN_OUT,
|
easingFunction: Cesium.EasingFunction.CUBIC_IN_OUT,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import * as Cesium from 'cesium';
|
import * as Cesium from 'cesium';
|
||||||
|
import * as geo from '../../geo/index.js';
|
||||||
import {
|
import {
|
||||||
REPLAY_ASCENT_FALLBACK_SEC,
|
REPLAY_ASCENT_FALLBACK_SEC,
|
||||||
REPLAY_ASCENT_MIN_SEC,
|
REPLAY_ASCENT_MIN_SEC,
|
||||||
@@ -52,10 +53,10 @@ export function createReplay({ state: layerState, services, parts, source }) {
|
|||||||
if (!previous || !next) return next;
|
if (!previous || !next) return next;
|
||||||
const distance = Math.hypot(next.x - previous.x, next.y - previous.y);
|
const distance = Math.hypot(next.x - previous.x, next.y - previous.y);
|
||||||
if (!Number.isFinite(distance) || distance > snapDistance) return next;
|
if (!Number.isFinite(distance) || distance > snapDistance) return next;
|
||||||
const amount = Cesium.Math.clamp(Number(alpha) || 0, 0, 1);
|
const amount = geo.math.clamp(Number(alpha) || 0, 0, 1);
|
||||||
return {
|
return {
|
||||||
x: Cesium.Math.lerp(previous.x, next.x, amount),
|
x: geo.math.lerp(previous.x, next.x, amount),
|
||||||
y: Cesium.Math.lerp(previous.y, next.y, amount),
|
y: geo.math.lerp(previous.y, next.y, amount),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,13 +78,13 @@ export function createReplay({ state: layerState, services, parts, source }) {
|
|||||||
.slice(1)
|
.slice(1)
|
||||||
.reduce(
|
.reduce(
|
||||||
(total, point, index) =>
|
(total, point, index) =>
|
||||||
total + Cesium.Cartesian3.distance(ascentPath[index], point),
|
total + geo.cartesian3.distance(ascentPath[index], point),
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
realAscentSeconds = Math.max(180, pathLength / 9000);
|
realAscentSeconds = Math.max(180, pathLength / 9000);
|
||||||
}
|
}
|
||||||
if (!realAscentSeconds) realAscentSeconds = REPLAY_ASCENT_FALLBACK_SEC * 50;
|
if (!realAscentSeconds) realAscentSeconds = REPLAY_ASCENT_FALLBACK_SEC * 50;
|
||||||
return Cesium.Math.clamp(
|
return geo.math.clamp(
|
||||||
REPLAY_ASCENT_FALLBACK_SEC * (realAscentSeconds / 600),
|
REPLAY_ASCENT_FALLBACK_SEC * (realAscentSeconds / 600),
|
||||||
REPLAY_ASCENT_MIN_SEC,
|
REPLAY_ASCENT_MIN_SEC,
|
||||||
REPLAY_ASCENT_MAX_SEC,
|
REPLAY_ASCENT_MAX_SEC,
|
||||||
@@ -99,11 +100,7 @@ export function createReplay({ state: layerState, services, parts, source }) {
|
|||||||
function normalizeReplaySpeed(value) {
|
function normalizeReplaySpeed(value) {
|
||||||
const numeric = Number(value);
|
const numeric = Number(value);
|
||||||
if (!Number.isFinite(numeric)) return 1;
|
if (!Number.isFinite(numeric)) return 1;
|
||||||
const clamped = Cesium.Math.clamp(
|
const clamped = geo.math.clamp(numeric, REPLAY_SPEED_MIN, REPLAY_SPEED_MAX);
|
||||||
numeric,
|
|
||||||
REPLAY_SPEED_MIN,
|
|
||||||
REPLAY_SPEED_MAX,
|
|
||||||
);
|
|
||||||
return Math.round(clamped / REPLAY_SPEED_STEP) * REPLAY_SPEED_STEP;
|
return Math.round(clamped / REPLAY_SPEED_STEP) * REPLAY_SPEED_STEP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,7 +411,7 @@ export function createReplay({ state: layerState, services, parts, source }) {
|
|||||||
track.lastCameraHeading,
|
track.lastCameraHeading,
|
||||||
);
|
);
|
||||||
const orbitBlend = !state.ascending
|
const orbitBlend = !state.ascending
|
||||||
? Cesium.Math.clamp(
|
? geo.math.clamp(
|
||||||
(Number(state.phaseProgress) || 0) /
|
(Number(state.phaseProgress) || 0) /
|
||||||
REPLAY_ORBIT_PULLBACK_FRACTION,
|
REPLAY_ORBIT_PULLBACK_FRACTION,
|
||||||
0,
|
0,
|
||||||
@@ -428,16 +425,16 @@ export function createReplay({ state: layerState, services, parts, source }) {
|
|||||||
if (state.ascending) track.orbitCameraWorldFrame = false;
|
if (state.ascending) track.orbitCameraWorldFrame = false;
|
||||||
const nowMs = performance.now();
|
const nowMs = performance.now();
|
||||||
const frameDurationMs = Number.isFinite(lastCameraUpdateMs)
|
const frameDurationMs = Number.isFinite(lastCameraUpdateMs)
|
||||||
? Cesium.Math.clamp(nowMs - lastCameraUpdateMs, 4, 50)
|
? geo.math.clamp(nowMs - lastCameraUpdateMs, 4, 50)
|
||||||
: 1000 / 60;
|
: 1000 / 60;
|
||||||
lastCameraUpdateMs = nowMs;
|
lastCameraUpdateMs = nowMs;
|
||||||
track.lastCameraHeading = parts.camera.smoothReplayCameraHeading(
|
track.lastCameraHeading = parts.camera.smoothReplayCameraHeading(
|
||||||
track.lastCameraHeading,
|
track.lastCameraHeading,
|
||||||
desiredHeading,
|
desiredHeading,
|
||||||
(Cesium.Math.toRadians(2) * frameDurationMs) / (1000 / 60),
|
(geo.math.toRadians(2) * frameDurationMs) / (1000 / 60),
|
||||||
);
|
);
|
||||||
const cartographic =
|
const cartographic =
|
||||||
Cesium.Ellipsoid.WGS84.cartesianToCartographic(position);
|
geo.ellipsoid.WGS84.cartesianToCartographic(position);
|
||||||
const altitude = Math.max(0, cartographic?.height || 0);
|
const altitude = Math.max(0, cartographic?.height || 0);
|
||||||
const cameraView = parts.camera.replayCameraView(state, altitude);
|
const cameraView = parts.camera.replayCameraView(state, altitude);
|
||||||
const defaultOrbitTarget = !state.ascending
|
const defaultOrbitTarget = !state.ascending
|
||||||
@@ -518,7 +515,7 @@ export function createReplay({ state: layerState, services, parts, source }) {
|
|||||||
{
|
{
|
||||||
offset: new Cesium.HeadingPitchRange(
|
offset: new Cesium.HeadingPitchRange(
|
||||||
initialHeading,
|
initialHeading,
|
||||||
Cesium.Math.toRadians(-20),
|
geo.math.toRadians(-20),
|
||||||
REPLAY_INITIAL_RANGE_M,
|
REPLAY_INITIAL_RANGE_M,
|
||||||
),
|
),
|
||||||
duration: 1.4,
|
duration: 1.4,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import * as Cesium from 'cesium';
|
import * as Cesium from 'cesium';
|
||||||
|
import * as geo from '../../geo/index.js';
|
||||||
import { MISSION_GLOBE_VIEW_RANGE_M, MISSION_FOCUS_RANGE_M } from './policy.js';
|
import { MISSION_GLOBE_VIEW_RANGE_M, MISSION_FOCUS_RANGE_M } from './policy.js';
|
||||||
|
|
||||||
export function createSelection({
|
export function createSelection({
|
||||||
@@ -24,7 +25,7 @@ export function createSelection({
|
|||||||
fovy >= Math.PI
|
fovy >= Math.PI
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
const earthRadius = Cesium.Ellipsoid.WGS84.maximumRadius;
|
const earthRadius = geo.ellipsoid.WGS84.maximumRadius;
|
||||||
const keyholeRadius = getKeyholeGeometry(width, height).radius;
|
const keyholeRadius = getKeyholeGeometry(width, height).radius;
|
||||||
const targetScreenRadius = keyholeRadius * 0.61;
|
const targetScreenRadius = keyholeRadius * 0.61;
|
||||||
const angularRadius = Math.atan(
|
const angularRadius = Math.atan(
|
||||||
@@ -33,14 +34,14 @@ export function createSelection({
|
|||||||
const distance = earthRadius / Math.max(Math.sin(angularRadius), 1e-4);
|
const distance = earthRadius / Math.max(Math.sin(angularRadius), 1e-4);
|
||||||
const altitude = Math.max(earthRadius * 1.55, distance - earthRadius);
|
const altitude = Math.max(earthRadius * 1.55, distance - earthRadius);
|
||||||
viewer.camera.flyTo({
|
viewer.camera.flyTo({
|
||||||
destination: Cesium.Cartesian3.fromRadians(
|
destination: geo.cartesian3.fromRadians(
|
||||||
cartographic.longitude,
|
cartographic.longitude,
|
||||||
cartographic.latitude,
|
cartographic.latitude,
|
||||||
altitude,
|
altitude,
|
||||||
),
|
),
|
||||||
orientation: {
|
orientation: {
|
||||||
heading: viewer.camera.heading,
|
heading: viewer.camera.heading,
|
||||||
pitch: -Cesium.Math.PI_OVER_TWO,
|
pitch: -geo.math.PI_OVER_TWO,
|
||||||
roll: 0,
|
roll: 0,
|
||||||
},
|
},
|
||||||
duration,
|
duration,
|
||||||
@@ -99,7 +100,7 @@ export function createSelection({
|
|||||||
if (!layerState._viewer || !launch || layerState._replayCameraLaunchId)
|
if (!layerState._viewer || !launch || layerState._replayCameraLaunchId)
|
||||||
return;
|
return;
|
||||||
stopMissionZoomAnchor();
|
stopMissionZoomAnchor();
|
||||||
const target = Cesium.Cartesian3.fromDegrees(launch.lon, launch.lat);
|
const target = geo.cartesian3.fromDegrees(launch.lon, launch.lat);
|
||||||
const range = Math.max(
|
const range = Math.max(
|
||||||
2000,
|
2000,
|
||||||
Number(initialRange) || MISSION_GLOBE_VIEW_RANGE_M,
|
Number(initialRange) || MISSION_GLOBE_VIEW_RANGE_M,
|
||||||
@@ -127,15 +128,12 @@ export function createSelection({
|
|||||||
const orbitPositions = orbitEntity?.polyline?.positions?.getValue(
|
const orbitPositions = orbitEntity?.polyline?.positions?.getValue(
|
||||||
Cesium.JulianDate.now(),
|
Cesium.JulianDate.now(),
|
||||||
);
|
);
|
||||||
const launchPosition = Cesium.Cartesian3.fromDegrees(
|
const launchPosition = geo.cartesian3.fromDegrees(launch.lon, launch.lat);
|
||||||
launch.lon,
|
|
||||||
launch.lat,
|
|
||||||
);
|
|
||||||
let range = 18000000;
|
let range = 18000000;
|
||||||
if (orbitPositions?.length > 1) {
|
if (orbitPositions?.length > 1) {
|
||||||
const canvas = layerState._viewer.scene.canvas;
|
const canvas = layerState._viewer.scene.canvas;
|
||||||
const fovy =
|
const fovy =
|
||||||
layerState._viewer.camera.frustum?.fovy || Cesium.Math.toRadians(60);
|
layerState._viewer.camera.frustum?.fovy || geo.math.toRadians(60);
|
||||||
const aspect = Math.max(
|
const aspect = Math.max(
|
||||||
0.1,
|
0.1,
|
||||||
(canvas.clientWidth || canvas.width) /
|
(canvas.clientWidth || canvas.width) /
|
||||||
@@ -145,7 +143,7 @@ export function createSelection({
|
|||||||
const paddedHalfAngle = Math.min(fovy, fovx) * 0.5 * 0.62;
|
const paddedHalfAngle = Math.min(fovy, fovx) * 0.5 * 0.62;
|
||||||
const orbitExtent = orbitPositions.reduce(
|
const orbitExtent = orbitPositions.reduce(
|
||||||
(largest, point) =>
|
(largest, point) =>
|
||||||
Math.max(largest, Cesium.Cartesian3.distance(launchPosition, point)),
|
Math.max(largest, geo.cartesian3.distance(launchPosition, point)),
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
range = Math.max(
|
range = Math.max(
|
||||||
@@ -153,39 +151,35 @@ export function createSelection({
|
|||||||
18000000,
|
18000000,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const targetNormal = Cesium.Cartesian3.normalize(
|
const targetNormal = geo.cartesian3.normalize(
|
||||||
launchPosition,
|
launchPosition,
|
||||||
new Cesium.Cartesian3(),
|
geo.cartesian3.create(),
|
||||||
);
|
);
|
||||||
const destination = Cesium.Cartesian3.add(
|
const destination = geo.cartesian3.add(
|
||||||
launchPosition,
|
launchPosition,
|
||||||
Cesium.Cartesian3.multiplyByScalar(
|
geo.cartesian3.multiplyByScalar(
|
||||||
targetNormal,
|
targetNormal,
|
||||||
range,
|
range,
|
||||||
new Cesium.Cartesian3(),
|
geo.cartesian3.create(),
|
||||||
),
|
),
|
||||||
new Cesium.Cartesian3(),
|
geo.cartesian3.create(),
|
||||||
);
|
);
|
||||||
const direction = Cesium.Cartesian3.negate(
|
const direction = geo.cartesian3.negate(
|
||||||
targetNormal,
|
targetNormal,
|
||||||
new Cesium.Cartesian3(),
|
geo.cartesian3.create(),
|
||||||
);
|
);
|
||||||
let right = Cesium.Cartesian3.cross(
|
let right = geo.cartesian3.cross(
|
||||||
direction,
|
direction,
|
||||||
Cesium.Cartesian3.UNIT_Z,
|
geo.cartesian3.UNIT_Z,
|
||||||
new Cesium.Cartesian3(),
|
geo.cartesian3.create(),
|
||||||
);
|
);
|
||||||
if (Cesium.Cartesian3.magnitudeSquared(right) < 1e-8) {
|
if (geo.cartesian3.magnitudeSquared(right) < 1e-8) {
|
||||||
right = Cesium.Cartesian3.cross(
|
right = geo.cartesian3.cross(direction, geo.cartesian3.UNIT_Y, right);
|
||||||
direction,
|
|
||||||
Cesium.Cartesian3.UNIT_Y,
|
|
||||||
right,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Cesium.Cartesian3.normalize(right, right);
|
geo.cartesian3.normalize(right, right);
|
||||||
const up = Cesium.Cartesian3.normalize(
|
const up = geo.cartesian3.normalize(
|
||||||
Cesium.Cartesian3.cross(right, direction, new Cesium.Cartesian3()),
|
geo.cartesian3.cross(right, direction, geo.cartesian3.create()),
|
||||||
new Cesium.Cartesian3(),
|
geo.cartesian3.create(),
|
||||||
);
|
);
|
||||||
layerState._viewer.camera.flyTo({
|
layerState._viewer.camera.flyTo({
|
||||||
destination,
|
destination,
|
||||||
@@ -202,10 +196,7 @@ export function createSelection({
|
|||||||
if (!layerState._viewer || !launch) return;
|
if (!layerState._viewer || !launch) return;
|
||||||
parts.replay.stopMissionReplay();
|
parts.replay.stopMissionReplay();
|
||||||
stopMissionZoomAnchor();
|
stopMissionZoomAnchor();
|
||||||
const launchPosition = Cesium.Cartesian3.fromDegrees(
|
const launchPosition = geo.cartesian3.fromDegrees(launch.lon, launch.lat);
|
||||||
launch.lon,
|
|
||||||
launch.lat,
|
|
||||||
);
|
|
||||||
layerState._viewer.selectedEntity = layerState._dataSource.entities.getById(
|
layerState._viewer.selectedEntity = layerState._dataSource.entities.getById(
|
||||||
`rocket-launch:${launch.id}`,
|
`rocket-launch:${launch.id}`,
|
||||||
);
|
);
|
||||||
@@ -214,7 +205,7 @@ export function createSelection({
|
|||||||
{
|
{
|
||||||
offset: new Cesium.HeadingPitchRange(
|
offset: new Cesium.HeadingPitchRange(
|
||||||
0,
|
0,
|
||||||
Cesium.Math.toRadians(-42),
|
geo.math.toRadians(-42),
|
||||||
MISSION_FOCUS_RANGE_M,
|
MISSION_FOCUS_RANGE_M,
|
||||||
),
|
),
|
||||||
duration: 1.4,
|
duration: 1.4,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import * as Cesium from 'cesium';
|
import * as Cesium from 'cesium';
|
||||||
|
import * as geo from '../../geo/index.js';
|
||||||
|
|
||||||
export function createState({ services }) {
|
export function createState({ services }) {
|
||||||
const { setOverlayEntries, setOverlaySourceVisible, clearOverlaySource } =
|
const { setOverlayEntries, setOverlaySourceVisible, clearOverlaySource } =
|
||||||
@@ -125,7 +126,7 @@ export function createState({ services }) {
|
|||||||
|
|
||||||
state._declutterOccluder = new Cesium.EllipsoidalOccluder(
|
state._declutterOccluder = new Cesium.EllipsoidalOccluder(
|
||||||
Cesium.Ellipsoid.WGS84,
|
Cesium.Ellipsoid.WGS84,
|
||||||
new Cesium.Cartesian3(),
|
geo.cartesian3.create(),
|
||||||
);
|
);
|
||||||
|
|
||||||
state._missionRingDate = new Date(0);
|
state._missionRingDate = new Date(0);
|
||||||
|
|||||||
Reference in new issue
Block a user