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/matrix_grid.rs

//! **MAP3D ~1000-CASE MATRIX GRID** (the owner's explicit scale) — a programmatic
//! parameter sweep over the whole start→pixel space, FEEDING real input and
//! ASSERTING real output per case (the inject-and-assert LAW, not no-crash).
//!
//! Each case builds a real `Map3D` from one of several geometries, places the
//! camera at a swept pose (orbit yaw × tilt × elevation × dolly distance, incl. the
//! failing street-level dolly-in and below-ground requests), renders the start→pixel
//! chain headlessly via `shade_faces`, and asserts the EMIT ORACLES:
//!
//!   * **finite** — every projected vertex is finite (no near-singularity inf/NaN);
//!   * **no_smear** — `max_projected_extent ≤ viewport · K` (the screen-extent bound);
//!   * **front_of_eye** — every painted face's depth is in front of the near plane;
//!   * **ink_outside_rect == 0** — the rect scissor confines every painted vertex;
//!   * **non_blank** — a non-degenerate pose renders visible faces.
//!
//! Each case emits ONE functional_status row (`facett-map3d` / `matrix_grid`) so the
//! whole pose/geometry space is provably covered in the warehouse. Built + run with
//! `--features testmatrix`; the grid is ~1000 cases (see `GRID_SIZE` assert).
//!
//! Run: `cargo test -p facett-map3d --features testmatrix --test matrix_grid`

use egui::{Color32, Pos2};
use facett_core::Theme;
use facett_map::Way;
use facett_map3d::{clip_poly_to_rect, scissor_report, Map3D, OrbitCamera};

fn building(id: i64, ring: &[(f64, f64)]) -> Way {
    let tags = vec![("building".to_string(), "yes".to_string())];
    Way::from_lonlat(id, ring, &tags, &Theme::default()).expect("a building way")
}

/// Geometry fixtures the grid sweeps (each a real extruded mesh path).
#[derive(Clone, Copy)]
enum Geom {
    /// The extruded znippy-rabbit synthetic skyline.
    Rabbit,
    /// A small Sigtuna-ish town of `building=yes` rings (the `from_ways` path).
    Town,
    /// A denser town that triggers `densest_cluster_subset` + framing (`from_geometry`).
    City,
    /// A single degenerate near-plane-straddling sliver building.
    Sliver,
}

impl Geom {
    fn name(self) -> &'static str {
        match self {
            Geom::Rabbit => "rabbit",
            Geom::Town => "town",
            Geom::City => "city",
            Geom::Sliver => "sliver",
        }
    }
    fn build(self) -> Map3D {
        match self {
            Geom::Rabbit => Map3D::synthetic("grid-rabbit"),
            Geom::Town => {
                let mut ways = Vec::new();
                let mut id = 1;
                for r in 0..5 {
                    for c in 0..5 {
                        let bx = 17.70 + c as f64 * 0.0015;
                        let by = 59.61 + r as f64 * 0.0015;
                        ways.push(building(
                            id,
                            &[(bx, by), (bx + 0.0008, by), (bx + 0.0008, by + 0.0008), (bx, by + 0.0008), (bx, by)],
                        ));
                        id += 1;
                    }
                }
                Map3D::from_ways("grid-town", &ways, 0.22)
            }
            Geom::City => {
                let mut ways = Vec::new();
                let mut id = 1;
                for r in 0..10 {
                    for c in 0..10 {
                        let bx = 17.70 + c as f64 * 0.0009;
                        let by = 59.61 + r as f64 * 0.0009;
                        ways.push(building(
                            id,
                            &[(bx, by), (bx + 0.0005, by), (bx + 0.0005, by + 0.0005), (bx, by + 0.0005), (bx, by)],
                        ));
                        id += 1;
                    }
                }
                Map3D::from_geometry("grid-city", &ways)
            }
            Geom::Sliver => {
                // A long thin near-degenerate footprint — the near-plane straddle bait.
                let w = building(1, &[(17.70, 59.61), (17.74, 59.6101), (17.74, 59.6102), (17.70, 59.6102), (17.70, 59.61)]);
                Map3D::from_ways("grid-sliver", &[w], 0.22)
            }
        }
    }
}

