Merge branch 'main' into codex/shared-geodesy

This commit is contained in:
Sameh Khamis committed 2026-10-17 11:42:58 -07:00
commit 64d7ed3c61
1373 files changed
+245910 -10664

No files matched your search

+50 -19
View File
@@ -11,11 +11,12 @@
*
* PURE data module — no Cesium imports, node-testable. The packs are lazy-
* loaded on first lookup and cached in module scope (bbox/area computed once
* at load). In the browser Vite bundles the JSON via dynamic import; under
* node the same files are read from disk. A failed load is retried on the
* next lookup rather than cached (see `createRetryableLoader`).
* at load) through `loadBundledJson`, which works in the browser and under
* node:test. A failed load is retried on the next lookup rather than cached
* (see `createRetryableLoader`).
*/
import { loadBundledJson } from './bundledJson.js';
import { createRetryableLoader } from './retryableLoad.js';
import { EARTH_RADIUS_KM, greatCircleKm } from '../geoDistance.js';
@@ -111,20 +112,14 @@ function suffixVariants(norm) {
/** @type {Array|null} flat entry list for listRegions() */
let _entries = null;
async function loadPackFile(base) {
// Vite bundles these JSON files as modules; the import attribute is what Node
// needs to load the same files under node:test (same pattern as
// neighborhoodPolygons.js). One path, so no node: import reaches the browser.
const mod =
base === 'regions'
? await import('./local_data/natural_earth/regions.json', {
with: { type: 'json' },
})
: await import('./local_data/natural_earth/marine.json', {
with: { type: 'json' },
});
return mod.default || mod;
}
const PACKS = {
regions: {
url: new URL('./local_data/natural_earth/regions.json', import.meta.url),
},
marine: {
url: new URL('./local_data/natural_earth/marine.json', import.meta.url),
},
};
function buildEntries(pack, kind) {
const out = [];
@@ -169,8 +164,8 @@ function buildEntries(pack, kind) {
*/
const loadIndex = createRetryableLoader(async () => {
const [regions, marine] = await Promise.all([
loadPackFile('regions'),
loadPackFile('marine'),
loadBundledJson(PACKS.regions.url),
loadBundledJson(PACKS.marine.url),
]);
_entries = [
...buildEntries(regions, 'natural'),
@@ -316,3 +311,39 @@ export async function lookupNaturalRegionOutline(query, lat, lon) {
}
return null;
}
/** Resolve the smallest containing bundled physical region without a network geocoder. */
export async function naturalRegionAtPoint(latitude, longitude) {
if (
![latitude, longitude].every(Number.isFinite) ||
Math.abs(latitude) > 90 ||
Math.abs(longitude) > 180
)
return null;
await loadIndex();
let best = null;
for (const entry of _entries) {
const [west, south, east, north] = entry.bbox;
if (
longitude < west ||
longitude > east ||
latitude < south ||
latitude > north
)
continue;
if (best && entry.areaKm2 >= best.areaKm2) continue;
if (entry.polygons.some((ring) => pointInRing(ring, latitude, longitude)))
best = entry;
}
return best
? {
label: best.name,
locality: null,
region: best.name,
country: null,
countryCode: null,
source: 'Natural Earth',
kind: best.kind,
}
: null;
}