aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/viewer/js/exports.js
diff options
context:
space:
mode:
authorgodosa <godosa@godosa.eu>2026-10-07 00:14:38 +0200
committergodosa <godosa@godosa.eu>2026-10-07 00:14:38 +0200
commit3443c1c65e9f1753e1e656b35d08416c1fa298f2 (patch)
tree4e43236f460145a4d75d1b4616dcb7aa6ef08f51 /viewer/js/exports.js
downloadworldmap-viewer-3443c1c65e9f1753e1e656b35d08416c1fa298f2.tar.gz
worldmap-viewer-3443c1c65e9f1753e1e656b35d08416c1fa298f2.zip
worldmap-viewer: initial public history
Diffstat (limited to 'viewer/js/exports.js')
-rw-r--r--viewer/js/exports.js40
1 files changed, 40 insertions, 0 deletions
diff --git a/viewer/js/exports.js b/viewer/js/exports.js
new file mode 100644
index 0000000..25d66ea
--- /dev/null
+++ b/viewer/js/exports.js
@@ -0,0 +1,40 @@
+// exports.js — terrain export helpers (pure): sample count, the square on the map, size estimate, status text
+import { R_KM } from './geo.js';
+export { R_KM };
+
+export function samplesFor(sizeKm, resM) { // the smallest 2^n + 1 covering the size (as export.samples_for)
+ const need = (sizeKm * 1000) / resM + 1;
+ let n = 1;
+ while (2 ** n + 1 < need) n++;
+ return 2 ** n + 1;
+}
+
+function destination(lat, lon, bearing, km, R) {
+ const r = Math.PI / 180, d = km / R, la = lat * r, b = bearing;
+ const la2 = Math.asin(Math.sin(la) * Math.cos(d) + Math.cos(la) * Math.sin(d) * Math.cos(b));
+ const lo2 = lon * r + Math.atan2(Math.sin(b) * Math.sin(d) * Math.cos(la), Math.cos(d) - Math.sin(la) * Math.sin(la2));
+ return { lat: la2 / r, lon: ((lo2 / r + 540) % 360) - 180 };
+}
+
+export function squareOutline(lat, lon, sizeKm, R = R_KM, per = 8) { // the export square (azimuthal equidistant)
+ const h = sizeKm / 2, pts = [];
+ const corners = [[-h, h], [h, h], [h, -h], [-h, -h], [-h, h]]; // [x east, y north], from the north-west
+ for (let k = 0; k < 4; k++) {
+ for (let i = 0; i < per; i++) {
+ const t = i / per, x = corners[k][0] + (corners[k + 1][0] - corners[k][0]) * t;
+ const y = corners[k][1] + (corners[k + 1][1] - corners[k][1]) * t;
+ pts.push(destination(lat, lon, Math.atan2(x, y), Math.hypot(x, y), R));
+ }
+ }
+ pts.push(pts[0]);
+ return pts;
+}
+
+export const exportSizeMB = n => (n * n * 7.8) / 1e6; // f32 + 16-bit PNG + raw + preview (the island: 128 MB)
+
+export function exportStatusText(s) {
+ if (!s || s.state === 'idle') return '';
+ if (s.state === 'running') return `Exporting ${s.name}… ${Math.round((s.fraction ?? 0) * 100)}%`;
+ if (s.state === 'failed') return `Export ${s.name} failed: ${s.error ?? 'unknown error'}`;
+ return `Exported ${s.name}`;
+}