/// One swept case's measured oracles.
struct CaseResult {
    finite: bool,
    no_smear: bool,
    front_of_eye: bool,
    ink_outside_rect: usize,
    faces: usize,
    max_extent: f32,
    cap: f32,
}

/// Render one case (geometry × pose × canvas) and measure the oracles.
fn run_case(geom: Geom, az: f32, elev: f32, dist: f32, canvas: (f32, f32)) -> CaseResult {
    let mut m = geom.build();
    m.spin = false;
    // Aim at the geometry's framed target (from_geometry frames the cluster), then
    // override the swept pose so the camera math is exercised end to end.
    let tgt = m.render_camera().target;
    m.cam.target = tgt;
    m.cam.goal_target = tgt;
    m.cam.azimuth = az;
    m.cam.goal_azimuth = az;
    m.cam.elevation = elev; // requested; clamp_elev lifts below-ground requests
    m.cam.goal_elevation = elev;
    m.cam.distance = dist;
    m.cam.goal_distance = dist;
    m.cam.settle();

    let rect = egui::Rect::from_min_max(Pos2::new(0.0, 0.0), Pos2::new(canvas.0, canvas.1));
    let center = rect.center();
    let scale = rect.height() * 0.5;
    let bg = Color32::from_rgb(20, 24, 40);
    let faces = m.shade_faces(center, scale, bg);

    let near = OrbitCamera::NEAR_PLANE;
    let mut finite = true;
    let mut front_of_eye = true;
    let mut max_extent = 0.0f32;
    for (depth, pts, _c) in &faces {
        for p in pts {
            if !p.x.is_finite() || !p.y.is_finite() {
                finite = false;
            }
        }
        if *depth < near - 1e-3 {
            front_of_eye = false;
        }
        let ex = pts[0].x.max(pts[1].x).max(pts[2].x) - pts[0].x.min(pts[1].x).min(pts[2].x);
        let ey = pts[0].y.max(pts[1].y).max(pts[2].y) - pts[0].y.min(pts[1].y).min(pts[2].y);
        max_extent = max_extent.max(ex.max(ey));
    }
    // VIEWPORT-TIGHT cap. `SCREEN_BOUND_K` is 1.0, so the screen bound clips to
    // ±half_h and a fully-clipped face spans AT MOST the viewport (2·half_h); +1px
    // float-boundary epsilon. This used to be `scale * 8.0 + 1.0` — 1000+ swept
    // cases against a cap 4× looser than the contract, i.e. the exact 2026-06-21
    // failure mode (strong Axis A, blind Axis B: green-on-broken).
    let cap = scale * 2.0 + 1.0;
    let no_smear = max_extent <= cap;

    // ink_outside_rect after the rect scissor (the painter's final confine).
    let mut ink = 0usize;
    for (_d, pts, _c) in &faces {
        for p in &clip_poly_to_rect(pts, rect) {
            let over = (rect.left() - p.x).max(p.x - rect.right()).max(rect.top() - p.y).max(p.y - rect.bottom());
            if over > 1e-2 {
                ink += 1;
            }
        }
    }
    let _ = scissor_report(&faces, rect);

    CaseResult { finite, no_smear, front_of_eye, ink_outside_rect: ink, faces: faces.len(), max_extent, cap }
}

