Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

facett-map3d/tests/scene_scale_metric_constants.rs

//! **Every render/extrude constant that means a LENGTH is metric — asserted at TWO
//! SCALES, because one scale cannot see this defect.**
//!
//! Three separate bugs in this crate have been the same mistake: an absolute
//! design-unit constant weighed against a metrically scaled scene. `GROUND_LIFT` and
//! `BUILDING_RISE_EPS` were the first two. `extrude::WATER_HEIGHT` (`5.0e-3 du`) and
//! the fragment shader's height haze (`0.25 du`) were the third and fourth, plus the
//! SSAO radius (`0.16 du`).
//!
//! A design unit is **whatever the data's span makes it**: 625 m in the fixture,
//! 1875 m in the 3 km town window `korp` flies, 62 741 m in a region load. So an
//! absolute `5.0e-3 du` water plane is `3.1 m`, `9.4 m` and `174 m` of clearance in
//! those three scenes — the same literal, three different physical objects.
//!
//! **Why two scales, and why these two.** A guard that measures at one span cannot
//! distinguish `f(du_per_m)` from a constant: any single measurement is consistent
//! with both. Worse is the IDENTITY-VALUE trap — a scene that happens to sit near
//! `du_per_m == 1` makes a scaled constant and an unscaled one numerically equal. Both
//! spans here are decades away from `du_per_m == 1` (`5.3e-4` and `1.6e-5`) and a
//! factor **33 apart** from each other, so a constant that failed to scale shows up as
//! a 33× error and cannot hide.
//!
//! Each guard carries its own **RED**: the legacy absolute is run through the same
//! assertion and asserted to FAIL it. A guard that has never reported red is not a
//! guard (LAW 2), and these specific guards replace ones that could not.

use facett_map::MapPalette;
use facett_map3d::backend;
use facett_map3d::extrude;
use facett_map::Way;

/// A square town of `n×n` little building rings spread over `span_deg` of longitude /
/// latitude, centred on Stockholm's latitude so the metre-per-degree factor is real.
/// The SAME topology at every span — only the ground it covers changes, which is
/// exactly the variable these constants must track and the shape of the bug.
fn town(span_deg: f64, n: usize) -> Vec<Way> {
    let pal = MapPalette::cartographic(true);
    let (lon0, lat0) = (18.0_f64, 59.33_f64);
    let step = span_deg / n as f64;
    // A building footprint that stays a fixed FRACTION of the span, so the geometry is
    // similar at both scales and only `du_per_m` moves.
    let d = step * 0.35;
    let mut ways = Vec::with_capacity(n * n + 1);
    for j in 0..n {
        for i in 0..n {
            let (x, y) = (lon0 + i as f64 * step, lat0 + j as f64 * step);
            let ring = [(x, y), (x + d, y), (x + d, y + d), (x, y + d), (x, y)];
            if let Some(w) = Way::from_lonlat_with(
                (j * n + i) as i64 + 1,
                &ring,
                &[("building".to_string(), "yes".to_string()), ("height".to_string(), "12".to_string())],
                &pal,
            ) {
                ways.push(w);
            }
        }
    }
    // One lake, so the water plane has something to be the plane OF.
    let (x, y) = (lon0 + span_deg * 0.55, lat0 + span_deg * 0.55);
    let lake = [(x, y), (x + span_deg * 0.2, y), (x + span_deg * 0.2, y + span_deg * 0.2), (x, y + span_deg * 0.2), (x, y)];
    if let Some(w) = Way::from_lonlat_with(
        900_001,
        &lake,
        &[("natural".to_string(), "water".to_string())],
        &pal,
    ) {
        ways.push(w);
    }
    ways
}

/// The 3 km town window `densest_cluster_subset` produces — `korp`'s actual viewport.
const CITY_DEG: f64 = 0.0270; // ≈ 3.0 km of latitude
/// A region load, ~17× wider. `du_per_m` here is `3.2e-5`: an absolute constant that
/// "looked right" in the city is off by 17× in this scene, and vice versa.
///
/// Deliberately kept INSIDE [`extrude::MIN_GROUND_BAND`]'s documented honest bound
/// (`du_per_m > 2.5e-5`, i.e. a span under ~64 km). Past that bound `ground_band` — and
/// `water_height`, which is floored above it — stop tracking the scene and start
/// meaning "a clear margin above the kerb" instead of an exact metre count. That is
/// documented, deliberate behaviour, and [`past_the_honest_bound_the_floor_takes_over`]
/// asserts it *as such* rather than letting this table quietly tolerate it.
const REGION_DEG: f64 = 0.4500; // ≈ 50 km of latitude
/// Past the honest bound — where `MIN_GROUND_BAND` governs instead of the metre.
const CONTINENT_DEG: f64 = 0.9000; // ≈ 100 km of latitude

/// The two scenes, with their measured scales — printed so a failure reads as a
/// number and not as a boolean (LAW 7).
fn two_scales() -> ((Vec<Way>, f32), (Vec<Way>, f32)) {
    let city = town(CITY_DEG, 14);
    let region = town(REGION_DEG, 14);
    let dc = extrude::design_units_per_metre(&city).expect("the city has a world span");
    let dr = extrude::design_units_per_metre(&region).expect("the region has a world span");
    println!(
        "  city   span {:8.0} m   du_per_m {dc:.3e}   metres_per_du {:9.1}",
        extrude::world_span_metres(&city).unwrap(),
        1.0 / dc
    );
    println!(
        "  region span {:8.0} m   du_per_m {dr:.3e}   metres_per_du {:9.1}",
        extrude::world_span_metres(&region).unwrap(),
        1.0 / dr
    );
    assert!(dc / dr > 10.0, "the two scales are decades apart, not a rounding error: {:.1}×", dc / dr);
    assert!(dr > 2.5e-5, "the region stays inside MIN_GROUND_BAND's honest bound ({dr:e})");
    assert!(dc < 0.1 && dr < 0.1, "neither scene sits near the du_per_m == 1 identity trap ({dc:e}, {dr:e})");
    ((city, dc), (region, dr))
}

