From 95f39bf5f13c6ccba071454cd25dfc2dfe8a93dc Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Mon, 26 Dec 2022 14:39:01 +0000 Subject: [PATCH] Introduce internal consistency checks --- osm2streets/src/intersection.rs | 14 +++++++++ osm2streets/src/lib.rs | 1 + osm2streets/src/road.rs | 14 +++++++++ osm2streets/src/validate.rs | 52 +++++++++++++++++++++++++++++++++ tests/src/lib.rs | 2 ++ 5 files changed, 83 insertions(+) create mode 100644 osm2streets/src/validate.rs diff --git a/osm2streets/src/intersection.rs b/osm2streets/src/intersection.rs index 7c398c21..d81a8394 100644 --- a/osm2streets/src/intersection.rs +++ b/osm2streets/src/intersection.rs @@ -88,6 +88,20 @@ impl Intersection { pub fn is_map_edge(&self) -> bool { self.kind == IntersectionKind::MapEdge } + + pub fn describe(&self) -> String { + let osm_ids = self + .osm_ids + .iter() + .map(|x| x.to_string()) + .collect::>() + .join(", "); + if osm_ids.is_empty() { + self.id.to_string() + } else { + format!("{} ({})", self.id, osm_ids) + } + } } impl StreetNetwork { diff --git a/osm2streets/src/lib.rs b/osm2streets/src/lib.rs index f56884d5..05ffeae3 100644 --- a/osm2streets/src/lib.rs +++ b/osm2streets/src/lib.rs @@ -37,6 +37,7 @@ mod render; mod road; mod transform; mod types; +mod validate; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct StreetNetwork { diff --git a/osm2streets/src/road.rs b/osm2streets/src/road.rs index 6e45297f..ce52f6c7 100644 --- a/osm2streets/src/road.rs +++ b/osm2streets/src/road.rs @@ -497,6 +497,20 @@ impl Road { pub fn from_osm_way(&self, way: osm::WayID) -> bool { self.osm_ids.iter().any(|id| *id == way) } + + pub fn describe(&self) -> String { + let osm_ids = self + .osm_ids + .iter() + .map(|x| x.to_string()) + .collect::>() + .join(", "); + if osm_ids.is_empty() { + self.id.to_string() + } else { + format!("{} ({})", self.id, osm_ids) + } + } } impl StreetNetwork { diff --git a/osm2streets/src/validate.rs b/osm2streets/src/validate.rs new file mode 100644 index 00000000..c211a2f2 --- /dev/null +++ b/osm2streets/src/validate.rs @@ -0,0 +1,52 @@ +use crate::StreetNetwork; + +impl StreetNetwork { + /// Validates various things are true about the StreetNetwork, panicking if not. + pub fn check_invariants(&self) { + for r in self.roads.values() { + for i in r.endpoints() { + let i = &self.intersections[&i]; + assert!( + i.roads.contains(&r.id), + "{} doesn't list {}", + i.describe(), + r.describe() + ); + } + assert!( + !r.lane_specs_ltr.is_empty(), + "{} has no lanes", + r.describe() + ); + } + + for i in self.intersections.values() { + assert!(!i.roads.is_empty(), "{} has no roads", i.describe()); + + for r in &i.roads { + let r = &self.roads[r]; + assert!( + r.src_i == i.id || r.dst_i == i.id, + "{} contains {}, which doesn't point to it", + i.describe(), + r.describe() + ); + } + + for (r1, r2) in &i.movements { + assert!( + i.roads.contains(r1), + "{} has a movement for the wrong road {}", + i.describe(), + r1 + ); + assert!( + i.roads.contains(r2), + "{} has a movement for the wrong road {}", + i.describe(), + r2 + ); + } + } + } +} diff --git a/tests/src/lib.rs b/tests/src/lib.rs index eba707cd..18d92a9d 100644 --- a/tests/src/lib.rs +++ b/tests/src/lib.rs @@ -30,8 +30,10 @@ mod tests { MapConfig::default(), &mut timer, )?; + street_network.check_invariants(); street_network .apply_transformations(Transformation::standard_for_clipped_areas(), &mut timer); + street_network.check_invariants(); street_network.save_to_geojson(format!("{path}/geometry.json"))?; let road_network: RoadNetwork = street_network.into();