#[test]
fn map3d_thousand_case_pose_geometry_grid() {
    // Sweep grid: geometries × azimuth × elevation × distance × canvas.
    let geoms = [Geom::Rabbit, Geom::Town, Geom::City, Geom::Sliver];
    // Azimuth: 8 turntable headings around the full circle.
    let azis: Vec<f32> = (0..8).map(|k| k as f32 * std::f32::consts::TAU / 8.0).collect();
    // Elevation: incl. requested below-ground (-0.3, -0.1) → clamp_elev must lift,
    // street-level (0.0, 0.05), oblique (0.3, 0.6), near-top (1.4).
    let elevs = [-0.3f32, -0.1, 0.0, 0.05, 0.3, 0.6, 1.4];
    // Distance: dolly from street-level all the way out (incl. the failing 0.41).
    let dists = [0.41f32, 0.6, 1.0, 2.0];
    // Canvas: a few aspect ratios + sizes.
    let canvases = [(600.0f32, 280.0f32), (800.0, 600.0), (320.0, 480.0)];

    let total = geoms.len() * azis.len() * elevs.len() * dists.len() * canvases.len();
    assert!(total >= 1000, "the grid is ~1000 cases (got {total})");

    let mut failures: Vec<String> = Vec::new();
    let mut cases = 0usize;
    let mut nonblank_cases = 0usize;
    let mut max_extent_seen = 0.0f32;
    for &geom in &geoms {
        for &az in &azis {
            for &elev in &elevs {
                for &dist in &dists {
                    for &canvas in &canvases {
                        cases += 1;
                        let r = run_case(geom, az, elev, dist, canvas);
                        max_extent_seen = max_extent_seen.max(r.max_extent);
                        if r.faces > 0 {
                            nonblank_cases += 1;
                        }
                        // ── per-case ORACLES (inject-assert) ──
                        let ok = r.finite && r.no_smear && r.front_of_eye && r.ink_outside_rect == 0;
                        if !ok {
                            failures.push(format!(
                                "geom={} az={az:.2} elev={elev:.2} dist={dist} canvas={canvas:?}: finite={} no_smear={}(ext={:.0}/cap={:.0}) front={} ink={} faces={}",
                                geom.name(), r.finite, r.no_smear, r.max_extent, r.cap, r.front_of_eye, r.ink_outside_rect, r.faces
                            ));
                        }
                        // ── EMIT one row per case (warehouse coverage) ──
                        #[cfg(feature = "testmatrix")]
                        facett_core::testmatrix::emit(
                            "facett-map3d",
                            "matrix_grid",
                            ok,
                            &format!(
                                "geom={} az={az:.2} elev={elev:.2} dist={dist} canvas={}x{} faces={} max_extent_px={:.0} cap_px={:.0} ink_outside_rect={} finite={} front_of_eye={}",
                                geom.name(), canvas.0, canvas.1, r.faces, r.max_extent, r.cap, r.ink_outside_rect, r.finite, r.front_of_eye
                            ),
                        );
                    }
                }
            }
        }
    }

    eprintln!(
        "[matrix_grid] {cases} cases, {nonblank_cases} non-blank, worst max_extent={max_extent_seen:.0}px, failures={}",
        failures.len()
    );

    // ── grid-level oracles ──
    assert_eq!(cases, total, "every grid tuple ran");
    assert!(
        failures.is_empty(),
        "{} of {cases} grid cases violated an oracle:\n{}",
        failures.len(),
        failures.iter().take(20).cloned().collect::<Vec<_>>().join("\n")
    );
    // The grid must actually render geometry in the overwhelming majority of poses
    // (a pose looking straight away still draws the far city). A few extreme poses
    // can legitimately frame nothing, so require ≥ 80% non-blank.
    assert!(
        nonblank_cases as f32 >= cases as f32 * 0.80,
        "the grid renders geometry in most poses ({nonblank_cases}/{cases})"
    );

    #[cfg(feature = "testmatrix")]
    facett_core::testmatrix::emit(
        "facett-map3d",
        "matrix_grid_summary",
        failures.is_empty(),
        &format!("cases={cases} nonblank={nonblank_cases} failures={} worst_max_extent_px={max_extent_seen:.0}", failures.len()),
    );
}