/// A design-unit length read back as **metres** at the scale it was computed for.
fn metres(du: f32, du_per_m: f32) -> f32 {
    du / du_per_m
}

/// **THE guard.** Each metric length must read the SAME number of metres in both
/// scenes; the legacy absolute must not. Every constant, both directions, one table.
#[test]
fn every_length_constant_means_the_same_metres_at_both_scales() {
    let ((city, dc), (region, dr)) = two_scales();

    // (name, du at city, du at region, the metres it claims to be, tolerance %)
    let rows: Vec<(&str, f32, f32, f32)> = vec![
        ("ground_band", extrude::ground_band(Some(dc)), extrude::ground_band(Some(dr)), extrude::GROUND_BAND_METRES),
        (
            "building_rise_eps",
            extrude::building_rise_eps(Some(dc)),
            extrude::building_rise_eps(Some(dr)),
            extrude::BUILDING_RISE_METRES,
        ),
        ("water_height", extrude::water_height(Some(dc)), extrude::water_height(Some(dr)), extrude::WATER_RISE_METRES),
        (
            "haze_scale_height",
            backend::haze_scale_height(Some(dc)),
            backend::haze_scale_height(Some(dr)),
            backend::HAZE_SCALE_HEIGHT_METRES,
        ),
        ("ssao_radius", backend::ssao_radius(Some(dc)), backend::ssao_radius(Some(dr)), backend::SSAO_RADIUS_METRES),
        // The route overlay's lift — band-relative, so its metre value is the band's
        // times ROUTE_LIFT_BANDS rather than a constant of its own.
        (
            "route_lift",
            extrude::route_lift(Some(dc)),
            extrude::route_lift(Some(dr)),
            extrude::GROUND_BAND_METRES * extrude::ROUTE_LIFT_BANDS,
        ),
        // The water lane's last two raw design units: the Gerstner amplitude and the
        // base wavelength, both world lengths `water.wgsl` displaces vertices by.
        (
            "wave_amplitude",
            extrude::wave_amplitude(Some(dc)),
            extrude::wave_amplitude(Some(dr)),
            extrude::WAVE_AMPLITUDE_METRES,
        ),
        (
            "wave_wavelength",
            extrude::wave_wavelength(Some(dc)),
            extrude::wave_wavelength(Some(dr)),
            extrude::WAVE_WAVELENGTH_METRES,
        ),
        // …and the grid that has to carry them, derived from the wavelength.
        (
            "water_grid_cell",
            extrude::water_grid_cell(Some(dc)),
            extrude::water_grid_cell(Some(dr)),
            extrude::WAVE_WAVELENGTH_METRES * extrude::GERSTNER_OCTAVE_WAVELENGTHS[2] / 4.0,
        ),
    ];

    println!("\n  {:<20}{:>13}{:>13}{:>12}{:>12}{:>10}", "constant", "city du", "region du", "city m", "region m", "want m");
    let mut failed = Vec::new();
    for (name, du_city, du_region, want_m) in &rows {
        let (m_city, m_region) = (metres(*du_city, dc), metres(*du_region, dr));
        println!("  {name:<20}{du_city:>13.3e}{du_region:>13.3e}{m_city:>12.3}{m_region:>12.3}{want_m:>10.3}");
        // The design-unit values MUST differ — if they agree, the constant is absolute.
        if (du_city - du_region).abs() / du_city.max(1e-12) < 0.05 {
            failed.push(format!("{name}: same design units at both scales ⇒ it is an ABSOLUTE, not a length"));
        }
        // …and the metres MUST agree, with each other and with the stated constant.
        for (label, got) in [("city", m_city), ("region", m_region)] {
            if (got - want_m).abs() / want_m > 0.05 {
                failed.push(format!("{name} at {label} scale: {got:.3} m, but the constant says {want_m:.3} m"));
            }
        }
    }
    assert!(failed.is_empty(), "metric constants that are not metric:\n  - {}", failed.join("\n  - "));

    // The scenes are the ones the constants were read from — not a detached table.
    let (_, _, water_city) = extrude::build_with_water(&city, 0.22);
    let (_, _, water_region) = extrude::build_with_water(&region, 0.22);
    for (label, w, dpm) in [("city", &water_city, dc), ("region", &water_region, dr)] {
        assert!(w.triangle_count() > 0, "{label}: the lake tessellated");
        let y = w.positions[0][1];
        assert!(
            w.positions.iter().all(|p| (p[1] - y).abs() < 1e-9),
            "{label}: one water plane, not several"
        );
        let m = metres(y, dpm);
        assert!(
            (m - extrude::WATER_RISE_METRES).abs() < 0.05,
            "{label}: the BUILT water grid sits {m:.3} m up, want {:.3} m",
            extrude::WATER_RISE_METRES
        );
    }
}

