diff --git a/data/MANIFEST.txt b/data/MANIFEST.txt index af5355e9d0..9cf0e1498a 100644 --- a/data/MANIFEST.txt +++ b/data/MANIFEST.txt @@ -364,16 +364,16 @@ data/input/seattle/sidewalks.bin,034dd47ab77902dbc81c0107f13d8965,https://www.dr data/input/seattle/sidewalks.kml,94d385ba03ef1b57a5ba10965913ec6c,https://www.dropbox.com/s/vn8amar9xi6vbvh/sidewalks.kml.zip?dl=0 data/input/seattle/trips_2014.csv,d4a8e733045b28c0385fb81359d6df03,https://www.dropbox.com/s/5ppravwmk6bf20d/trips_2014.csv.zip?dl=0 data/system/cities/seattle.bin,65ed19fe6b0a41d57ccb481a5c76652a,https://www.dropbox.com/s/kwei76ih7g12n1r/seattle.bin.zip?dl=0 -data/system/maps/ballard.bin,f1b176c7b9eb1bea45a83765178eda2e,https://www.dropbox.com/s/fyuls5w3jk0ksxz/ballard.bin.zip?dl=0 -data/system/maps/downtown.bin,c527a115321c330b170d6f6aa4b8057e,https://www.dropbox.com/s/icrmjsbpuw91sty/downtown.bin.zip?dl=0 -data/system/maps/downtown_atx.bin,ee780989b94cce25d1bb7b01fc125b86,https://www.dropbox.com/s/8mhkgojsd4jn4e5/downtown_atx.bin.zip?dl=0 -data/system/maps/huge_austin.bin,283232e25f9e618750b3d2ced2688ac5,https://www.dropbox.com/s/n5o81x245c7xz30/huge_austin.bin.zip?dl=0 -data/system/maps/huge_seattle.bin,2b4a60c31f52531f6e976f8030302230,https://www.dropbox.com/s/2lpu4xxfscy4nff/huge_seattle.bin.zip?dl=0 -data/system/maps/lakeslice.bin,9b6116bdb4df69cffdfb68f130d7cc01,https://www.dropbox.com/s/ni1kmtkkb8a6an7/lakeslice.bin.zip?dl=0 -data/system/maps/montlake.bin,df8b69d40cafdd228971e0bc28cd38b1,https://www.dropbox.com/s/vqb2ysjt91k6ouu/montlake.bin.zip?dl=0 -data/system/maps/south_seattle.bin,48698eaf565319848aed1b4412a4532f,https://www.dropbox.com/s/2u5givacl37kfgr/south_seattle.bin.zip?dl=0 -data/system/maps/udistrict.bin,b548af3f3518efb707c9a2d656b1aa19,https://www.dropbox.com/s/un4refjrbieipg5/udistrict.bin.zip?dl=0 -data/system/maps/west_seattle.bin,40ebddbf0e990e283c788813cc9b6c33,https://www.dropbox.com/s/6hb3pveo77r3gue/west_seattle.bin.zip?dl=0 +data/system/maps/ballard.bin,995adf8b00f7ae1bcf5b3bcb4287df16,https://www.dropbox.com/s/iottgk3e3wwn1sb/ballard.bin.zip?dl=0 +data/system/maps/downtown.bin,f02f91f4e7a3ff910ebe803e8401afcf,https://www.dropbox.com/s/0pu30om3lsh014w/downtown.bin.zip?dl=0 +data/system/maps/downtown_atx.bin,58749e8cc6c520ffbc6028f2be04656d,https://www.dropbox.com/s/p4d4jlrttmflbf7/downtown_atx.bin.zip?dl=0 +data/system/maps/huge_austin.bin,1074a390013957bbd8a3d359638aadc5,https://www.dropbox.com/s/pa20via4ifb61r6/huge_austin.bin.zip?dl=0 +data/system/maps/huge_seattle.bin,0858a4e1914aa72ce04abd8b61e4ed28,https://www.dropbox.com/s/f5lhssdvzwugey1/huge_seattle.bin.zip?dl=0 +data/system/maps/lakeslice.bin,690a17e8f0fae370fb6764c9f7836a12,https://www.dropbox.com/s/d9tpix5a12316i2/lakeslice.bin.zip?dl=0 +data/system/maps/montlake.bin,e770cedad9dbbd4a7d7dd737b79d753c,https://www.dropbox.com/s/1muzjwmrhf99ppq/montlake.bin.zip?dl=0 +data/system/maps/south_seattle.bin,00c2054bce2202b10c603b420a076f31,https://www.dropbox.com/s/4cz88pohpzp48eu/south_seattle.bin.zip?dl=0 +data/system/maps/udistrict.bin,ce77eaa72521046a11bc841eeadc4cdf,https://www.dropbox.com/s/b7tvz3tfchfrmdh/udistrict.bin.zip?dl=0 +data/system/maps/west_seattle.bin,2887904a9b2a662a67678fa6a1bcfe7e,https://www.dropbox.com/s/6pu9dqsawpk7swo/west_seattle.bin.zip?dl=0 data/system/prebaked_results/lakeslice/weekday.bin,05e4bf98e698919bbde9d62fa48a8599,https://www.dropbox.com/s/i1qun9jbo7xpy1k/weekday.bin.zip?dl=0 data/system/prebaked_results/montlake/car vs bike contention.bin,50b15194b8f91500ee6c17a5b0d498af,https://www.dropbox.com/s/jefg0ikjy9dsrdd/car%20vs%20bike%20contention.bin.zip?dl=0 data/system/prebaked_results/montlake/weekday.bin,fa12670c06a816719fa7331eabe8bc48,https://www.dropbox.com/s/jt6x1ej48n7cp3g/weekday.bin.zip?dl=0 diff --git a/map_model/src/lib.rs b/map_model/src/lib.rs index d0b54eec03..bdd0fb4149 100644 --- a/map_model/src/lib.rs +++ b/map_model/src/lib.rs @@ -17,6 +17,7 @@ mod stop_signs; mod traffic_signals; mod traversable; mod turn; +mod zone; pub use crate::area::{Area, AreaID, AreaType}; pub use crate::building::{Building, BuildingID, FrontPath, OffstreetParking}; @@ -37,6 +38,7 @@ pub use crate::stop_signs::{ControlStopSign, RoadWithStopSign}; pub use crate::traffic_signals::{ControlTrafficSignal, Phase, PhaseType}; pub use crate::traversable::{Position, Traversable}; pub use crate::turn::{Turn, TurnGroup, TurnGroupID, TurnID, TurnPriority, TurnType}; +pub use crate::zone::{Zone, ZoneID}; use abstutil::Cloneable; use geom::Distance; diff --git a/map_model/src/make/mod.rs b/map_model/src/make/mod.rs index 18f581c04d..8279030163 100644 --- a/map_model/src/make/mod.rs +++ b/map_model/src/make/mod.rs @@ -6,3 +6,4 @@ pub mod remove_disconnected; pub mod sidewalk_finder; pub mod traffic_signals; pub mod turns; +pub mod zones; diff --git a/map_model/src/make/zones.rs b/map_model/src/make/zones.rs new file mode 100644 index 0000000000..26ce8f1095 --- /dev/null +++ b/map_model/src/make/zones.rs @@ -0,0 +1,64 @@ +use crate::{Map, RoadID, Zone, ZoneID}; +use std::collections::BTreeSet; + +pub fn make_all_zones(map: &Map) -> Vec { + let mut queue = Vec::new(); + for r in map.all_roads() { + if r.is_private() { + queue.push(r.id); + } + } + + let mut zones = Vec::new(); + let mut seen = BTreeSet::new(); + while !queue.is_empty() { + let start = queue.pop().unwrap(); + if seen.contains(&start) { + continue; + } + let zone = floodfill(map, start, ZoneID(zones.len())); + seen.extend(zone.members.clone()); + zones.push(zone); + } + + zones +} + +fn floodfill(map: &Map, start: RoadID, id: ZoneID) -> Zone { + let mut queue = vec![start]; + let mut members = BTreeSet::new(); + let mut borders = BTreeSet::new(); + while !queue.is_empty() { + let current = queue.pop().unwrap(); + if members.contains(¤t) { + continue; + } + members.insert(current); + for r in map.get_next_roads(current) { + let r = map.get_r(r); + if r.is_private() { + queue.push(r.id); + } else { + let current_r = map.get_r(current); + if r.src_i == current_r.src_i { + borders.insert(r.src_i); + } else if r.src_i == current_r.dst_i { + borders.insert(r.src_i); + } else if r.dst_i == current_r.src_i { + borders.insert(r.dst_i); + } else if r.dst_i == current_r.dst_i { + borders.insert(r.dst_i); + } else { + unreachable!(); + } + } + } + } + assert!(!members.is_empty()); + assert!(!borders.is_empty()); + Zone { + id, + members, + borders, + } +} diff --git a/map_model/src/map.rs b/map_model/src/map.rs index 761fe6e9cd..e74d3fcb21 100644 --- a/map_model/src/map.rs +++ b/map_model/src/map.rs @@ -5,7 +5,7 @@ use crate::{ BusStopID, ControlStopSign, ControlTrafficSignal, EditCmd, EditEffects, EditIntersection, Intersection, IntersectionID, IntersectionType, Lane, LaneID, LaneType, MapEdits, ParkingLot, ParkingLotID, Path, PathConstraints, PathRequest, Position, Road, RoadID, Turn, TurnGroupID, - TurnID, TurnType, NORMAL_LANE_THICKNESS, SIDEWALK_THICKNESS, + TurnID, TurnType, Zone, ZoneID, NORMAL_LANE_THICKNESS, SIDEWALK_THICKNESS, }; use abstutil::{deserialize_btreemap, serialize_btreemap, Error, Timer, Warn}; use geom::{Angle, Bounds, Distance, GPSBounds, Line, PolyLine, Polygon, Pt2D, Speed}; @@ -31,6 +31,7 @@ pub struct Map { bus_routes: Vec, areas: Vec, parking_lots: Vec, + zones: Vec, boundary_polygon: Polygon, // Note that border nodes belong in neither! @@ -88,6 +89,10 @@ impl Map { "- parking lots: {} bytes", prettyprint_usize(serialized_size_bytes(&map.parking_lots)) ); + println!( + "- zones: {} bytes", + prettyprint_usize(serialized_size_bytes(&map.zones)) + ); println!( "- pathfinder: {} bytes", prettyprint_usize(serialized_size_bytes(&map.pathfinder)) @@ -125,6 +130,7 @@ impl Map { bus_routes: Vec::new(), areas: Vec::new(), parking_lots: Vec::new(), + zones: Vec::new(), boundary_polygon: Polygon::new(&vec![ Pt2D::new(0.0, 0.0), Pt2D::new(1.0, 0.0), @@ -282,6 +288,10 @@ impl Map { &self.parking_lots } + pub fn all_zones(&self) -> &Vec { + &self.zones + } + pub fn maybe_get_r(&self, id: RoadID) -> Option<&Road> { self.roads.get(id.0) } @@ -355,6 +365,10 @@ impl Map { &self.parking_lots[id.0] } + pub fn get_z(&self, id: ZoneID) -> &Zone { + &self.zones[id.0] + } + pub fn get_stop_sign(&self, id: IntersectionID) -> &ControlStopSign { &self.stop_signs[&id] } @@ -909,6 +923,7 @@ fn make_half_map( bus_routes: Vec::new(), areas: Vec::new(), parking_lots: Vec::new(), + zones: Vec::new(), boundary_polygon: raw.boundary_polygon.clone(), stop_signs: BTreeMap::new(), traffic_signals: BTreeMap::new(), @@ -1121,6 +1136,8 @@ fn make_half_map( map.parking_lots = make::buildings::make_all_parking_lots(&raw.parking_lots, &raw.parking_aisles, &map, timer); + map.zones = make::zones::make_all_zones(&map); + for (idx, a) in raw.areas.iter().enumerate() { map.areas.push(Area { id: AreaID(idx), diff --git a/map_model/src/zone.rs b/map_model/src/zone.rs new file mode 100644 index 0000000000..3808f8f555 --- /dev/null +++ b/map_model/src/zone.rs @@ -0,0 +1,21 @@ +use crate::{IntersectionID, RoadID}; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeSet; +use std::fmt; + +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct ZoneID(pub usize); + +impl fmt::Display for ZoneID { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Zone #{}", self.0) + } +} + +// A contiguous set of roads with access restrictions +#[derive(Serialize, Deserialize, Debug)] +pub struct Zone { + pub id: ZoneID, + pub members: BTreeSet, + pub borders: BTreeSet, +}