mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
feat: add Nepal flood incident scene
This commit is contained in:
1 parent
76c20be277
commit
60768ccc0b
48 files changed
+15431
-161
No files matched your search
@@ -0,0 +1,65 @@
|
||||
import { BHOTE_KOSHI_FLOOD_PATH } from './bhoteKoshiFloodPath.js';
|
||||
|
||||
export const SOURCE_PATH_BEAT_IDS = Object.freeze([
|
||||
'debris-dammed-lake', 'second-landslide', 'dhunche',
|
||||
'mailung-upper-trishuli', 'mailung-bazzar', 'dandagaun',
|
||||
'dandagaun-viewpoint', 'betrawati-bazaar', 'bhainse', 'bidur-trishuli-bridge',
|
||||
]);
|
||||
|
||||
function nearestVertex(point, route) {
|
||||
if (!point || !Number.isFinite(point.lon) || !Number.isFinite(point.lat)) return -1;
|
||||
const longitudeScale = Math.cos(point.lat * Math.PI / 180);
|
||||
let nearest = -1;
|
||||
let distance = 1000; // Witness viewpoints can sit beside the river, not on it.
|
||||
route.forEach(([lon, lat], index) => {
|
||||
const metres = Math.hypot((lon - point.lon) * longitudeScale, lat - point.lat) * 111195;
|
||||
if (metres < distance) { distance = metres; nearest = index; }
|
||||
});
|
||||
return nearest;
|
||||
}
|
||||
|
||||
/** Split the already-bundled GeoPera centreline; never connect witness pins. */
|
||||
export function buildSourceShotPaths(event, route = BHOTE_KOSHI_FLOOD_PATH) {
|
||||
const observations = new Map((event.evidenceSpine || []).map((point) => [point.id, point]));
|
||||
const result = new Map();
|
||||
const add = (id, from, to, { joinComparison = false } = {}) => {
|
||||
let start = nearestVertex(from, route);
|
||||
const end = nearestVertex(to, route);
|
||||
if (start < 0 || end <= start) return;
|
||||
const startHeight = from.fallbackElevationM ?? from.elevationM;
|
||||
const endHeight = to.fallbackElevationM ?? to.elevationM;
|
||||
if (!Number.isFinite(startHeight) || !Number.isFinite(endHeight)) return;
|
||||
if (joinComparison) {
|
||||
// The raster corridor ends between simplified centreline vertices.
|
||||
// Snapping to its nearest vertex can move the head upstream on entry.
|
||||
// Keep that already-sourced endpoint and continue to the next vertex
|
||||
// downstream of it, rather than replaying the upstream half-segment.
|
||||
const [lon, lat] = route[start];
|
||||
const [nextLon, nextLat] = route[start + 1];
|
||||
const scale = Math.cos(from.lat * Math.PI / 180);
|
||||
const along = (from.lon - lon) * (nextLon - lon) * scale * scale
|
||||
+ (from.lat - lat) * (nextLat - lat);
|
||||
if (along > 0) start++;
|
||||
}
|
||||
const coordinates = route.slice(start, end + 1);
|
||||
if (joinComparison && (coordinates[0][0] !== from.lon || coordinates[0][1] !== from.lat)) {
|
||||
coordinates.unshift([from.lon, from.lat]);
|
||||
}
|
||||
result.set(id, coordinates.map(([lon, lat], index) => ({
|
||||
lon, lat,
|
||||
// Stable source profile for explicit source-elevation shots; otherwise a
|
||||
// fallback when neither rendered mesh nor elevation terrain can be sampled.
|
||||
fallbackElevationM: startHeight + (endHeight - startHeight) * index / (coordinates.length - 1),
|
||||
})));
|
||||
};
|
||||
add('debris-dammed-lake', observations.get('debris-dammed-lake'), observations.get('second-landslide'));
|
||||
add('second-landslide', observations.get('second-landslide'), observations.get('gyirong-border-gate'));
|
||||
let previous = event.reconstruction?.corridor?.at(-1);
|
||||
for (const id of SOURCE_PATH_BEAT_IDS.slice(2)) {
|
||||
const point = observations.get(id);
|
||||
add(id, previous, point, { joinComparison: id === 'dhunche' });
|
||||
// Missing coverage breaks continuity rather than inventing a long connector.
|
||||
previous = point;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
Reference in new issue
Block a user