/// **"Your route" is painted ON the street, at both scales — asserted on the EMITTED
/// route vertices, not on a constant.**
///
/// `ROUTE_LIFT` was the one constant DERIVED from `GROUND_LIFT` (`× 1.6`) and the one
/// the `GROUND_LIFT` fix did not take with it: the streets moved to
/// `ground_band(du_per_m)` and the route overlay stayed absolute. In `korp`'s 3 km town
/// window that is 3.6 m of ribbon over a road top at 0.49 m — a ratio of 7.4, so the
/// route floats ~3.1 m over the street it claims to be painted on, in a scene where a
/// storey is 3 m. The doc on it promises "sub-pixel … reads as painted on the ground".
///
/// The bound is the scene's OWN road top ([`extrude::ground_top`] of its band), so this
/// is a relation between two things in the same scene rather than a number to re-tune.
#[test]
fn the_route_ribbon_is_painted_on_the_street_at_both_scales() {
    let ((city, dc), (region, dr)) = two_scales();
    /// The most a route ribbon may float above the road tops, in metres. It has to
    /// clear them (no z-fight) and it has to read as paint, not as a bridge.
    const MAX_FLOAT_M: f32 = 0.5;

    for (label, ways, dpm) in [("city", &city, dc), ("region", &region, dr)] {
        // A two-point route through the middle of the town, in the Mercator-unit space
        // `project_route` expects (the same space `Way::points` lives in).
        let pts: Vec<(f32, f32)> = vec![ways[0].points[0], ways[ways.len() - 2].points[0]];
        let route = extrude::project_route(ways, &pts);
        assert!(route.len() == 2, "{label}: the route projected");
        let y = route[0][1];
        let road_top = extrude::ground_top(extrude::ground_band(Some(dpm)));
        let float_m = metres(y - road_top, dpm);
        println!(
            "  {label:<8} route y {y:.3e} du ({:.3} m)   road top {road_top:.3e} du ({:.3} m)   \
             floats {float_m:>7.3} m",
            metres(y, dpm),
            metres(road_top, dpm)
        );
        assert!(y > road_top, "{label}: the route must draw OVER the streets (no z-fight)");
        assert!(
            float_m <= MAX_FLOAT_M,
            "{label}: \"your route\" floats {float_m:.2} m over the street it is painted on \
             (a storey is 3 m) — the ribbon lift is absolute while the streets are metric"
        );
    }
}

/// **RED.** The same assertion, run against the legacy absolutes the fix replaced.
/// It must FAIL — that is the proof the guard above can see the disease it guards.
/// Every number here is what the shipped code actually did on 2026-08-04.
#[test]
fn the_legacy_absolutes_fail_the_two_scale_guard() {
    let ((_, dc), (_, dr)) = two_scales();
    let absolutes: [(&str, f32); 10] = [
        ("WATER_HEIGHT", extrude::WATER_HEIGHT),
        // The water lane's legacy raw design units.
        ("WAVE_AMPLITUDE_DU", extrude::WAVE_AMPLITUDE_DU),
        ("WAVE_WAVELENGTH_DU", extrude::WAVE_WAVELENGTH_DU),
        ("WATER_GRID_CELL_DU", extrude::WATER_GRID_CELL_DU),
        ("haze layer (0.25 du)", backend::HAZE_SCALE_HEIGHT_DU),
        ("SSAO radius (0.16 du)", backend::SSAO_RADIUS_DU),
        // The route-overlay family: the constants derived from GROUND_LIFT /
        // ROAD_MIN_HALF_W that the metric fixes had not taken with them.
        ("ROUTE_LIFT", extrude::ROUTE_LIFT),
        ("ROUTE_HALF_W", extrude::ROUTE_HALF_W),
        ("ROUTE_MARKER_R", extrude::ROUTE_MARKER_R),
        ("CHEVRON_CADENCE_DU", extrude::CHEVRON_CADENCE_DU),
    ];
    println!("\n  {:<24}{:>12}{:>12}{:>10}", "absolute", "city m", "region m", "ratio");
    for (name, du) in absolutes {
        let (m_city, m_region) = (metres(du, dc), metres(du, dr));
        let ratio = m_region / m_city;
        println!("  {name:<24}{m_city:>12.1}{m_region:>12.1}{ratio:>10.1}×");
        assert!(
            ratio > 10.0,
            "{name} would have to disagree with itself across the two scales for the guard \
             above to be meaningful — it does not, so the guard is blind ({ratio:.1}×)"
        );
    }
}

/// The two names for the scene's scale are **one number**, not two — `lod`'s
/// `metres_per_design_unit` and `extrude`'s `design_units_per_metre` are exact
/// reciprocals by definition (both are `DESIGN_FILL / world_span_metres`), and this
/// asserts the definition rather than trusting the doc comment that states it.
#[test]
fn scene_scale_is_one_number() {
    for (label, ways) in [("city", town(CITY_DEG, 8)), ("region", town(REGION_DEG, 8))].iter() {
        let (label, ways) = (*label, ways);
        let du_per_m = extrude::design_units_per_metre(ways).expect("has a span");
        let m_per_du = facett_map3d::metres_per_design_unit(ways);
        let rel = ((1.0 / du_per_m) - m_per_du).abs() / m_per_du;
        println!("  {label:<8} 1/du_per_m {:12.4}   metres_per_du {m_per_du:12.4}   rel {rel:.2e}", 1.0 / du_per_m);
        assert!(rel < 1e-5, "{label}: the two scale names disagree by {rel:.2e} — that is two scales, not one");
    }
}

