mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 03:14:00 +00:00
Merge branch 'main' into codex/shared-geodesy
This commit is contained in:
commit
64d7ed3c61
1373 files changed
+245910
-10664
No files matched your search
@@ -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;
|
||||
}
|
||||
Reference in new issue
Block a user