worldmap-viewer

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

master

raw · 1530 bytes

// riverlod.js — which river orders the rivers overlay draws at a scale: those whose rivers lie far enough apart on
// screen not to merge into a blue sheet. First-order channels lie about one cell step apart; order k's are as much
// farther apart as their total length is shorter (rivers are lines: spacing ≈ area / length).
import { distanceKm } from './geo.js';

export const MIN_GAP_PX = 8;

export function cellSpacingKm(res, radiusKm) {   // mean distance between H3 cell centres at a resolution
  return Math.sqrt((4 * Math.PI * radiusKm ** 2) / (2 + 120 * 7 ** res));
}

export function riverStats(fc) {   // {length: {order: total km}} from rivers.geojson
  const length = {};
  for (const f of fc.features ?? []) {
    const o = f.properties?.order ?? 1, c = f.geometry?.coordinates ?? [];
    let km = 0;
    for (let i = 1; i < c.length; i++) {
      km += distanceKm({ lat: c[i - 1][1], lon: c[i - 1][0] }, { lat: c[i][1], lon: c[i][0] });
    }
    length[o] = (length[o] ?? 0) + km;
  }
  return { length };
}

export function riverMinOrder(kmPerPx, { length }, cellKm, minGap = MIN_GAP_PX) {
  const orders = Object.keys(length).map(Number).filter(k => length[k] > 0).sort((a, b) => a - b);
  if (!orders.length) return 1;
  if (!(kmPerPx > 0) || !Number.isFinite(kmPerPx)) return orders.at(-1);
  const l1 = length[orders[0]];
  for (const k of orders) if ((cellKm * l1) / length[k] >= minGap * kmPerPx) return k;
  return orders.at(-1);                                   // whole planet: just the biggest
}