/// **The `None` arm — the ONLY branch where the two scale names can actually diverge.**
///
/// [`scene_scale_is_one_number`] sweeps `city` and `region`, i.e. the two CALIBRATED
/// scenes, where both names are `DESIGN_FILL / world_span_metres` by construction and
/// cannot disagree. The branch that can is the span-less one: `design_units_per_metre`
/// returns `None` and every consumer picks its OWN fallback, while
/// `lod::metres_per_design_unit` silently returns [`lod::DEFAULT_METRES_PER_DESIGN_UNIT`]
/// as a naked `f32` no caller can tell apart from a calibrated value (the
/// identity-value trap: 625 is a perfectly believable number).
///
/// This asserts the fallback through the **applied output** — the design-space `y` the
/// relief heightfield actually emits for a known metric relief — not through a constant
/// round-trip. Recovering `metres per design unit` from the emitted mesh must land on
/// `lod`'s default; a second, private fallback shows up as a ratio.
///
/// RED before the fix (`extrude.rs` relief field carried its own `unwrap_or(2.0e-4)`):
/// the mesh says 5000 m/du where the LOD lever says 625 — **8× apart, on precisely the
/// span-less data both are written for**.
#[test]
fn the_spanless_fallback_is_the_same_number_on_both_sides() {
    /// A pure north-south ramp over the relief builder's own procedural patch
    /// (lat 59.00 → 59.05 when the data has no bbox): 0 m at the south edge,
    /// `RELIEF_M` at the north. Deterministic, and its peak deviation (±5 m) is far
    /// under `MAX_TERRAIN_RELIEF / du_per_m` at either candidate scale, so the
    /// auto-fit ceiling cannot mask the number under test.
    struct Ramp;
    const RELIEF_M: f32 = 10.0;
    impl facett_map3d::terrain::Elevation for Ramp {
        fn elevation_at(&self, _lon_deg: f64, lat_deg: f64) -> f32 {
            (((lat_deg - 59.0) / 0.05) as f32).clamp(0.0, 1.0) * RELIEF_M
        }
    }

    // Span-less data: the fixture / degenerate case. Both names must agree HERE.
    let ways: Vec<Way> = Vec::new();
    assert!(
        extrude::design_units_per_metre(&ways).is_none(),
        "this fixture must actually be the None branch, or the guard tests nothing"
    );
    let lod_default = facett_map3d::metres_per_design_unit(&ways);

    let mut mesh = extrude::Mesh3::default();
    extrude::relief_terrain_into(&mut mesh, &ways, &Ramp, 24, 1.0);
    let (lo, hi) = mesh
        .positions
        .iter()
        .fold((f32::MAX, f32::MIN), |(lo, hi), p| (lo.min(p[1]), hi.max(p[1])));
    let span_du = hi - lo;
    assert!(span_du > 0.0, "the ramp must produce relief at all ({span_du:e} du)");

    // What the emitted geometry says one design unit is worth, in metres.
    let mesh_m_per_du = RELIEF_M / span_du;
    let ratio = mesh_m_per_du / lod_default;
    println!(
        "  spanless: relief {RELIEF_M} m → {span_du:.5} du ⇒ {mesh_m_per_du:.1} m/du   \
         lod default {lod_default:.1} m/du   ratio {ratio:.2}×"
    );
    assert!(
        (ratio - 1.0).abs() < 0.02,
        "the relief field and the LOD lever disagree about the span-less scale by {ratio:.2}× \
         (mesh {mesh_m_per_du:.1} m/du vs lod {lod_default:.1} m/du) — that is two writers of \
         one number, on the only data where they can differ"
    );
}

/// **Past the honest bound the FLOOR governs, not the metre — and that is on purpose.**
///
/// `ground_band` stops shrinking at [`extrude::MIN_GROUND_BAND`] (`du_per_m < 2.5e-5`,
/// a span past ~64 km) so the flat-cover band never sinks under the `f32` depth
/// epsilon, and `water_height` is floored above it for the same reason. So at 100 km
/// the band reads ~0.6 m and the water ~0.87 m rather than the stated 0.4 / 0.6.
///
/// A guard that let the main table tolerate this would be tolerating exactly the
/// symptom it exists to catch. Asserted separately, as the documented behaviour:
/// **the value is the floor, and the ORDERING still holds.**
#[test]
fn past_the_honest_bound_the_floor_takes_over() {
    let ways = town(CONTINENT_DEG, 10);
    let dpm = extrude::design_units_per_metre(&ways).expect("has a span");
    assert!(dpm < 2.5e-5, "this scene is past MIN_GROUND_BAND's bound ({dpm:e})");
    let band = extrude::ground_band(Some(dpm));
    let water = extrude::water_height(Some(dpm));
    println!(
        "  100 km: du_per_m {dpm:e}  band {:.3} m (metric would be {:.3})  water {:.3} m",
        band / dpm,
        extrude::GROUND_BAND_METRES,
        water / dpm
    );
    assert!(
        (band - extrude::MIN_GROUND_BAND).abs() < 1e-9,
        "the band is pinned at MIN_GROUND_BAND, not at the metric value: {band:e}"
    );
    assert!(band / dpm > extrude::GROUND_BAND_METRES, "the floor is LOOSER than the metre here, never tighter");
    // The ordering that actually matters survives the floor.
    assert!(water > extrude::ground_top(band), "water still clears the cover past the bound");
    assert!(water < extrude::MIN_DEFAULT_BUILDING_HEIGHT_M * dpm, "water still stays under the shortest house");
}

/// Data with **no world span at all** keeps every legacy absolute, so a scene the
/// extruder cannot scale renders byte-for-byte as before the metric fix.
///
/// **The `None` branch is narrower than it reads.** `Map3D::synthetic` — the rabbit
/// fixture — carries real lon/lat and therefore DOES have a span (`du_per_m ≈ 1.9e-4`,
/// ~5.2 km), so it takes the METRIC path, not this one. Recorded here because the doc
/// comments on `ground_band` / `building_rise_eps` call the fixture the archetypal
/// `None` case and it is not one; only genuinely span-less input reaches these lines.
#[test]
fn span_less_scenes_keep_the_legacy_absolutes() {
    assert_eq!(extrude::water_height(None), extrude::WATER_HEIGHT);
    assert_eq!(extrude::wave_amplitude(None), extrude::WAVE_AMPLITUDE_DU);
    assert_eq!(extrude::wave_wavelength(None), extrude::WAVE_WAVELENGTH_DU);
    assert_eq!(extrude::water_grid_cell(None), extrude::WATER_GRID_CELL_DU);
    assert_eq!(backend::haze_scale_height(None), backend::HAZE_SCALE_HEIGHT_DU);
    assert_eq!(backend::ssao_radius(None), backend::SSAO_RADIUS_DU);
    assert_eq!(extrude::ground_band(None), extrude::GROUND_LIFT);
    assert_eq!(extrude::design_units_per_metre(&[]), None, "empty data has no scale");

    let rabbit = facett_map3d::Map3D::synthetic("fixture");
    let dpm = rabbit
        .design_units_per_metre()
        .expect("MEASURED 2026-08-04: the rabbit fixture DOES carry a world span");
    println!("  rabbit fixture: du_per_m {dpm:e}  ⇒ metres_per_du {:.1}", 1.0 / dpm);
    assert!(dpm > 0.0, "…so the fixture is on the metric path, not the legacy one");
}

