aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/viewer/js/profile.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/profile.js
downloadworldmap-viewer-3443c1c65e9f1753e1e656b35d08416c1fa298f2.tar.gz
worldmap-viewer-3443c1c65e9f1753e1e656b35d08416c1fa298f2.zip
worldmap-viewer: initial public history
Diffstat (limited to 'viewer/js/profile.js')
-rw-r--r--viewer/js/profile.js37
1 files changed, 37 insertions, 0 deletions
diff --git a/viewer/js/profile.js b/viewer/js/profile.js
new file mode 100644
index 0000000..695ba29
--- /dev/null
+++ b/viewer/js/profile.js
@@ -0,0 +1,37 @@
+// profile.js — elevation profile chart model (pure): samples {d_km, z_m, water} → SVG path data + scales
+const PAD = { l: 40, r: 6, t: 8, b: 18 };
+
+export function profileModel(samples, w, h) {
+ const L = samples.at(-1).d_km || 1;
+ const zs = samples.map(s => s.z_m);
+ const lo = Math.min(0, ...zs);
+ const hi = Math.max(lo + 100, 0, ...zs);
+ const X = d => PAD.l + (d / L) * (w - PAD.l - PAD.r);
+ const Y = z => PAD.t + (1 - (z - lo) / (hi - lo)) * (h - PAD.t - PAD.b);
+ const line = samples.map((s, i) => `${i ? 'L' : 'M'}${X(s.d_km).toFixed(1)},${Y(s.z_m).toFixed(1)}`).join('');
+ const area = `${line}L${X(L).toFixed(1)},${Y(lo).toFixed(1)}L${X(0).toFixed(1)},${Y(lo).toFixed(1)}Z`;
+ const half = L / Math.max(1, samples.length - 1) / 2;
+ const water = [];
+ let start = null;
+ samples.forEach((s, i) => {
+ if (s.water && start === null) start = i;
+ const last = i === samples.length - 1;
+ if (start !== null && (!s.water || last)) {
+ const end = s.water ? i : i - 1;
+ water.push([X(Math.max(0, samples[start].d_km - half)), X(Math.min(L, samples[end].d_km + half))]);
+ start = null;
+ }
+ });
+ const xAt = px => ((px - PAD.l) / (w - PAD.l - PAD.r)) * L;
+ return { line, area, water, seaY: Y(0), lo, hi, L, X, Y, xAt };
+}
+
+export function sampleAt(samples, d) {
+ let a = 0, b = samples.length - 1;
+ while (b - a > 1) {
+ const m = (a + b) >> 1;
+ if (samples[m].d_km <= d) a = m;
+ else b = m;
+ }
+ return Math.abs(samples[a].d_km - d) <= Math.abs(samples[b].d_km - d) ? a : b;
+}