mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 02:44:02 +00:00
fix(geo): wrap longitude differences across the antimeridian
The flights ground-floor pipeline subtracted longitudes without wrapping. approxDistanceKm, and its copy in the mesh-floor sampler, measured two points 0.2° apart either side of 180° (21 km at Fiji) as about 38,000 km, so low and grounded aircraft just across the line from the viewer were never floored or mesh-sampled. corridorFloorCells walked a segment across 180° the long way round, filling its cell budget with ground behind the contact and never requesting the cells it was about to cross, and stickyFloorCell dropped its hysteresis for a contact on the seam. Each now takes the short way round, and corridor points are normalised back into [-180, 180]. SEARCH NEARBY SITES centred its Google Places search on the mean of west and east, which for a view across 180° (west > east) is longitude 0, and sized the radius from the view's height alone. It now measures the view's width through 180° and searches its real centre.
This commit is contained in:
1 parent
d4492d8f8c
commit
2c61d9e2b7
9 files changed
+146
-17
No files matched your search
@@ -133,15 +133,16 @@ export function createIngestion({
|
||||
let placesError = null;
|
||||
if (layerState.googleSearchRequested) {
|
||||
layerState.googleSearchRequested = false;
|
||||
// A view across 180° has west > east; its width runs through 180°.
|
||||
const lonSpan = box.east - box.west + (box.east < box.west ? 360 : 0);
|
||||
const latitude = (box.south + box.north) / 2;
|
||||
const longitude = (box.west + box.east) / 2;
|
||||
let longitude = box.west + lonSpan / 2;
|
||||
if (longitude > 180) longitude -= 360;
|
||||
const radiusM = Math.min(
|
||||
50000,
|
||||
Math.max(
|
||||
1000,
|
||||
Math.round(
|
||||
Math.max(box.north - box.south, box.east - box.west) * 55_000,
|
||||
),
|
||||
Math.round(Math.max(box.north - box.south, lonSpan) * 55_000),
|
||||
),
|
||||
);
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { createIngestion } from './ingestion.js';
|
||||
|
||||
// Taveuni, Fiji: Cesium reports a view across 180° with west > east. Each view
|
||||
// is 0.4° wide and 0.2° tall; the last one does not cross 180°.
|
||||
for (const [west, east, centre] of [
|
||||
[179.7, -179.9, 179.9],
|
||||
[179.9, -179.7, -179.9],
|
||||
[179.5, 179.9, 179.7],
|
||||
])
|
||||
test(`a nearby search is centred on the view at ${centre}`, async () => {
|
||||
const box = { south: -17, west, north: -16.8, east };
|
||||
const searches = [];
|
||||
const state = {
|
||||
enabled: true,
|
||||
viewer: {},
|
||||
records: [],
|
||||
googleSearchRequested: true,
|
||||
};
|
||||
const ingestion = createIngestion({
|
||||
state,
|
||||
source: {
|
||||
getMappedSites: async () => ({ records: [], wide: true }),
|
||||
searchNearby: async (query) => {
|
||||
searches.push(query);
|
||||
return { places: [] };
|
||||
},
|
||||
},
|
||||
services: {
|
||||
render: { governorRequestRender() {} },
|
||||
ground: { resolveGroundFloorCellsBounded: async () => {} },
|
||||
},
|
||||
parts: {
|
||||
viewport: {
|
||||
loadArea: () => ({ box, coverage: {} }),
|
||||
clearUnavailableRetry() {},
|
||||
scheduleUnavailableRetry() {},
|
||||
},
|
||||
model: { installationWithinViewport: () => true },
|
||||
rendering: { renderRecords() {}, warmInstallationFloors() {} },
|
||||
},
|
||||
});
|
||||
await ingestion.loadInstallations();
|
||||
assert.equal(searches.length, 1);
|
||||
const { latitude, longitude, radiusM } = searches[0];
|
||||
assert.ok(Math.abs(latitude + 16.9) < 1e-9);
|
||||
assert.ok(Math.abs(longitude - centre) < 1e-9, `longitude ${longitude}`);
|
||||
// The width, not the height, sets the radius.
|
||||
assert.equal(radiusM, 22000);
|
||||
});
|
||||
Reference in new issue
Block a user