facett-map3d/tests/region_span_buildings_rise.rs
//! **On a korp region viewport the houses must still count as houses.**
//!
//! `BUILDING_RISE_EPS` was an absolute design-unit constant (`4.0e-3`) deciding whether
//! a mesh vertex is a wall or a roof, while a building's rise is `height_m · du_per_m` —
//! metric, and therefore a function of how much ground the scene spans. Two unrelated
//! quantities, so which is bigger depends entirely on the viewport.
//!
//! MEASURED on the shipped korp path, a real focused Xvfb window (`:97`, 1900×1150,
//! `korp-ui --server` against the live korp-server, adapter NVIDIA GeForce RTX 4090
//! [discrete/Vulkan], `software=false`), Stockholm zoom 12.1, 2026-08-03:
//! `building_ways = 39 587`, `extruded_triangles = 2 123 768`, and
//! **`building_vertices = 0`, `buildings_visible = 0`** — two million triangles of
//! extruded city and not one vertex that counted as a building. `camera.distance` came
//! back `3.200000047683716`, bit-identical to the whole-mesh default, because
//! `frame_densest_cluster` took its `risen.len() < 3` early return: not THREE vertices
//! in Stockholm cleared even the looser `1e-3` the fitter used.
//!
//! Two definitions of "risen" in one file was the second half of it, and it hid the
//! first: the fitter asked `y > 1e-3`, every observable asked `y > BUILDING_RISE_EPS`,
//! so the camera and the oracles could disagree about whether the scene had buildings
//! in it — and on this data they did.
//!
//! Everything below asserts on APPLIED OUTPUT — the extruded mesh's own y coordinates,
//! the vertices that project inside the frustum at the framed pose — never on a knob
//! round-trip, and never on `camera.distance` alone (a number that sat on its default
//! and looked perfectly reasonable is precisely what hid this bug).
mod common;
use common::{region_with_town, ring, tags, M_PER_DEG_LAT, STOCKHOLM};
use facett_core::Theme;
use facett_map::Way;
use facett_map3d::{extrude, Map3D, BUILDING_RISE_EPS};
/// The measured korp z12 Stockholm viewport span.
const KORP_Z12_SPAN_M: f64 = 55_688.0;
/// **The defect, on the extruded mesh.** At korp's own measured region span the mesh
/// carries real risen building geometry, and the OLD absolute threshold could not see
/// any of it.
///
/// The second assert is the RED line: it pins that this fixture really is a scene where
/// the old constant reports zero, so the first assert is not passing on a scene that
/// would have worked anyway.
#[test]
fn a_region_scene_has_risen_buildings_the_absolute_threshold_could_not_see() {
let ways = region_with_town(KORP_Z12_SPAN_M, 24);
let span = extrude::world_span_metres(&ways).expect("a real world span");
let du_per_m = extrude::DESIGN_FILL / span;
assert!(
(span - KORP_Z12_SPAN_M as f32).abs() / span < 0.05,
"the fixture spans korp's measured viewport: {span:.0} m vs {KORP_Z12_SPAN_M:.0} m",
);
let map = Map3D::from_ways("region", &ways, 0.22);
let eps = map.building_rise_eps();
// APPLIED OUTPUT: the mesh's own vertices, counted by the scene's threshold.
let risen = map.building_vertices();
assert!(
risen > 0,
"span {span:.0} m, du_per_m {du_per_m:.3e}: {} building ways extruded and NOT ONE mesh \
vertex counts as risen (threshold {eps:.4e})",
ways.iter().filter(|w| w.kind == "building").count(),
);
// …and it counted them by the SCENE's threshold, derived from the scene's own span.
let want = extrude::building_rise_eps(Some(du_per_m));
assert!(
(eps - want).abs() <= want * 1e-6,
"the scene's rise threshold is derived from its own span: {eps:.4e} vs {want:.4e}",
);
// ── the RED line, spelled out ─────────────────────────────────────────────
// With the old absolute constant this exact mesh reports zero. If this assert ever
// fails the fixture has stopped being a region scene and the test above has stopped
// proving anything.
let by_absolute = map.mesh().positions.iter().filter(|p| p[1] > BUILDING_RISE_EPS).count();
assert_eq!(
by_absolute, 0,
"NON-VACUITY: the old absolute BUILDING_RISE_EPS ({BUILDING_RISE_EPS:.1e}) must still see \
nothing here — that is the defect this fixture reproduces",
);
// And by how much it missed: the tallest roof in the scene, against both thresholds.
let ymax = map.mesh().positions.iter().fold(0.0f32, |a, p| a.max(p[1]));
println!(
"span {span:.0} m du_per_m {du_per_m:.3e} ymax {ymax:.4e} \
metric eps {eps:.4e} ({:.1}× under the roof) absolute eps {BUILDING_RISE_EPS:.1e} \
({:.0}× OVER the roof) risen vertices {risen}",
ymax / eps,
BUILDING_RISE_EPS / ymax,
);
}
/// **The threshold still keeps the ground out.** The whole reason `BUILDING_RISE_EPS`
/// was set high was so a road-only scene reports zero buildings. A metric threshold has
/// to keep that guarantee at every span, and by construction rather than by luck: it is
/// floored above `ground_top`, the top of the scene's own ground band.
#[test]
fn no_road_or_cover_ever_counts_as_a_house_at_any_span() {
let theme = Theme::default();
for span_m in [300.0f64, 1_000.0, 3_000.0, 10_000.0, KORP_Z12_SPAN_M, 200_000.0] {
// The same region, with every building way removed.
let ground: Vec<Way> = region_with_town(span_m, 24).into_iter().filter(|w| w.kind != "building").collect();
assert!(!ground.is_empty(), "span {span_m}: the ground-only scene must still have features");
let map = Map3D::from_ways("ground only", &ground, 0.22);
assert_eq!(
map.building_vertices(),
0,
"span {span_m} m: a scene of roads, water and forest reported {} risen 'building' \
vertices at threshold {:.4e}",
map.building_vertices(),
map.building_rise_eps(),
);
// …and the margin, measured: the highest ground vertex in the mesh vs the threshold.
let gmax = map.mesh().positions.iter().fold(0.0f32, |a, p| a.max(p[1]));
assert!(
gmax > 0.0,
"span {span_m} m: the ground layers must still clear the terrain plane (else this \
passes vacuously — a band collapsed to zero is not a band)",
);
assert!(
gmax < map.building_rise_eps(),
"span {span_m} m: the ground reaches {gmax:.4e}, at or over the rise threshold {:.4e}",
map.building_rise_eps(),
);
// The shortest building the extruder can emit must clear it at the same span —
// both halves of "cover < road < roof", on one scale.
let full = region_with_town(span_m, 4);
let stats = extrude::building_height_stats(&full, 0.22);
let eps_full = extrude::building_rise_eps_for(&full);
assert!(
stats.min > eps_full,
"span {span_m} m: the SHORTEST roof ({:.4e}) does not clear the rise threshold \
({eps_full:.4e})",
stats.min,
);
// A theme-suppressing check that the fixture really produced buildings.
assert!(stats.buildings > 0, "span {span_m} m: the fixture extruded no buildings");
let _ = &theme;
}
}
/// **The camera fitter fires, and it fires on the SAME definition of "risen".**
///
/// `frame_densest_cluster` used its own hardcoded `1e-3`. On a region viewport that was
/// above every real rooftop, so the fitter early-returned and left the camera on its
/// whole-box default over a scene that was nothing but city — the "huge empty ground
/// plane with the town as a thumbnail" a korp user sees.
///
/// The oracle here is NOT `camera.distance` (the number that sat on `3.2` and looked
/// fine). It is `city_framing()`, which is `None` until the fitter actually ran, plus
/// `buildings_visible()` — vertices PROJECTED through the live render camera and found
/// inside the frustum, i.e. houses genuinely in shot.
#[test]
fn the_camera_fitter_finds_the_town_in_a_region_scene() {
let ways = region_with_town(KORP_Z12_SPAN_M, 24);
let mut map = Map3D::from_ways("region", &ways, 0.22);
assert!(map.city_framing().is_none(), "a fresh from_ways has not framed anything yet");
let default_dist = map.render_camera().distance;
map.frame_densest_cluster();
let framing = map
.city_framing()
.expect("the fitter must have found the town — None means it took the risen.len() < 3 return");
let dist = map.render_camera().distance;
// The fitter's OWN published centroid — the cluster it actually landed on.
let target = framing.center;
// It moved, and it moved ONTO the town — not merely to some other number. The town
// sits a third of the way toward the NE corner, so both design-plane coordinates
// must be positive and well off the origin the default pose looks at.
assert!(
target.x > 0.1 && target.z < -0.1,
"the camera targets the off-centre town (design +x, north = −z): target = \
({:.3}, {:.3}, {:.3})",
target.x,
target.y,
target.z,
);
assert!(
dist < default_dist,
"the fitter dollies IN on the town: {dist:.4} vs the default {default_dist:.4}",
);
assert!(framing.extent > 0.0, "the framing carries a real town extent: {:?}", framing.extent);
// APPLIED OUTPUT: at the framed pose, real building vertices project inside the
// viewport. This is the assert `camera.distance` could never make.
let visible = map.buildings_visible();
assert!(
visible > 0,
"the framed camera has no houses in shot ({} risen vertices exist in the mesh)",
map.building_vertices(),
);
println!(
"framed: target ({:.3}, {:.3}, {:.3}) distance {dist:.4} (default {default_dist:.4}) \
extent {:.4} buildings_visible {visible} / {} risen",
target.x,
target.y,
target.z,
framing.extent,
map.building_vertices(),
);
}
/// **One quantity, one writer.** Every risen-geometry question in `Map3D` must answer
/// from the SAME threshold — that is the whole LAW-5 half of this defect. Proven by
/// construction: a scene built so that the metric threshold and the old absolute one
/// disagree must have every observable on the metric side of the split.
#[test]
fn every_risen_geometry_observable_uses_the_one_threshold() {
let ways = region_with_town(KORP_Z12_SPAN_M, 24);
let mut map = Map3D::from_ways("region", &ways, 0.22);
map.frame_densest_cluster();
let eps = map.building_rise_eps();
assert!(eps < BUILDING_RISE_EPS, "the split this test needs: {eps:.4e} < {BUILDING_RISE_EPS:.1e}");
// `building_vertices` is the threshold applied to the raw mesh — recompute it here
// independently and require the API to agree.
let by_hand = map.mesh().positions.iter().filter(|p| p[1] > eps).count();
assert_eq!(map.building_vertices(), by_hand, "building_vertices counts by the scene threshold");
assert!(by_hand > 0, "…and there is something to count");
// `buildings_visible` is a strict subset (frustum-culled) and non-empty at the pose.
let visible = map.buildings_visible();
assert!(visible > 0 && visible <= by_hand, "visible {visible} of {by_hand} risen");
// `flanking_houses` reads the same set through the camera basis.
let (l, r) = map.flanking_houses();
assert!(l + r > 0, "the flanking-house oracle sees the same risen set (left {l}, right {r})");
// The roof accent recolours only caps ABOVE the same threshold — applied output is
// the mesh's own colour buffer, so compare against an un-accented twin.
let plain = Map3D::from_ways("region", &ways, 0.22);
let accented = Map3D::from_ways("region", &ways, 0.22).with_roof_accent(0.6);
let lum = |c: egui::Color32| c.r() as u32 + c.g() as u32 + c.b() as u32;
let changed = (0..plain.mesh().triangle_count())
.filter(|&t| lum(accented.mesh().colors[t]) != lum(plain.mesh().colors[t]))
.count();
assert!(
changed > 0,
"the roof accent brightened NO triangle — it bailed on `ymax <= eps` exactly like the \
observables did, which is what one shared threshold is for",
);
}
/// The threshold function itself: metric where there is a metre, the legacy absolute
/// value where there is not, and never down inside the ground band.
///
/// The `None` arm is what keeps every synthetic fixture (the rabbit, the unit-test
/// towns) reporting byte-for-byte the same counts as before.
#[test]
fn the_rise_threshold_is_metric_where_there_is_a_metre() {
assert_eq!(
extrude::building_rise_eps(None),
BUILDING_RISE_EPS,
"no world scale ⇒ the legacy absolute threshold, so synthetic scenes do not move",
);
assert_eq!(extrude::building_rise_eps(Some(0.0)), BUILDING_RISE_EPS, "a degenerate scale is no scale");
// The ground half holds at EVERY span, without exception — that is the guarantee
// the floor exists for, and it is unconditional.
for span_m in [300.0f32, 1_000.0, 3_000.0, 10_000.0, 55_688.0, 200_000.0, 1_000_000.0] {
let dpm = extrude::DESIGN_FILL / span_m;
let eps = extrude::building_rise_eps(Some(dpm));
let top = extrude::ground_top(extrude::ground_band(Some(dpm)));
assert!(
eps > top,
"span {span_m} m: the rise threshold {eps:.4e} must sit clear of the top of the \
ground band {top:.4e}, or a road ribbon is a house",
);
}
// The building half holds up to the documented bound and NOT past it. Both sides are
// asserted, so the bound is MEASURED here rather than claimed in a doc comment.
for span_m in [300.0f32, 1_000.0, 3_000.0, 10_000.0, 55_688.0, 200_000.0, 270_000.0] {
let dpm = extrude::DESIGN_FILL / span_m;
let eps = extrude::building_rise_eps(Some(dpm));
assert!(
eps < extrude::MIN_DEFAULT_BUILDING_HEIGHT_M * dpm,
"span {span_m} m: the threshold {eps:.4e} must stay under the SHORTEST building the \
extruder can emit ({:.4e}), or a real house is ground",
extrude::MIN_DEFAULT_BUILDING_HEIGHT_M * dpm,
);
}
for span_m in [275_000.0f32, 1_000_000.0] {
let dpm = extrude::DESIGN_FILL / span_m;
assert!(
extrude::building_rise_eps(Some(dpm)) > extrude::MIN_DEFAULT_BUILDING_HEIGHT_M * dpm,
"span {span_m} m is supposed to be OUTSIDE the honest bound — if this now passes the \
bound has moved and the doc on `building_rise_eps` is stale",
);
}
// Inside the bound (span ≤ ~110 km) the threshold IS the metric conversion — it
// means "one metre", not "a bit above the kerb".
for span_m in [300.0f32, 3_000.0, 55_688.0] {
let dpm = extrude::DESIGN_FILL / span_m;
let eps = extrude::building_rise_eps(Some(dpm));
let metric = extrude::BUILDING_RISE_METRES * dpm;
assert!(
(eps - metric).abs() <= metric * 1e-6,
"span {span_m} m: inside the honest bound the threshold is exactly {metric:.4e} \
(one metre), got {eps:.4e}",
);
}
}
/// A **flat** synthetic scene still reports zero — the guard the old constant was really
/// there for, on the path that keeps the absolute value.
#[test]
fn a_scene_with_no_world_scale_keeps_the_legacy_threshold() {
// A single degenerate way: no span the extruder can measure ⇒ `du_per_m == None`.
let theme = Theme::default();
let (clon, clat) = STOCKHOLM;
let tiny = 0.2 / M_PER_DEG_LAT; // a 40 cm ring — under the 1 m span floor
let ways: Vec<Way> = Way::from_lonlat(1, &ring(clon, clat, tiny, tiny), &tags(&[("building", "yes")]), &theme).into_iter().collect();
assert!(!ways.is_empty());
assert!(
extrude::world_span_metres(&ways).is_none(),
"the fixture must genuinely have no measurable world span",
);
let map = Map3D::from_ways("scale-free", &ways, 0.22);
assert_eq!(
map.building_rise_eps(),
BUILDING_RISE_EPS,
"a scene with no metres keeps the absolute threshold, so synthetic goldens do not move",
);
}
/// **The legibility oracle must not be blind.**
///
/// `buildings_visible` counts vertices inside the frustum. On the shipped korp path it
/// reported 340 581 houses in shot over a pane that drew a flat white pancake — a green
/// that could never go red for the thing a user complains about, because the houses were
/// 0.66 px tall. `skyline_screen_height_px` is the number that reads flat when the pane
/// looks flat, and this pins that it actually distinguishes the two cases rather than
/// returning something plausible in both.
#[test]
fn the_legibility_oracle_tells_a_pancake_from_a_town() {
// A REGION viewport: the town is a 1 km speck in a 55.7 km scene.
let region = region_with_town(KORP_Z12_SPAN_M, 24);
let mut wide = Map3D::from_ways("region", ®ion, 0.22);
wide.frame_densest_cluster();
let wide_px = wide.skyline_screen_height_px(1000.0);
// The SAME houses, extruded as their own town (a 1.5 km scene) — the scale the
// subset path produces.
let town = region_with_town(1_500.0, 24);
let mut close = Map3D::from_ways("town", &town, 0.22);
close.frame_densest_cluster();
let close_px = close.skyline_screen_height_px(1000.0);
// Both scenes are full of houses BY THE COUNT — that is the point.
assert!(wide.buildings_visible() > 1_000, "the region pane has houses in shot: {}", wide.buildings_visible());
assert!(close.buildings_visible() > 1_000, "the town pane has houses in shot: {}", close.buildings_visible());
// …and only one of them shows any.
assert!(
wide_px < 3.0,
"the region pane must READ FLAT — that is the defect this oracle exists to see, \
got {wide_px:.2} px",
);
assert!(
close_px >= 3.0,
"the town pane must read as buildings, got {close_px:.2} px",
);
assert!(
close_px > wide_px * 5.0,
"the oracle must SEPARATE the two, not merely rank them: town {close_px:.2} px vs \
region {wide_px:.2} px",
);
println!("legibility: region {wide_px:.2} px town {close_px:.2} px \
(visible {} vs {})", wide.buildings_visible(), close.buildings_visible());
// NON-VACUITY: an empty pane reads 0, so a scene with nothing risen cannot be
// mistaken for a legible one.
let ground: Vec<Way> = region_with_town(KORP_Z12_SPAN_M, 24).into_iter().filter(|w| w.kind != "building").collect();
let flat = Map3D::from_ways("ground only", &ground, 0.22);
assert_eq!(flat.skyline_screen_height_px(1000.0), 0.0, "no risen geometry ⇒ no skyline");
}
/// **The town window must bound the GEOMETRY, not merely choose it.**
///
/// `densest_cluster_subset` finds the town correctly and then used to return every way
/// that *touched* the window, whole — so a single trunk road running out of the window
/// put the retained bbox, and with it the scene's design unit, straight back at region
/// scale. MEASURED on the shipped korp path (2026-08-03, Stockholm z12, live server):
/// the subset cut 2 802 173 triangles to 116 465 — it HAD found the town — while
/// `metres_per_design_unit` stayed at **33 195**, a 33 km design unit on a 3 km window,
/// and the median house still stood 0.43 px.
#[test]
fn the_town_subset_bounds_the_scene_scale() {
let region = region_with_town(KORP_Z12_SPAN_M, 24);
let region_span = extrude::world_span_metres(®ion).expect("a region span");
assert!(region_span > 50_000.0, "the fixture is region-scale: {region_span:.0} m");
let town = extrude::densest_cluster_subset(®ion);
let town_span = extrude::world_span_metres(&town).expect("the town has a span");
// The window is ±1500 m, so a bounded subset spans at most ~3 km. Allow the
// diagonal; what must NOT happen is the span staying region-sized.
assert!(
town_span < 5_000.0,
"the subset must be TOWN-scale — got {town_span:.0} m out of a {region_span:.0} m \
region. A way reaching out of the window is still setting the scene scale.",
);
// …and it is still a town, not a crumb: the houses survived, and so did the part of
// the trunk road that crosses them (clipped, not deleted).
let houses = town.iter().filter(|w| w.kind == "building").count();
assert!(houses > 100, "the town kept its buildings, got {houses}");
let roads = town.iter().filter(|w| w.kind == "road").count();
assert!(roads > 0, "the street through the town survived the clip");
for w in town.iter() {
assert!(!w.lonlat.is_empty(), "no way is left with an empty geometry");
assert_eq!(w.points.len(), w.lonlat.len(), "clipping kept points and lonlat in step");
}
// APPLIED OUTPUT: what the scale is FOR — a legible house.
let mut map = Map3D::from_geometry("town", ®ion);
map.frame_densest_cluster();
let px = map.skyline_screen_height_px(1000.0);
assert!(
px >= 3.0,
"the whole point of the subset is a house you can see: {px:.2} px on a 1000 px pane",
);
println!(
"subset: {region_span:.0} m / {} ways -> {town_span:.0} m / {} ways \
({houses} houses, {roads} roads) skyline {px:.2} px m/du {:.0}",
region.len(),
town.len(),
map.metres_per_design_unit(),
);
}