diff options
Diffstat (limited to 'viewer/js/profile.js')
| -rw-r--r-- | viewer/js/profile.js | 37 |
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; +} |