/// **The water plane sits between the ground cover and the shortest house — at BOTH
/// scales.** The physical property `WATER_HEIGHT` was supposed to have and had at
/// exactly one span. Stated as an ordering, so it cannot pass by sitting on a number.
#[test]
fn water_sits_above_the_ground_cover_and_below_the_houses_at_both_scales() {
    for (label, dpm) in [("city", extrude::design_units_per_metre(&town(CITY_DEG, 8)).unwrap()),
                         ("region", extrude::design_units_per_metre(&town(REGION_DEG, 8)).unwrap())] {
        let top = extrude::ground_top(extrude::ground_band(Some(dpm)));
        let water = extrude::water_height(Some(dpm));
        let house = extrude::MIN_DEFAULT_BUILDING_HEIGHT_M * dpm;
        println!(
            "  {label:<8} ground_top {:8.3} m   water {:8.3} m   min house {:8.3} m",
            metres(top, dpm),
            metres(water, dpm),
            metres(house, dpm)
        );
        assert!(water > top, "{label}: water ({water:e}) must clear the ground cover ({top:e})");
        assert!(water < house, "{label}: water ({water:e}) must stay under the shortest house ({house:e})");
    }
}

/// **The sea does not cut through the ground it sits on — at BOTH scales, and by
/// CONSTRUCTION rather than by tuning.**
///
/// `water.wgsl` sums three Gerstner octaves, so the deepest a trough can reach below
/// the water plane is [`extrude::gerstner_octave_sum`] times the base amplitude. The
/// plane itself is [`extrude::water_height`] above the terrain quad at `y = 0`. The
/// property is therefore one inequality, and [`extrude::wave_amplitude`] enforces it
/// with a cap instead of leaving it to whoever last edited a literal.
///
/// The `y` under test is read off the **built water mesh**, not off the constant —
/// `build_with_water` is the thing the renderer uploads.
///
/// RED (below): the shipped absolute `0.0020 du` is 12.5× the whole clearance in the
/// 3 km town window, so the troughs pass clean through the terrain.
#[test]
fn the_summed_wave_trough_never_reaches_the_terrain_plane() {
    let ((city, dc), (region, dr)) = two_scales();
    let sum = extrude::gerstner_octave_sum();
    assert!(sum > 1.0, "the octaves sum to more than the base amplitude ({sum})");

    for (label, ways, dpm) in [("city", &city, dc), ("region", &region, dr)] {
        let (_, _, water) = extrude::build_with_water(ways, 0.22);
        assert!(water.triangle_count() > 0, "{label}: the lake tessellated");
        let plane = water.positions[0][1];
        let amp = extrude::wave_amplitude(Some(dpm));
        let trough = plane - sum * amp;
        println!(
            "  {label:<8} plane {:7.3} m   amp {:7.3} m   summed trough {:7.3} m   \
             clearance {:7.3} m",
            metres(plane, dpm),
            metres(amp, dpm),
            metres(sum * amp, dpm),
            metres(trough, dpm)
        );
        assert!(
            trough > 0.0,
            "{label}: the summed wave trough reaches {:.3} m — BELOW the terrain plane the \
             water is drawn on, so the sea cuts through the ground",
            metres(trough, dpm)
        );
        // …and the amplitude is still a real chop, not a cap that flattened it away.
        assert!(
            metres(amp, dpm) > 0.5 * extrude::WAVE_AMPLITUDE_METRES,
            "{label}: the cap swallowed the metric amplitude ({:.3} m of a wanted {:.3} m) — \
             the constant is decoration if the clamp always wins",
            metres(amp, dpm),
            extrude::WAVE_AMPLITUDE_METRES
        );
    }
}

/// **RED for [`the_summed_wave_trough_never_reaches_the_terrain_plane`].** The same
/// inequality, run against the amplitude the shipped code actually used
/// (`0.0020 du`, absolute). It must FAIL at both scales — otherwise the guard above is
/// passing on a property that was never violated and proves nothing.
#[test]
fn the_legacy_wave_amplitude_cuts_through_the_ground() {
    let ((_, dc), (_, dr)) = two_scales();
    let sum = extrude::gerstner_octave_sum();
    for (label, dpm) in [("city", dc), ("region", dr)] {
        let plane = extrude::water_height(Some(dpm));
        let trough = plane - sum * extrude::WAVE_AMPLITUDE_DU;
        println!(
            "  {label:<8} legacy amp {:9.1} m   plane {:7.3} m   trough {:11.1} m   \
             overshoot {:6.1}×",
            metres(extrude::WAVE_AMPLITUDE_DU, dpm),
            metres(plane, dpm),
            metres(trough, dpm),
            sum * extrude::WAVE_AMPLITUDE_DU / plane
        );
        assert!(
            trough < 0.0,
            "{label}: the legacy absolute would have had to already satisfy the guard for it \
             to mean anything — it does not violate the inequality, so the guard is blind"
        );
    }
}

