1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
use crate::{IndividTrip, PersonID, PersonSpec, SpawnTrip, TripEndpoint, TripMode}; use geom::{Distance, FindClosest, LonLat, Pt2D, Time}; use map_model::Map; use serde::Deserialize; #[derive(Deserialize)] pub struct ExternalPerson { pub origin: LonLat, pub trips: Vec<ExternalTrip>, } #[derive(Deserialize)] pub struct ExternalTrip { pub departure: Time, pub position: LonLat, pub mode: TripMode, } impl ExternalPerson { pub fn import(map: &Map, input: Vec<ExternalPerson>) -> Result<Vec<PersonSpec>, String> { let mut closest: FindClosest<TripEndpoint> = FindClosest::new(map.get_bounds()); for b in map.all_buildings() { closest.add(TripEndpoint::Bldg(b.id), b.polygon.points()); } for i in map.all_intersections() { closest.add(TripEndpoint::Border(i.id, None), i.polygon.points()); } let lookup_pt = |gps| match closest.closest_pt( Pt2D::from_gps(gps, map.get_gps_bounds()), Distance::meters(100.0), ) { Some((x, _)) => Ok(x), None => Err(format!( "No building or border intersection within 100m of {}", gps )), }; let mut results = Vec::new(); for person in input { let mut spec = PersonSpec { id: PersonID(results.len()), orig_id: None, trips: Vec::new(), }; let mut from = lookup_pt(person.origin)?; for trip in person.trips { let to = lookup_pt(trip.position)?; if let Some(t) = SpawnTrip::new(from.clone(), to.clone(), trip.mode, &map) { spec.trips.push(IndividTrip::new(trip.departure, t)); from = to; } else { return Err(format!( "Can't make a {} trip from {:?} to {:?}", trip.mode.ongoing_verb(), from, to )); } } results.push(spec); } Ok(results) } }