worldmap-viewer

git clone https://git.godosa.eu/worldmap-viewer

master

raw · 1537 bytes

// 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;
}