/// **The Rust copy of the shader's octave multipliers cannot drift from the shader.**
///
/// [`extrude::wave_amplitude`]'s cap is only sound if
/// [`extrude::gerstner_octave_sum`] is the sum the GPU actually applies, and those
/// three multipliers live in `water.wgsl`. Two copies of one number is exactly the
/// shape LAW 5 forbids, and a doc comment saying "keep these in sync" is not a guard —
/// so this reads the multipliers back out of the shader source.
///
/// Carries its own RED: the same matcher is run over a MUTATED copy of the shader and
/// asserted to fail, so a matcher that silently matches nothing cannot pass.
#[test]
fn the_shader_octaves_match_the_rust_copy() {
    const SRC: &str = include_str!("../src/water.wgsl");

    /// What the shader must contain if it applies exactly these multipliers.
    fn octaves_missing_from(src: &str) -> Vec<String> {
        let mut missing = Vec::new();
        let calls = src.matches("gerstner(p, t,").count();
        if calls != extrude::GERSTNER_OCTAVE_AMPLITUDES.len() {
            missing.push(format!("{calls} gerstner octaves in the shader, {} in Rust", extrude::GERSTNER_OCTAVE_AMPLITUDES.len()));
        }
        for (i, (a, w)) in extrude::GERSTNER_OCTAVE_AMPLITUDES
            .iter()
            .zip(extrude::GERSTNER_OCTAVE_WAVELENGTHS.iter())
            .enumerate()
            .skip(1)
        {
            for needle in [format!("amp * {a}"), format!("base_wl * {w}")] {
                if !src.contains(&needle) {
                    missing.push(format!("octave {i}: shader has no `{needle}`"));
                }
            }
        }
        // Octave 0 is applied bare — `amp,` and `base_wl,` with no multiplier.
        for needle in ["base_wl,", " amp,"] {
            if !src.contains(needle) {
                missing.push(format!("octave 0: shader has no bare `{needle}`"));
            }
        }
        missing
    }

    let missing = octaves_missing_from(SRC);
    println!(
        "  rust  amps {:?}  wavelens {:?}  sum {:.2}",
        extrude::GERSTNER_OCTAVE_AMPLITUDES,
        extrude::GERSTNER_OCTAVE_WAVELENGTHS,
        extrude::gerstner_octave_sum()
    );
    assert!(missing.is_empty(), "water.wgsl and the Rust copy have drifted:\n  - {}", missing.join("\n  - "));

    // RED: mutate the shader's second octave and the matcher must see it.
    let mutated = SRC.replacen(
        &format!("amp * {}", extrude::GERSTNER_OCTAVE_AMPLITUDES[1]),
        "amp * 0.91",
        1,
    );
    assert_ne!(mutated, SRC, "the mutation must actually change the source, or the RED is vacuous");
    let caught = octaves_missing_from(&mutated);
    println!("  RED: mutated octave 1 ⇒ {} finding(s): {caught:?}", caught.len());
    assert!(!caught.is_empty(), "the matcher passed a shader whose octave 1 was changed — it matches nothing");
}

/// **The water grid actually resolves the wave it carries — measured on the EMITTED
/// vertices, not on the constants.**
///
/// The cell size and the wavelength were two independent literals (`0.018 du` and
/// `0.14 du`), self-consistent at one scale and at no other. They are one number now
/// ([`extrude::water_grid_cell`] is derived from [`extrude::wave_wavelength`]), and
/// this measures the spacing the tessellator really emitted against the shortest
/// octave the shader really displaces by.
///
/// **Honest bound:** the per-ring resolution is clamped to a vertex budget (96), so a
/// lake wider than `96 ·` cell is under-resolved on purpose. The assertion is
/// therefore stated as "either the budget is saturated, or the wave is resolved" —
/// and it PRINTS which arm it took, so a scene that silently slid into the budget arm
/// is visible rather than green.
#[test]
fn the_water_grid_resolves_the_shortest_octave_or_says_it_is_budget_bound() {
    let ((city, dc), (region, dr)) = two_scales();
    for (label, ways, dpm) in [("city", &city, dc), ("region", &region, dr)] {
        let (_, _, water) = extrude::build_with_water(ways, 0.22);
        assert!(water.triangle_count() > 0, "{label}: the lake tessellated");
        // The emitted grid is axis-aligned; the smallest non-zero x gap between two
        // vertices IS the cell the tessellator chose.
        let mut xs: Vec<f32> = water.positions.iter().map(|p| p[0]).collect();
        xs.sort_by(|a, b| a.partial_cmp(b).unwrap());
        let gap = xs
            .windows(2)
            .map(|w| w[1] - w[0])
            .filter(|d| *d > 1e-9)
            .fold(f32::MAX, f32::min);
        assert!(gap < f32::MAX, "{label}: the grid has more than one column");
        let shortest = extrude::wave_wavelength(Some(dpm)) * extrude::GERSTNER_OCTAVE_WAVELENGTHS[2];
        let per_wave = shortest / gap;
        let budget_bound = gap > extrude::water_grid_cell(Some(dpm)) * 1.5;
        println!(
            "  {label:<8} cell {:8.3} m   shortest octave {:8.3} m   {per_wave:5.2} cells/wave   \
             {}   verts {}",
            metres(gap, dpm),
            metres(shortest, dpm),
            if budget_bound { "BUDGET-BOUND" } else { "resolved" },
            water.vertex_count()
        );
        assert!(
            per_wave >= 3.0 || budget_bound,
            "{label}: {per_wave:.2} cells across the shortest wave and the vertex budget is NOT \
             saturated — the grid and the wavelength have drifted apart again"
        );
        // A budget-bound ring must cost the BUDGET density, not the ceiling: the whole
        // point of dropping to it is that spending 26× the vertices only buys aliasing.
        if budget_bound {
            let ceiling = (extrude::WATER_MAX_RES + 1) * (extrude::WATER_MAX_RES + 1);
            assert!(
                water.vertex_count() < ceiling / 4,
                "{label}: budget-bound and still {} verts of a {ceiling}-vertex ceiling — the \
                 fallback did not fire and the ring pays full price to alias its ripple",
                water.vertex_count()
            );
        }
    }
}

