mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
refactor(earthquakes): extract native renderer with identical ground-disc output
Keep refresh, cancellation and label policy engine-neutral; inject the original native entities at composition. Prove static geometry, analyst records, owner disposal and last-good refresh behavior. Native dev and QA-preview pass 18 checks each; all eight baseline PNGs remain byte-identical.
This commit is contained in:
1 parent
e8870a4766
commit
c89185f352
13 files changed
+343
-92
No files matched your search
@@ -34,6 +34,7 @@ const navaraPackage = /^(?:(?:three|postprocessing)(?:\/|$)|@navaramap\/)/;
|
||||
// engine in their renderers: cesium only in render/cesium*.js, three and
|
||||
// Navara only in render/navara*.js. The list grows with each moved layer.
|
||||
const RENDERED_LAYER_DIRS = [
|
||||
'src/layers/earthquakes/',
|
||||
'src/layers/flights/',
|
||||
'src/layers/military/',
|
||||
'src/layers/localAdsb/',
|
||||
|
||||
@@ -1182,5 +1182,7 @@
|
||||
"src/tooling/w1RuntimeEvidence.test.mjs",
|
||||
"scripts/qa-w2-layers.mjs",
|
||||
"scripts/fixtures/w2/earthquakes.mjs",
|
||||
"src/tooling/w2QaComparison.test.mjs"
|
||||
"src/tooling/w2QaComparison.test.mjs",
|
||||
"src/layers/earthquakes/render/cesium.js",
|
||||
"src/layers/earthquakes/render/cesium.test.mjs"
|
||||
]
|
||||
@@ -1074,9 +1074,26 @@
|
||||
"src/layers/earthquakes/index.js",
|
||||
"src/layers/earthquakes/model.js",
|
||||
"src/layers/earthquakes/source.js",
|
||||
"src/layers/earthquakes/records.js"
|
||||
"src/layers/earthquakes/records.js",
|
||||
"src/geo/boundingSphere.js",
|
||||
"src/geo/cartesian2.js",
|
||||
"src/geo/cartesian3.js",
|
||||
"src/geo/cartographic.js",
|
||||
"src/geo/check.js",
|
||||
"src/geo/debug.js",
|
||||
"src/geo/developerError.js",
|
||||
"src/geo/ellipsoid.js",
|
||||
"src/geo/ellipsoidGeodesic.js",
|
||||
"src/geo/index.js",
|
||||
"src/geo/math.js",
|
||||
"src/geo/matrix3.js",
|
||||
"src/geo/matrix4.js",
|
||||
"src/geo/quaternion.js",
|
||||
"src/geo/scaleToGeodeticSurface.js",
|
||||
"src/geo/transforms.js",
|
||||
"src/layers/shared/color.js"
|
||||
],
|
||||
"external": ["cesium"]
|
||||
"external": []
|
||||
},
|
||||
"recent-imagery": {
|
||||
"exports": ["./layers/recent-imagery"],
|
||||
@@ -2677,7 +2694,8 @@
|
||||
"src/layers/shared/render/engineView.js",
|
||||
"src/celestialRing/render/cesium.js",
|
||||
"src/celestialRing/view.js",
|
||||
"src/layers/satellites/render/cesium.js"
|
||||
"src/layers/satellites/render/cesium.js",
|
||||
"src/layers/earthquakes/render/cesium.js"
|
||||
],
|
||||
"external": [
|
||||
"hls.js",
|
||||
@@ -3269,7 +3287,8 @@
|
||||
"src/celestialRing/render/cesium.js",
|
||||
"src/celestialRing/view.js",
|
||||
"src/layers/shared/render/engineView.js",
|
||||
"src/layers/satellites/render/cesium.js"
|
||||
"src/layers/satellites/render/cesium.js",
|
||||
"src/layers/earthquakes/render/cesium.js"
|
||||
],
|
||||
"external": [
|
||||
"hls.js",
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
import { rendererFor } from './renderers.js';
|
||||
import { createEarthquakesCesiumRenderer } from '../../layers/earthquakes/render/cesium.js';
|
||||
import { createEarthquakesLayer } from '../../layers/earthquakes/index.js';
|
||||
import { overlayHost } from './overlayHost.js';
|
||||
/** Wire earthquake observations to the application overlay host. */
|
||||
export function createApplicationEarthquakes(options) {
|
||||
return createEarthquakesLayer({ overlayHost, ...options });
|
||||
export function createApplicationEarthquakes({
|
||||
renderer = {
|
||||
create: ({ engine = null, ...options }) =>
|
||||
engine
|
||||
? rendererFor('earthquakes', engine, options)
|
||||
: createEarthquakesCesiumRenderer(null, options),
|
||||
},
|
||||
...options
|
||||
} = {}) {
|
||||
return createEarthquakesLayer({ overlayHost, renderer, ...options });
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { createEarthquakesCesiumRenderer } from '../../layers/earthquakes/render/cesium.js';
|
||||
import { createLaunchesCesiumRenderer } from '../../layers/launches/render/cesium.js';
|
||||
// Which engine draws which layer: the layer renderer registry (plan, "layer
|
||||
// renderer interface") and the layer availability API built on it.
|
||||
@@ -89,6 +90,7 @@ export const layerAvailableOn = (layerId, engineKind) =>
|
||||
|
||||
/** Cesium renderers extracted from their layers (render/cesium.js). */
|
||||
export const CESIUM_LAYER_RENDERERS = Object.freeze({
|
||||
earthquakes: createEarthquakesCesiumRenderer,
|
||||
'rocket-launches': createLaunchesCesiumRenderer,
|
||||
satellites: createSatellitesCesiumRenderer,
|
||||
flights: createFlightsCesiumRenderer,
|
||||
|
||||
@@ -56,8 +56,9 @@ test('the default registry: every layer on Cesium, none yet on Navara', () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('the aircraft, vessels, satellites and launches have extracted Cesium renderers; the others still draw themselves', () => {
|
||||
test('the aircraft, vessels, satellites, launches and earthquakes have extracted Cesium renderers', () => {
|
||||
assert.deepEqual(Object.keys(CESIUM_LAYER_RENDERERS), [
|
||||
'earthquakes',
|
||||
'rocket-launches',
|
||||
'satellites',
|
||||
'flights',
|
||||
|
||||
@@ -294,7 +294,7 @@ test('a quake poll still reaches the screen with the render loop idle', async ()
|
||||
});
|
||||
|
||||
test('the earthquakes layer installs no per-frame callback and no continuous-render hold', () => {
|
||||
const source = ['index', 'model', 'source'].map(name =>
|
||||
const source = ['index', 'model', 'source', 'render/cesium'].map(name =>
|
||||
readFileSync(new URL(`../layers/earthquakes/${name}.js`, import.meta.url), 'utf8')).join('\n');
|
||||
assert.doesNotMatch(
|
||||
source,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as Cesium from 'cesium';
|
||||
import * as geo from '../../geo/index.js';
|
||||
import {
|
||||
EARTHQUAKE_OVERLAY_SOURCE_ID,
|
||||
EARTHQUAKE_OVERLAY_COHORT_LIMIT,
|
||||
@@ -11,14 +11,22 @@ import {
|
||||
export * from './model.js';
|
||||
export { createUsgsEarthquakeSource } from './source.js';
|
||||
|
||||
/** Own one earthquake display and its refresh lifecycle. */
|
||||
export function createEarthquakesLayer({ source, overlayHost } = {}) {
|
||||
/**
|
||||
* Own one earthquake display and its refresh lifecycle.
|
||||
* renderer.create({viewer, engine}) owns drawing and returns:
|
||||
* setVisible(boolean), replace(discs), records(limit), destroy().
|
||||
* Discs are plain ECEF anchors, metre radii and Rgba colours; renderers keep
|
||||
* source order and return plain raw analyst rows (model.mapAnalystRecord).
|
||||
*/
|
||||
export function createEarthquakesLayer({ source, overlayHost, renderer } = {}) {
|
||||
if (typeof source?.getSnapshot !== 'function')
|
||||
throw new TypeError('Earthquakes require a snapshot source');
|
||||
if (!overlayHost) throw new TypeError('Earthquakes require an overlay host');
|
||||
if (typeof renderer?.create !== 'function')
|
||||
throw new TypeError('Earthquakes require a renderer factory');
|
||||
let _viewer = null;
|
||||
let _request = null;
|
||||
let _dataSource = null;
|
||||
let _renderer = null;
|
||||
let _count = 0;
|
||||
let _lastUpdate = null;
|
||||
let _lastError = null;
|
||||
@@ -31,12 +39,12 @@ export function createEarthquakesLayer({ source, overlayHost } = {}) {
|
||||
source: 'USGS',
|
||||
updateInterval: 60000,
|
||||
|
||||
init(viewer) {
|
||||
if (_viewer) throw new Error('Earthquake layer is already initialized');
|
||||
init(viewer, { engine = null } = {}) {
|
||||
if (_renderer) throw new Error('Earthquake layer is already initialized');
|
||||
_viewer = viewer;
|
||||
_dataSource = new Cesium.CustomDataSource('earthquakes');
|
||||
_dataSource.show = false;
|
||||
viewer.dataSources.add(_dataSource);
|
||||
_renderer = renderer.create({ viewer, engine });
|
||||
if (!_renderer) throw new Error('Earthquake renderer unavailable');
|
||||
_renderer.setVisible(false);
|
||||
_count = 0;
|
||||
_lastUpdate = null;
|
||||
_lastError = null;
|
||||
@@ -49,7 +57,7 @@ export function createEarthquakesLayer({ source, overlayHost } = {}) {
|
||||
_enabled = true;
|
||||
// No continuous-render hold: the discs are static geometry now, so the
|
||||
// layer has no per-frame animator to keep the render loop alive for.
|
||||
if (_dataSource) _dataSource.show = true;
|
||||
_renderer?.setVisible(true);
|
||||
overlayHost.setVisible(EARTHQUAKE_OVERLAY_SOURCE_ID, true);
|
||||
},
|
||||
|
||||
@@ -57,13 +65,13 @@ export function createEarthquakesLayer({ source, overlayHost } = {}) {
|
||||
_request?.abort();
|
||||
_request = null;
|
||||
_enabled = false;
|
||||
if (_dataSource) _dataSource.show = false;
|
||||
_renderer?.setVisible(false);
|
||||
overlayHost.clearSource(EARTHQUAKE_OVERLAY_SOURCE_ID);
|
||||
overlayHost.setVisible(EARTHQUAKE_OVERLAY_SOURCE_ID, false);
|
||||
},
|
||||
|
||||
async update(viewer) {
|
||||
if (!_enabled || !_dataSource) return false;
|
||||
if (!_enabled || !_renderer) return false;
|
||||
_request?.abort();
|
||||
const request = new AbortController();
|
||||
_request = request;
|
||||
@@ -72,7 +80,7 @@ export function createEarthquakesLayer({ source, overlayHost } = {}) {
|
||||
if (request.signal.aborted || _request !== request || !_enabled)
|
||||
return false;
|
||||
|
||||
const nextEntities = [];
|
||||
const nextDiscs = [];
|
||||
let count = 0;
|
||||
const overlayEntries = [];
|
||||
|
||||
@@ -93,34 +101,21 @@ export function createEarthquakesLayer({ source, overlayHost } = {}) {
|
||||
const fillAlpha = isSignificant ? 0.4 : 0.3;
|
||||
const outlineAlpha = isSignificant ? 1.0 : 0.8;
|
||||
|
||||
const position = Cesium.Cartesian3.fromDegrees(lon, lat);
|
||||
nextEntities.push(
|
||||
new Cesium.Entity({
|
||||
id: `earthquake:${stableId}`,
|
||||
position,
|
||||
ellipse: {
|
||||
// Static axes — see the module header. A CallbackProperty here
|
||||
// re-tessellates the clamped ground geometry every frame.
|
||||
semiMajorAxis: baseRadius,
|
||||
semiMinorAxis: baseRadius,
|
||||
material: new Cesium.ColorMaterialProperty(
|
||||
color.withAlpha(fillAlpha),
|
||||
),
|
||||
outline: true,
|
||||
outlineColor: color.withAlpha(outlineAlpha),
|
||||
outlineWidth: isSignificant ? 3 : 2,
|
||||
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
|
||||
},
|
||||
properties: {
|
||||
// Analyst seam (additive): the USGS event id (e.g. "us7000abcd").
|
||||
usgsId,
|
||||
mag,
|
||||
place,
|
||||
time,
|
||||
depth: depthKm,
|
||||
},
|
||||
}),
|
||||
);
|
||||
const position = geo.cartesian3.fromDegrees(lon, lat);
|
||||
nextDiscs.push({
|
||||
stableId,
|
||||
usgsId,
|
||||
position,
|
||||
baseRadius,
|
||||
color,
|
||||
isSignificant,
|
||||
fillAlpha,
|
||||
outlineAlpha,
|
||||
mag,
|
||||
place,
|
||||
time,
|
||||
depthKm,
|
||||
});
|
||||
overlayEntries.push(
|
||||
createEarthquakeOverlayEntry({
|
||||
id: String(stableId),
|
||||
@@ -131,8 +126,7 @@ export function createEarthquakesLayer({ source, overlayHost } = {}) {
|
||||
);
|
||||
}
|
||||
|
||||
_dataSource.entities.removeAll();
|
||||
for (const entity of nextEntities) _dataSource.entities.add(entity);
|
||||
_renderer.replace(nextDiscs);
|
||||
if (_enabled) {
|
||||
overlayHost.setEntries(
|
||||
EARTHQUAKE_OVERLAY_SOURCE_ID,
|
||||
@@ -168,10 +162,8 @@ export function createEarthquakesLayer({ source, overlayHost } = {}) {
|
||||
_enabled = false;
|
||||
overlayHost.clearSource(EARTHQUAKE_OVERLAY_SOURCE_ID);
|
||||
overlayHost.setVisible(EARTHQUAKE_OVERLAY_SOURCE_ID, false);
|
||||
if (_dataSource) {
|
||||
viewer.dataSources.remove(_dataSource, true);
|
||||
_dataSource = null;
|
||||
}
|
||||
_renderer?.destroy();
|
||||
_renderer = null;
|
||||
_count = 0;
|
||||
_lastUpdate = null;
|
||||
_lastError = null;
|
||||
@@ -186,39 +178,11 @@ export function createEarthquakesLayer({ source, overlayHost } = {}) {
|
||||
* @returns {Array<Object>} See mapAnalystRecord for the record shape.
|
||||
*/
|
||||
getAnalystRecords(maxCount = 2000) {
|
||||
if (!_dataSource || !_dataSource.show) return [];
|
||||
const entities = _dataSource.entities.values;
|
||||
if (!entities.length) return [];
|
||||
if (!_enabled || !_renderer) return [];
|
||||
const limit = Number.isFinite(maxCount)
|
||||
? Math.max(1, Math.floor(maxCount))
|
||||
: 2000;
|
||||
const now = Cesium.JulianDate.now();
|
||||
const result = [];
|
||||
for (const entity of entities) {
|
||||
if (result.length >= limit) break;
|
||||
const cartesian = entity.position
|
||||
? entity.position.getValue(now)
|
||||
: null;
|
||||
const carto = cartesian
|
||||
? Cesium.Cartographic.fromCartesian(cartesian)
|
||||
: null;
|
||||
const p = entity.properties;
|
||||
result.push(
|
||||
mapAnalystRecord(
|
||||
{
|
||||
id: p?.usgsId?.getValue(now) ?? null,
|
||||
mag: p?.mag?.getValue(now),
|
||||
place: p?.place?.getValue(now),
|
||||
time: p?.time?.getValue(now),
|
||||
depth: p?.depth?.getValue(now),
|
||||
lat: carto ? Cesium.Math.toDegrees(carto.latitude) : null,
|
||||
lon: carto ? Cesium.Math.toDegrees(carto.longitude) : null,
|
||||
},
|
||||
result.length,
|
||||
),
|
||||
);
|
||||
}
|
||||
return result;
|
||||
return _renderer.records(limit).map(mapAnalystRecord);
|
||||
},
|
||||
|
||||
getStats() {
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import * as Cesium from 'cesium';
|
||||
import { constantRgba } from '../shared/color.js';
|
||||
const RED = constantRgba(1, 0, 0);
|
||||
const ORANGE = constantRgba(1, 165 / 255, 0);
|
||||
const YELLOW = constantRgba(1, 1, 0);
|
||||
export const EARTHQUAKE_OVERLAY_SOURCE_ID = 'earthquakes';
|
||||
export const EARTHQUAKE_OVERLAY_COHORT_LIMIT = 96;
|
||||
export const EARTHQUAKE_OVERLAY_COLLISION_CAPACITY = 48;
|
||||
@@ -10,9 +13,9 @@ export const EARTHQUAKE_OVERLAY_COLLISION_CAPACITY = 48;
|
||||
* - Deep (>300km): Yellow
|
||||
*/
|
||||
export function depthColor(depthKm) {
|
||||
if (depthKm < 70) return Cesium.Color.RED;
|
||||
if (depthKm < 300) return Cesium.Color.ORANGE;
|
||||
return Cesium.Color.YELLOW;
|
||||
if (depthKm < 70) return RED;
|
||||
if (depthKm < 300) return ORANGE;
|
||||
return YELLOW;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -21,7 +24,7 @@ export function depthColor(depthKm) {
|
||||
* shared renderer.
|
||||
* @param {object} input
|
||||
* @param {string} input.id Stable USGS or deterministic fallback id.
|
||||
* @param {Cesium.Cartesian3} input.position Ground anchor shared with the pulse.
|
||||
* @param {object} input.position Ground anchor shared with the pulse.
|
||||
* @param {number} input.magnitude USGS magnitude.
|
||||
* @param {string} input.accent Source-owned depth-band color.
|
||||
* @returns {object}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { createEarthquakesCesiumRenderer } from './render/cesium.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { createEarthquakesLayer } from './index.js';
|
||||
@@ -17,6 +18,9 @@ function harness(source) {
|
||||
};
|
||||
const layer = createEarthquakesLayer({
|
||||
source,
|
||||
renderer: {
|
||||
create: ({ viewer }) => createEarthquakesCesiumRenderer(null, { viewer }),
|
||||
},
|
||||
overlayHost: {
|
||||
setEntries(...args) {
|
||||
events.push(args);
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
// Native earthquake entities, moved from the layer without changing its
|
||||
// static CLAMP_TO_GROUND ellipses, properties or analyst snapshot semantics.
|
||||
import * as Cesium from 'cesium';
|
||||
|
||||
export function createEarthquakesCesiumRenderer(_engine, { viewer }) {
|
||||
if (!viewer?.dataSources)
|
||||
throw new TypeError('Earthquakes require a native viewer');
|
||||
const dataSource = new Cesium.CustomDataSource('earthquakes');
|
||||
dataSource.show = false;
|
||||
viewer.dataSources.add(dataSource);
|
||||
let destroyed = false;
|
||||
return {
|
||||
kind: 'cesium',
|
||||
setVisible(show) {
|
||||
if (!destroyed) dataSource.show = show !== false;
|
||||
},
|
||||
replace(discs) {
|
||||
if (destroyed) return;
|
||||
const entities = discs.map(
|
||||
({
|
||||
stableId,
|
||||
usgsId,
|
||||
position,
|
||||
baseRadius,
|
||||
color,
|
||||
isSignificant,
|
||||
fillAlpha,
|
||||
outlineAlpha,
|
||||
mag,
|
||||
place,
|
||||
time,
|
||||
depthKm,
|
||||
}) =>
|
||||
new Cesium.Entity({
|
||||
id: `earthquake:${stableId}`,
|
||||
position,
|
||||
ellipse: {
|
||||
semiMajorAxis: baseRadius,
|
||||
semiMinorAxis: baseRadius,
|
||||
material: new Cesium.ColorMaterialProperty(
|
||||
color.withAlpha(fillAlpha),
|
||||
),
|
||||
outline: true,
|
||||
outlineColor: color.withAlpha(outlineAlpha),
|
||||
outlineWidth: isSignificant ? 3 : 2,
|
||||
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
|
||||
},
|
||||
properties: { usgsId, mag, place, time, depth: depthKm },
|
||||
}),
|
||||
);
|
||||
dataSource.entities.removeAll();
|
||||
for (const entity of entities) dataSource.entities.add(entity);
|
||||
},
|
||||
records(limit) {
|
||||
if (destroyed || !dataSource.show) return [];
|
||||
const now = Cesium.JulianDate.now();
|
||||
const rows = [];
|
||||
for (const entity of dataSource.entities.values) {
|
||||
if (rows.length >= limit) break;
|
||||
const position = entity.position?.getValue(now);
|
||||
const carto = position
|
||||
? Cesium.Cartographic.fromCartesian(position)
|
||||
: null;
|
||||
const p = entity.properties;
|
||||
rows.push({
|
||||
id: p?.usgsId?.getValue(now) ?? null,
|
||||
mag: p?.mag?.getValue(now),
|
||||
place: p?.place?.getValue(now),
|
||||
time: p?.time?.getValue(now),
|
||||
depth: p?.depth?.getValue(now),
|
||||
lat: carto ? Cesium.Math.toDegrees(carto.latitude) : null,
|
||||
lon: carto ? Cesium.Math.toDegrees(carto.longitude) : null,
|
||||
});
|
||||
}
|
||||
return rows;
|
||||
},
|
||||
destroy() {
|
||||
if (destroyed) return;
|
||||
destroyed = true;
|
||||
viewer.dataSources.remove(dataSource, true);
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import * as Cesium from 'cesium';
|
||||
import * as geo from '../../../geo/index.js';
|
||||
import { createEarthquakesLayer } from '../index.js';
|
||||
import { createEarthquakesCesiumRenderer } from './cesium.js';
|
||||
|
||||
const rows = [
|
||||
{
|
||||
stableId: 'a',
|
||||
usgsId: 'us-a',
|
||||
lon: -122.42,
|
||||
lat: 37.77,
|
||||
depthKm: 8,
|
||||
mag: 2.5,
|
||||
place: 'A',
|
||||
time: 1000,
|
||||
},
|
||||
{
|
||||
stableId: 'b',
|
||||
usgsId: 'us-b',
|
||||
lon: 30,
|
||||
lat: 20,
|
||||
depthKm: 70,
|
||||
mag: 5,
|
||||
place: 'B',
|
||||
time: 2000,
|
||||
},
|
||||
{
|
||||
stableId: 'c',
|
||||
usgsId: null,
|
||||
lon: 150,
|
||||
lat: -30,
|
||||
depthKm: 300,
|
||||
mag: 6,
|
||||
place: 'C',
|
||||
time: 3000,
|
||||
},
|
||||
];
|
||||
function harness() {
|
||||
const sources = new Set();
|
||||
const viewer = {
|
||||
dataSources: {
|
||||
add(source) {
|
||||
sources.add(source);
|
||||
},
|
||||
remove(source, destroy) {
|
||||
assert.equal(destroy, true);
|
||||
return sources.delete(source);
|
||||
},
|
||||
},
|
||||
};
|
||||
let snapshot = rows;
|
||||
const layer = createEarthquakesLayer({
|
||||
source: {
|
||||
async getSnapshot() {
|
||||
if (snapshot instanceof Error) throw snapshot;
|
||||
return snapshot;
|
||||
},
|
||||
},
|
||||
overlayHost: { setEntries() {}, setVisible() {}, clearSource() {} },
|
||||
renderer: {
|
||||
create: (options) => createEarthquakesCesiumRenderer(null, options),
|
||||
},
|
||||
});
|
||||
layer.init(viewer);
|
||||
layer.enable();
|
||||
return {
|
||||
viewer,
|
||||
sources,
|
||||
layer,
|
||||
setSnapshot(value) {
|
||||
snapshot = value;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
test('extracted native ground discs preserve static axes, depth palette and analyst identity', async () => {
|
||||
const h = harness();
|
||||
try {
|
||||
assert.equal(await h.layer.update(), true);
|
||||
const dataSource = [...h.sources][0];
|
||||
const now = Cesium.JulianDate.now();
|
||||
const colors = [Cesium.Color.RED, Cesium.Color.ORANGE, Cesium.Color.YELLOW];
|
||||
dataSource.entities.values.forEach((entity, index) => {
|
||||
const row = rows[index];
|
||||
const ellipse = entity.ellipse;
|
||||
assert.equal(entity.id, `earthquake:${row.stableId}`);
|
||||
assert.equal(ellipse.semiMajorAxis.isConstant, true);
|
||||
assert.equal(ellipse.semiMinorAxis.getValue(now), 2 ** row.mag * 1000);
|
||||
assert.equal(ellipse.semiMajorAxis.getValue(now), 2 ** row.mag * 1000);
|
||||
assert.equal(
|
||||
ellipse.heightReference.getValue(now),
|
||||
Cesium.HeightReference.CLAMP_TO_GROUND,
|
||||
);
|
||||
assert.equal(ellipse.outlineWidth.getValue(now), row.mag >= 5 ? 3 : 2);
|
||||
assert.deepEqual(
|
||||
{ ...ellipse.material.color.getValue(now) },
|
||||
{ ...colors[index].withAlpha(row.mag >= 5 ? 0.4 : 0.3) },
|
||||
);
|
||||
const expected = Cesium.Cartesian3.fromDegrees(row.lon, row.lat);
|
||||
assert.deepEqual(entity.position.getValue(now), expected);
|
||||
assert.deepEqual(
|
||||
{ ...geo.cartesian3.fromDegrees(row.lon, row.lat) },
|
||||
{
|
||||
x: expected.x,
|
||||
y: expected.y,
|
||||
z: expected.z,
|
||||
},
|
||||
);
|
||||
});
|
||||
const records = h.layer.getAnalystRecords();
|
||||
assert.deepEqual(
|
||||
records.map((r) => r.id),
|
||||
['us-a', 'us-b', 'QUAKE-0002'],
|
||||
);
|
||||
assert.equal(h.layer.getAnalystRecords(1).length, 1);
|
||||
assert.equal(h.layer.getAnalystRecords(0).length, 1);
|
||||
assert.equal(h.layer.getAnalystRecords(Infinity).length, 3);
|
||||
h.layer.disable();
|
||||
assert.deepEqual(h.layer.getAnalystRecords(), []);
|
||||
assert.equal(dataSource.show, false);
|
||||
} finally {
|
||||
h.layer.destroy();
|
||||
}
|
||||
assert.equal(h.sources.size, 0);
|
||||
});
|
||||
|
||||
test('failed native refresh retains the last complete geometry and analyst snapshot', async () => {
|
||||
const h = harness();
|
||||
try {
|
||||
await h.layer.update();
|
||||
const source = [...h.sources][0];
|
||||
const before = [...source.entities.values];
|
||||
const records = h.layer.getAnalystRecords();
|
||||
h.setSnapshot(new Error('fixture source unavailable'));
|
||||
assert.equal(await h.layer.update(), false);
|
||||
assert.deepEqual(source.entities.values, before);
|
||||
assert.deepEqual(h.layer.getAnalystRecords(), records);
|
||||
assert.equal(h.layer.getStats().error, 'fixture source unavailable');
|
||||
h.setSnapshot([]);
|
||||
assert.equal(await h.layer.update(), true);
|
||||
assert.equal(source.entities.values.length, 0);
|
||||
assert.equal(h.layer.getStats().error, null);
|
||||
} finally {
|
||||
h.layer.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
test('renderer destroys its owner even when passed another viewer and repeated destroy is safe', () => {
|
||||
const h = harness();
|
||||
const alien = {
|
||||
dataSources: {
|
||||
remove() {
|
||||
assert.fail('must not remove from another viewer');
|
||||
},
|
||||
},
|
||||
};
|
||||
h.layer.destroy(alien);
|
||||
h.layer.destroy(alien);
|
||||
assert.equal(h.sources.size, 0);
|
||||
});
|
||||
@@ -341,7 +341,7 @@ test('layers moved onto renderers keep each engine in its render file', (t) => {
|
||||
"export const load = () => import('../layers/flights/render/navara.js');",
|
||||
);
|
||||
// A layer not moved yet still imports cesium anywhere (until its *a task).
|
||||
write('src/layers/earthquakes/rendering.js', "import 'cesium';");
|
||||
write('src/layers/wind/rendering.js', "import 'cesium';");
|
||||
assert.doesNotThrow(() => checkImportDirections(root));
|
||||
|
||||
write('src/layers/flights/tracking.js', "import 'cesium';");
|
||||
|
||||
Reference in new issue
Block a user