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

nordisk/facett

facett-geomap/tests/osm_zorder.rs

//! **Z-band paint-order proof** for the 2D OSM viewer (`OsmView`).
//!
//! The documented order (see `osm2d::PaintBand`) is, bottom→top:
//!   Background → Fill (land/water) → Line (roads) → Point → Overlay → Label → Pin.
//! This renders a scene where a big **water fill** covers the pane, a bright **road**
//! crosses it, and a **pin** sits on top, then asserts through the real pixels that
//! the road is visible OVER the water (fills paint under roads) and the pin marker
//! is visible OVER everything (pins on top). It is the always-headless-runnable
//! guard for the CPU reference lane; the GPU-lane fix (emitting the line callback
//! AFTER the fills, so the two lanes agree) is structural — the GPU lane cannot
//! render on the headless harness.
//!
//! Run: `cargo test -p facett-geomap --test osm_zorder`

use egui_kittest::Harness;
use facett_core::Facet;
use facett_geomap::Way;
use facett_geomap::osm2d::{OsmView, Pin};

/// A closed square ring in (lon, lat).
fn square(x0: f64, y0: f64, x1: f64, y1: f64) -> Vec<(f64, f64)> {
    vec![(x0, y0), (x1, y0), (x1, y1), (x0, y1), (x0, y0)]
}

/// Count pixels whose colour is close to `(r,g,b)` (within a per-channel band).
fn count_near(img: &image::RgbaImage, r: u8, g: u8, b: u8, tol: i32) -> usize {
    img.pixels()
        .filter(|p| {
            (p.0[0] as i32 - r as i32).abs() <= tol
                && (p.0[1] as i32 - g as i32).abs() <= tol
                && (p.0[2] as i32 - b as i32).abs() <= tol
        })
        .count()
}

#[test]
fn fills_paint_under_roads_under_pins() {
    // A pure-BLUE water polygon over the whole data bbox, a pure-GREEN road across
    // its middle, and a pin at the centre. Distinct primaries make the bands
    // unambiguous in the rendered pixels.
    let water = Way::filled(
        1,
        "water",
        square(0.0, 0.0, 10.0, 10.0),
        egui::Color32::from_rgb(0, 0, 255),   // fill: blue
        egui::Color32::from_rgb(0, 0, 200),   // outline: blue-ish
        1.0,
    );
    let road = Way::line(
        2,
        "road",
        vec![(0.5, 5.0), (9.5, 5.0)],
        egui::Color32::from_rgb(0, 255, 0), // road: green
        6.0,
    );
    let pin = Pin::new(5.0, 5.0, "");

    let mut view = OsmView::from_geometry("z-order", Vec::new(), vec![water, road]).with_pins(vec![pin]);
    let mut harness = Harness::builder().with_size(egui::vec2(400.0, 400.0)).build_ui(move |ui| {
        view.ui(ui);
    });
    harness.run_steps(3);
    let img = harness.render().expect("wgpu render produced an image");

    let blue = count_near(&img, 0, 0, 255, 40);
    let green = count_near(&img, 0, 255, 0, 60);
    let red = count_near(&img, 230, 90, 90, 60); // the pin marker head

    eprintln!("[z-order] blue(water)={blue} green(road)={green} red(pin)={red}");

    // Water fills a large area (the background band).
    assert!(blue > 5_000, "the water fill covers a healthy area of the pane (got {blue})");
    // The GREEN road is visible ON TOP of the water: if fills painted over roads,
    // the green line would be covered by blue and vanish. Red-when-broken for the
    // fills-under-roads invariant.
    assert!(green > 300, "the road must be visible over the water fill (got {green} green px)");
    // The RED pin marker sits on top of everything.
    assert!(red > 40, "the pin marker must be visible on top (got {red} red px)");

    // testmatrix cell — OSM 2D z-band paint order holds (fills < roads < pins);
    // surfaces in the dwarves testmatrix (`--features testmatrix`), no-op otherwise.
    facett_core::testmatrix::emit(
        "facett-geomap/osm2d",
        "fills_paint_under_roads_under_pins",
        blue > 5_000 && green > 300 && red > 40,
        &format!("z-order pixels: water(blue)={blue}, road(green over water)={green}, pin(red on top)={red}"),
    );
}