/// **The wave decides the grid, and the budget decides when to stop — both arms
/// exercised, on the SAME function the extruder calls.**
///
/// [`extrude::water_grid_res`] has two arms and only one of them fires on the scenes
/// the metric table sweeps, so a table-only guard would leave the resolving arm
/// untested. Here the ring extent is swept across the crossover and both arms are
/// asserted, including that the crossover is where the derivation says it is.
///
/// The RED it replaces: the shipped `extent / 0.018` gave the SAME resolution for a
/// pond and for a lake at every scene span, because `0.018` is a fraction of the scene
/// and not a length — so no ring size could ever have moved it.
#[test]
fn the_grid_tracks_the_wave_until_the_vertex_budget_binds() {
    let ((city, dc), _) = two_scales();
    let _ = city;
    let cell = extrude::water_grid_cell(Some(dc));
    let crossover = cell * extrude::WATER_MAX_RES as f32;
    println!(
        "  cell {:.3} m   crossover ring {:.1} m   budget res {}   max res {}",
        metres(cell, dc),
        metres(crossover, dc),
        extrude::WATER_BUDGET_RES,
        extrude::WATER_MAX_RES
    );
    // A pond well inside the budget: the resolution tracks the extent, linearly.
    let (small, twice) = (crossover * 0.25, crossover * 0.5);
    let (rs, rt) = (extrude::water_grid_res(small, Some(dc)), extrude::water_grid_res(twice, Some(dc)));
    println!("  ring {:7.1} m ⇒ res {rs:3}   ring {:7.1} m ⇒ res {rt:3}", metres(small, dc), metres(twice, dc));
    assert!(rs >= extrude::WATER_MIN_RES && rt <= extrude::WATER_MAX_RES, "both stay inside the budget");
    assert!(
        (rt as f32 / rs as f32 - 2.0).abs() < 0.15,
        "a ring twice as wide wants twice the cells ({rs} → {rt}) — the grid is not tracking the wave"
    );
    // Past the crossover the budget takes over, and it costs the BUDGET density.
    let big = crossover * 4.0;
    let rb = extrude::water_grid_res(big, Some(dc));
    println!("  ring {:7.1} m ⇒ res {rb:3}  (budget arm)", metres(big, dc));
    assert_eq!(rb, extrude::WATER_BUDGET_RES, "past the budget the ring drops to the budget density");
    assert!(
        rb < rt,
        "the budget arm must be CHEAPER than the ring half its size ({rb} vs {rt}) — otherwise \
         the fallback is spending vertices to alias"
    );
    // Span-less scenes are byte-for-byte what they were: the legacy fraction.
    let legacy = extrude::water_grid_res(0.32, None);
    println!("  span-less ring 0.32 du ⇒ res {legacy} (legacy extent/{})", extrude::WATER_GRID_CELL_DU);
    assert_eq!(legacy, (0.32_f32 / extrude::WATER_GRID_CELL_DU).ceil() as usize);
}

/// **The street-label LOD ladder is the SAME ruler as the altitude ladder — measured
/// on the labels the gate actually admits, at two scales.**
///
/// `facett-map3d` carried two LOD ladders: `lod`'s, in honest metres
/// (`WATER_ON_ALTITUDE_M = 300.0`), and `Map3D::label_lod_distance`'s, in raw design
/// units (`0.95 / 0.45 / 0.18 / 0.10`). In `korp`'s 3 km town window a design unit is
/// ~1 800 m, so "residential/service: only near street level" gated at ~324 m; in a
/// region load the same literal is kilometres. The ladder measured the VIEWPORT, not
/// the ground.
///
/// The oracle is `Map3D::street_labels_gated_in`, not the constant — a count of the
/// anchors the gate lets through, which is what a viewer sees. `street_labels` (how
/// many EXIST) cannot move and could never have shown this.
#[test]
fn the_label_ladder_gates_on_metres_at_both_scales() {
    use facett_map::style::Lod;

    /// The town, plus a named street of every LOD tier laid across it — the fixture
    /// `town()` has no roads, so a ladder guard built on it alone would be vacuous.
    fn town_with_streets(span_deg: f64) -> Vec<Way> {
        let pal = MapPalette::cartographic(true);
        let (lon0, lat0) = (18.0_f64, 59.33_f64);
        let mut ways = town(span_deg, 14);
        for (i, class) in ["motorway", "secondary", "residential", "footway"].iter().enumerate() {
            let y = lat0 + span_deg * (0.2 + 0.15 * i as f64);
            let line = [(lon0, y), (lon0 + span_deg, y)];
            if let Some(w) = Way::from_lonlat_with(
                800_001 + i as i64,
                &line,
                &[
                    ("highway".to_string(), (*class).to_string()),
                    ("name".to_string(), format!("{class} street")),
                ],
                &pal,
            ) {
                ways.push(w);
            }
        }
        ways
    }

    let (city, region) = (town_with_streets(CITY_DEG), town_with_streets(REGION_DEG));
    let dc = extrude::design_units_per_metre(&city).expect("the city has a world span");
    let dr = extrude::design_units_per_metre(&region).expect("the region has a world span");
    assert!(dc / dr > 10.0, "the two scales stay decades apart with the streets in ({:.1}×)", dc / dr);
    // The probe is chosen so the guard can DISCRIMINATE, which is a stronger property
    // than "the numbers agree". At 400 m the metric ladder admits exactly the
    // `Country` rung (600 m) and no other, in BOTH scenes. The legacy design-unit
    // ladder admits two in the city (its rungs land at 1702 / 806 / 322 m there) and
    // all three in the region (28 362 / 13 435 / 5 374 m) — so 2 ≠ 3, and the
    // equality below is a real assertion instead of an arithmetic identity.
    // `the_legacy_label_ladder_gates_on_the_viewport` runs exactly that arm and
    // asserts it fails. A first draft of this test probed at 90 m, where the legacy
    // ladder also admits every rung at both scales: the equality would have held for
    // the broken ladder too.
    const PROBE_M: f32 = 400.0;

    let mut counts = Vec::new();
    for (label, ways, dpm) in [("city", &city, dc), ("region", &region, dr)] {
        let map = facett_map3d::Map3D::from_ways(label, ways, 0.22);
        let mpu = map.metres_per_design_unit();
        assert!(
            ((1.0 / dpm) - mpu).abs() / mpu < 1e-3,
            "{label}: the Map3D read a different scale ({mpu}) than the table ({})",
            1.0 / dpm
        );
        // The dolly that puts the eye PROBE_M metres out, in this scene's units.
        let dolly_du = PROBE_M / mpu;
        let admitted = map.street_labels_gated_in(dolly_du);
        println!(
            "  {label:<8} m/du {mpu:9.1}   dolly {dolly_du:.3e} du = {PROBE_M} m   \
             anchors {:4}   gated in {admitted:4}",
            map.street_label_count()
        );
        // The tier boundaries themselves, read through the scene's own scale.
        for lod in [Lod::Country, Lod::Region, Lod::City, Lod::Detail] {
            let edge_m = facett_map3d::Map3D::label_lod_distance_m(lod);
            let just_in = map.label_shows_at(lod, (edge_m * 0.99) / mpu);
            let just_out = map.label_shows_at(lod, (edge_m * 1.01) / mpu);
            assert!(
                just_in && !just_out,
                "{label}: {lod:?} does not switch at {edge_m} m through this scene's scale \
                 (in={just_in} out={just_out}) — the ladder is not reading the scale"
            );
        }
        counts.push((label, admitted));
    }

    // The SAME metric dolly must admit the SAME tiers in both scenes. The two towns
    // are the same topology at two spans, so the counts are comparable directly.
    let (a, b) = (counts[0].1, counts[1].1);
    println!("  city gated-in {a}   region gated-in {b}");
    assert_eq!(
        a, b,
        "at {PROBE_M} m the two scenes admit different label sets ({a} vs {b}) — the ladder \
         is measuring the viewport, not the ground"
    );
    assert!(a > 0, "the probe must actually admit labels, or the equality above is vacuous (0 == 0)");
}

