Skip to content

Commit 7900dcc

Browse files
committed
fix(models_3d): address Copilot PR review
- Clarify voxelize.rs comment: vertex colors modulate (not override) material. - Add MAX_LONG_EXTENT_M / MAX_SHORT_EXTENT_M / MAX_HEIGHT_M caps so mis-tagged whole-sports-complex polygons don't blow up voxelization. Mirrors Wikidata's extent caps. Test covers an oversize 1500×800 m leisure=stadium being rejected.
1 parent 9a0a536 commit 7900dcc

2 files changed

Lines changed: 28 additions & 3 deletions

File tree

src/models_3d/custom/stadium.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ const MODEL_URL: &str = "https://arnismc.com/assets/3dmodels/stadium.glb";
1212
const CACHE_FILE: &str = "stadium.glb";
1313

1414
const MIN_SHORT_EXTENT_M: f32 = 10.0;
15+
/// Caps to avoid voxelizing absurd polygons (entire sports complexes mis-tagged as one stadium).
16+
const MAX_LONG_EXTENT_M: f32 = 500.0;
17+
const MAX_SHORT_EXTENT_M: f32 = 400.0;
18+
const MAX_HEIGHT_M: f32 = 200.0;
1519
/// `leisure=stadium` qualifies on its own above this footprint area (m²).
1620
const LARGE_STADIUM_AREA_M2: f64 = 20_000.0;
1721
/// Smaller `leisure=stadium` needs an inner `building=stadium` to qualify.
@@ -230,7 +234,7 @@ fn build_placement(element: &ProcessedElement, args_scale: f64) -> Option<Placem
230234
let (long_blocks, short_blocks, theta) = principal_axis(&points)?;
231235
let long_m = (long_blocks / args_scale) as f32;
232236
let short_m = (short_blocks / args_scale) as f32;
233-
if short_m < MIN_SHORT_EXTENT_M {
237+
if short_m < MIN_SHORT_EXTENT_M || long_m > MAX_LONG_EXTENT_M || short_m > MAX_SHORT_EXTENT_M {
234238
return None;
235239
}
236240

@@ -239,7 +243,7 @@ fn build_placement(element: &ProcessedElement, args_scale: f64) -> Option<Placem
239243
.tags()
240244
.get("height")
241245
.and_then(|s| parse_meters(s))
242-
.map(|m| m as f32);
246+
.map(|m| (m as f32).min(MAX_HEIGHT_M));
243247

244248
Some(Placement {
245249
osm_id: element.id(),
@@ -835,6 +839,27 @@ mod tests {
835839
assert!(suppressed.contains(&("way", 13)));
836840
}
837841

842+
#[test]
843+
fn prescan_rejects_oversize_stadium() {
844+
// 1500×800 m — likely a whole sports complex mis-tagged. Above MAX_LONG_EXTENT_M.
845+
let mut tags = StdMap::new();
846+
tags.insert("leisure".to_string(), "stadium".to_string());
847+
let huge = ProcessedElement::Way(mk_way(
848+
20,
849+
vec![
850+
mk_node(200, 0, 0),
851+
mk_node(201, 1500, 0),
852+
mk_node(202, 1500, 800),
853+
mk_node(203, 0, 800),
854+
],
855+
tags,
856+
));
857+
let empty = HashSet::new();
858+
let (placements, suppressed) = prescan_offline(&[huge], &empty);
859+
assert_eq!(placements.len(), 0);
860+
assert!(!suppressed.contains(&("way", 20)));
861+
}
862+
838863
#[test]
839864
fn prescan_rejects_standalone_small_building_stadium() {
840865
let mut tags = StdMap::new();

src/models_3d/voxelize.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ pub fn voxelize_glb(
251251
} else {
252252
(0..positions.len() as u32).collect()
253253
};
254-
// Vertex colors (COLOR_0) override material color when present.
254+
// Vertex colors (COLOR_0) modulate the material color when present.
255255
let vertex_colors: Option<Vec<[f32; 4]>> =
256256
reader.read_colors(0).map(|c| c.into_rgba_f32().collect());
257257

0 commit comments

Comments
 (0)