mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 18:34:02 +00:00
- Imported metadata stays inert: descriptions, native labels, properties and KML extended data are dropped from every entity; names are kept as short plain text. GeoJSON loads with a describe that builds no HTML, and simplestyle (including marker-symbol) is dropped, so no icon asset is fetched for a file and GeoJSON draws in its row's color. - Bound geometry before loading: features and vertices are counted in the parsed GeoJSON, the KML document and while reading GPX, and a file over 20,000 features or 250,000 vertices is refused before Cesium builds it. - Imports run one batch at a time, so concurrent picks or drops cannot pass the 12-file cap. - Fly-to framing walks long tracks by index instead of spreading them into a call. - Fly-to is an immediate navigation through the application shell; the fly after an import is a deferred navigation stamped when the batch starts and re-asserted just before flying. - Dated imports never change the shared clock: imported sources expose no clock, entities are available for all time, and a KML gx:Track is drawn as its line. - GPX is read into GeoJSON with one line per track segment, without times. - KML/KMZ rows show a hatched swatch (they keep their own styles); keyboard focus is kept on the same control after hide/show and moves to the next row after remove. - Unit regressions for each, and the rendered QA now imports hostile metadata, dated KML/GPX and a two-segment track, and fails on any request for a file's contents or icon assets, a clock change, or surviving metadata. Co-Authored-By: Claude Opus 5.5 <[email protected]>
77 lines
2.6 KiB
JavaScript
77 lines
2.6 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import * as Cesium from 'cesium';
|
|
import { dataSourcePoints, flyToDataSource } from './flyToDataSource.js';
|
|
|
|
function source() {
|
|
const ds = new Cesium.CustomDataSource('t');
|
|
ds.entities.add({
|
|
position: Cesium.Cartesian3.fromDegrees(-122.4862, 37.7694, -2667),
|
|
billboard: { heightReference: Cesium.HeightReference.CLAMP_TO_GROUND },
|
|
});
|
|
ds.entities.add({
|
|
polyline: {
|
|
positions: Cesium.Cartesian3.fromDegreesArray([
|
|
-122.49, 37.77, -122.48, 37.771,
|
|
]),
|
|
},
|
|
});
|
|
ds.entities.add({
|
|
polygon: {
|
|
hierarchy: Cesium.Cartesian3.fromDegreesArray([
|
|
-122.5, 37.76, -122.49, 37.76, -122.49, 37.765,
|
|
]),
|
|
},
|
|
});
|
|
return ds;
|
|
}
|
|
|
|
test('points come from positions, lines and polygons, as lon/lat only', () => {
|
|
const points = dataSourcePoints(source());
|
|
assert.equal(points.length, 6);
|
|
assert.ok(Math.abs(points[0][0] + 122.4862) < 1e-6);
|
|
assert.ok(Math.abs(points[0][1] - 37.7694) < 1e-6);
|
|
});
|
|
|
|
test('the camera frames the footprint at the surface, never a buried center', () => {
|
|
const calls = [];
|
|
const viewer = {
|
|
camera: {
|
|
heading: 0,
|
|
flyToBoundingSphere: (sphere, options) => calls.push({ sphere, options }),
|
|
},
|
|
flyTo: () => calls.push('viewer.flyTo'),
|
|
};
|
|
assert.equal(flyToDataSource(viewer, source()), true);
|
|
const center = Cesium.Cartographic.fromCartesian(calls[0].sphere.center);
|
|
assert.ok(Math.abs(center.height) < 50, `center height ${center.height}`);
|
|
assert.ok(calls[0].options.offset.range >= 800);
|
|
assert.equal(
|
|
typeof calls[0].options.complete,
|
|
'function',
|
|
'the ground guard runs on landing',
|
|
);
|
|
assert.equal(
|
|
flyToDataSource(viewer, new Cesium.CustomDataSource('empty')),
|
|
false,
|
|
);
|
|
assert.equal(calls.at(-1), 'viewer.flyTo');
|
|
});
|
|
|
|
test('a very long track is framed without spreading it into a call', () => {
|
|
// 400k vertices: `push(...line)` throws RangeError (too many arguments)
|
|
// well below this; the walk keeps a bounded sample and both ends.
|
|
const n = 400_000;
|
|
const line = new Array(n);
|
|
for (let i = 0; i < n; i++)
|
|
line[i] = Cesium.Cartesian3.fromDegrees(-120 + (i / n) * 2, 40);
|
|
const ds = new Cesium.CustomDataSource('long');
|
|
ds.entities.add({ polyline: { positions: line } });
|
|
ds.entities.add({ position: Cesium.Cartesian3.fromDegrees(-110, 41) });
|
|
const points = dataSourcePoints(ds);
|
|
assert.ok(points.length <= 5002, `${points.length} points kept`);
|
|
const lons = points.map(([lon]) => lon);
|
|
assert.ok(Math.min(...lons) < -119.99 && Math.max(...lons) > -110.01);
|
|
assert.ok(lons.some((lon) => Math.abs(lon - -118.000005) < 0.01));
|
|
});
|