/// **RED for [`the_label_ladder_gates_on_metres_at_both_scales`].** The ladder as it
/// shipped — design-unit literals compared against `cam.distance` — run through the
/// SAME "same metres ⇒ same label set" question at the SAME probe. It must give two
/// different answers in the two scenes, or the guard above is passing on an identity.
#[test]
fn the_legacy_label_ladder_gates_on_the_viewport() {
    let ((city, dc), (region, dr)) = two_scales();
    let (_, _) = (&city, &region);
    /// The ladder exactly as it was, in design units, biggest rung first.
    const LEGACY_DU: [f32; 3] = [0.95, 0.45, 0.18];
    const PROBE_M: f32 = 400.0;

    let mut admitted = Vec::new();
    for (label, dpm) in [("city", dc), ("region", dr)] {
        let dolly_du = PROBE_M * dpm;
        let n = LEGACY_DU.iter().filter(|&&rung| dolly_du <= rung).count();
        println!(
            "  {label:<8} rungs {:9.0} / {:9.0} / {:9.0} m   at {PROBE_M} m ⇒ {n} of 3 admitted",
            LEGACY_DU[0] / dpm,
            LEGACY_DU[1] / dpm,
            LEGACY_DU[2] / dpm
        );
        admitted.push(n);
    }
    assert_ne!(
        admitted[0], admitted[1],
        "the legacy ladder would have to already admit the same label set at the same METRIC \
         distance in both scenes for the guard above to mean anything — it admits {} and {}",
        admitted[0], admitted[1]
    );
    let (m_city, m_region) = (LEGACY_DU[2] / dc, LEGACY_DU[2] / dr);
    assert!(
        m_region > 1_000.0,
        "…and the region's \"only near street level\" rung is {m_region:.0} m against the \
         city's {m_city:.0} m: the ladder measured the viewport, not the ground"
    );
}

/// **The flat-Earth ruler is a PHYSICAL number, and nothing pinned it.**
///
/// `M_PER_DEG_LAT` was declared nine times across this crate's sources and tests
/// (`granska-20`) — the production copy plus eight private ones in test files that
/// build their fixtures from it. Those copies made every fixture agree with the code
/// under test only by coincidence of nobody editing either side, and no test asserted
/// the VALUE at all: a typo in the production constant would have moved the extruder
/// and left every fixture measuring the old earth, silently, because the fixtures
/// carried their own.
///
/// The eight copies are gone (the tests import the extruder's constant now), so the
/// remaining risk is the opposite one: one writer, wrong. This pins it — against the
/// WGS-84 meridian, not against itself.
#[test]
fn the_flat_earth_ruler_is_the_wgs84_meridian() {
    // WGS-84 polar circumference / 360. The mean degree of latitude is 111 132.95 m at
    // the equator and 111 693.9 m at the pole; the extruder uses the round 111 320,
    // which is the ~45° value and the conventional flat-Earth constant. Bound the
    // check by the real spread rather than by the constant itself.
    let meridian_deg = 40_007_863.0 / 360.0; // m per degree, WGS-84 polar circumference
    let err = (extrude::M_PER_DEG_LAT - meridian_deg).abs() / meridian_deg;
    println!("  M_PER_DEG_LAT {:.1} m   WGS-84 mean {meridian_deg:.1} m   rel {err:.4}", extrude::M_PER_DEG_LAT);
    assert!(err < 0.005, "the latitude degree is {:.1} m — that is not the WGS-84 meridian ({meridian_deg:.1} m, rel {err:.4})", extrude::M_PER_DEG_LAT);

    // And the longitude writer must be the SAME ruler shrunk by cos(lat) — checked at
    // three latitudes, including Sweden's, because a constant-longitude bug is invisible
    // at the equator (cos 0 = 1: the identity value).
    for (lat, want) in [(0.0, 1.0), (59.3293, 59.3293_f64.to_radians().cos()), (69.0, 69.0_f64.to_radians().cos())] {
        let ratio = extrude::m_per_deg_lon(lat) / extrude::M_PER_DEG_LAT;
        println!("  lat {lat:>8.4}  m_per_deg_lon/M_PER_DEG_LAT {ratio:.6}  want cos(lat) {want:.6}");
        assert!((ratio - want).abs() < 1e-6, "at {lat}° the longitude degree is {ratio:.6} of the latitude degree, not cos(lat) = {want:.6}");
    }
}