diff --git a/importer/src/bin/import_traffic.rs b/importer/src/bin/import_traffic.rs index 728ef67c18..ea6e5f71d1 100644 --- a/importer/src/bin/import_traffic.rs +++ b/importer/src/bin/import_traffic.rs @@ -1,6 +1,6 @@ use serde::Deserialize; -use abstutil::{CmdArgs, Timer}; +use abstutil::{prettyprint_usize, CmdArgs, Timer}; use map_model::Map; use sim::{ExternalPerson, Scenario}; @@ -8,6 +8,7 @@ fn main() { let mut args = CmdArgs::new(); let map = args.required("--map"); let input = args.required("--input"); + let skip_problems = args.enabled("--skip_problems"); args.done(); let mut timer = Timer::new("import traffic demand data"); @@ -17,7 +18,13 @@ fn main() { let mut s = Scenario::empty(&map, &input.scenario_name); // Include all buses/trains s.only_seed_buses = None; - s.people = ExternalPerson::import(&map, input.people).unwrap(); + let orig_num = input.people.len(); + s.people = ExternalPerson::import(&map, input.people, skip_problems).unwrap(); + println!( + "Imported {}/{} people", + prettyprint_usize(s.people.len()), + prettyprint_usize(orig_num) + ); s.save(); } diff --git a/sim/src/make/external.rs b/sim/src/make/external.rs index a5edbefc7e..b334b41680 100644 --- a/sim/src/make/external.rs +++ b/sim/src/make/external.rs @@ -33,8 +33,13 @@ impl ExternalPerson { /// `PersonSpec` is a way to specify endpoints by a `LonLat`. This is snapped to the nearest /// building. If the point is outside of the map boundary, it's snapped to the nearest border /// (by Euclidean distance -- the network outside the given map isn't known). Failure happens - /// if a point is within the map, but not close enough to any buildings. - pub fn import(map: &Map, input: Vec) -> Result> { + /// if a point is within the map, but not close enough to any buildings. If `skip_problems` is + /// true, then those failures are logged; otherwise this panics at the first problem. + pub fn import( + map: &Map, + input: Vec, + skip_problems: bool, + ) -> Result> { let mut closest: FindClosest = FindClosest::new(map.get_bounds()); for b in map.all_buildings() { closest.add(TripEndpoint::Bldg(b.id), b.polygon.points()); @@ -68,7 +73,17 @@ impl ExternalPerson { for person in input { let mut spec = PersonSpec { orig_id: None, - origin: lookup_pt(person.origin, true, person.trips[0].mode)?, + origin: match lookup_pt(person.origin, true, person.trips[0].mode) { + Ok(endpt) => endpt, + Err(err) => { + if skip_problems { + warn!("Skipping person: {}", err); + continue; + } else { + return Err(err); + } + } + }, trips: Vec::new(), }; for trip in person.trips { @@ -78,7 +93,17 @@ impl ExternalPerson { TripPurpose::Shopping, // TODO Do we handle somebody going off-map via one one-way bridge, and // re-entering using the other? - lookup_pt(trip.destination, false, trip.mode)?, + match lookup_pt(trip.destination, false, trip.mode) { + Ok(endpt) => endpt, + Err(err) => { + if skip_problems { + warn!("Skipping person: {}", err); + continue; + } else { + return Err(err); + } + } + }, trip.mode, )); }