diff --git a/docs/TODO_phase4.md b/docs/TODO_phase4.md index a15439bf35..a49500f30f 100644 --- a/docs/TODO_phase4.md +++ b/docs/TODO_phase4.md @@ -4,3 +4,6 @@ - montlake/520 turn restrictions with pedestrian scramble - close interior neighborhoods to most cars (except for src/dst), see how traffic restricted to arterials would work - create a bike network with minimal hills, dedicated roads, minimal crossings + +- easter eggs + - name agents, with some good names scattered in diff --git a/docs/design.md b/docs/design.md index c849f5cd98..173c72799e 100644 --- a/docs/design.md +++ b/docs/design.md @@ -578,3 +578,6 @@ Time to get even more multi-modal / multi-phase! - all trips begin and end at a building - so first lets make all building paths go to a sidewalk. ignoring st name seems reasonable, since some buildings lack names anyway. +- sample trips... + - ped walks from bldg to sidewalk, to another sidewalk, then to another bldg + - ped walks from bldg to sidewalk, walks to their car, drives somewhere, parks, walks to right sidewalk and then a bldg diff --git a/editor/src/render/building.rs b/editor/src/render/building.rs index d2f691dcf4..00c49c75bd 100644 --- a/editor/src/render/building.rs +++ b/editor/src/render/building.rs @@ -15,17 +15,17 @@ pub struct DrawBuilding { // TODO should just have one. use graphics::Line for now. boundary_polygon: Polygon, pub fill_polygon: Polygon, - front_path: Option<[f64; 4]>, + front_path: [f64; 4], } impl DrawBuilding { pub fn new(bldg: &Building) -> DrawBuilding { DrawBuilding { id: bldg.id, - // TODO ideally start the path on a side of the building - front_path: bldg.front_path - .as_ref() - .map(|l| [l.pt1().x(), l.pt1().y(), l.pt2().x(), l.pt2().y()]), + front_path: { + let l = &bldg.front_path; + [l.pt1().x(), l.pt1().y(), l.pt2().x(), l.pt2().y()] + }, fill_polygon: Polygon::new(&bldg.points), boundary_polygon: PolyLine::new(bldg.points.clone()) .make_polygons_blindly(BUILDING_BOUNDARY_THICKNESS), @@ -39,10 +39,8 @@ impl DrawBuilding { path_color: Color, boundary_color: Color, ) { - if let Some(line) = self.front_path { - // TODO tune width - g.draw_line(&graphics::Line::new_round(path_color, 1.0), line); - } + // TODO tune width + g.draw_line(&graphics::Line::new_round(path_color, 1.0), self.front_path); g.draw_polygon(boundary_color, &self.boundary_polygon); g.draw_polygon(fill_color, &self.fill_polygon); @@ -66,10 +64,8 @@ impl DrawBuilding { pub fn get_bbox(&self) -> Rect { let mut b = self.fill_polygon.get_bounds(); - if let Some(line) = self.front_path { - b.update(line[0], line[1]); - b.update(line[2], line[3]); - } + b.update(self.front_path[0], self.front_path[1]); + b.update(self.front_path[2], self.front_path[3]); get_bbox(&b) } } diff --git a/map_model/src/building.rs b/map_model/src/building.rs index cdce11d046..c397113d5e 100644 --- a/map_model/src/building.rs +++ b/map_model/src/building.rs @@ -22,7 +22,7 @@ pub struct Building { pub osm_tags: BTreeMap, pub osm_way_id: i64, - pub front_path: Option, + pub front_path: Line, } impl PartialEq for Building { diff --git a/map_model/src/make/buildings.rs b/map_model/src/make/buildings.rs index 0870b83d7e..210beab6e5 100644 --- a/map_model/src/make/buildings.rs +++ b/map_model/src/make/buildings.rs @@ -11,14 +11,15 @@ pub(crate) fn make_building( id: BuildingID, bounds: &Bounds, lanes: &Vec, - roads: &Vec, + _roads: &Vec, ) -> Building { // TODO consume data, so we dont have to clone tags? let points = b.points .iter() .map(|coord| Pt2D::from_gps(coord, bounds)) .collect(); - let front_path = find_front_path(&points, &b.osm_tags, lanes, roads); + //let front_path = find_front_path_using_street_names(&points, &b.osm_tags, lanes, roads); + let front_path = find_front_path(&points, lanes); Building { points, @@ -29,7 +30,37 @@ pub(crate) fn make_building( } } -fn find_front_path( +fn find_front_path(bldg_points: &Vec, lanes: &Vec) -> Line { + use geo::prelude::{ClosestPoint, EuclideanDistance}; + + // TODO start from the side of the building, not the center + let bldg_center = geometry::center(bldg_points); + let center_pt = geo::Point::new(bldg_center.x(), bldg_center.y()); + + // Find the closest point on ALL sidewalks + let candidates: Vec<(LaneID, geo::Point)> = lanes + .iter() + .filter_map(|l| { + if l.is_sidewalk() { + if let geo::Closest::SinglePoint(pt) = + lane_to_line_string(&lanes[l.id.0]).closest_point(¢er_pt) + { + return Some((l.id, pt)); + } + } + None + }) + .collect(); + + let closest = candidates + .iter() + .min_by_key(|pair| NotNaN::new(pair.1.euclidean_distance(¢er_pt)).unwrap()) + .unwrap(); + Line::new(bldg_center, Pt2D::new(closest.1.x(), closest.1.y())) +} + +#[allow(dead_code)] +fn find_front_path_using_street_names( bldg_points: &Vec, bldg_osm_tags: &BTreeMap, lanes: &Vec,