finding paths between buildings and nearest sidewalk

This commit is contained in:
Dustin Carlino 2018-06-20 12:51:11 -07:00
parent 03df50c96e
commit c2473828a6
7 changed files with 97 additions and 8 deletions

14
TODO.md
View File

@ -45,17 +45,20 @@
- https://gis-kingcounty.opendata.arcgis.com/datasets/traffic-signs--sign-point/
- multiple lanes
- model cars parking
- maybe render numbers on the cars to distinguish them
- document the FSM (on lane driving, waiting, turning, parking, etc)
- always draw building to sidewalk paths
- move colors to config, have interactive picker
- model bikes in driving lanes (as slow cars)
- add random bike lanes, figure out how turns would work
- be able to convert between parking and bike lanes, recompute the turns
- model cars parking
- maybe render numbers on the cars to distinguish them
- document the FSM (on lane driving, waiting, turning, parking, etc)
- model pdestrians
- maybe draw crosswalks?
- when rendering sidewalks, have an option for a grass buffer
- regression testing
- goldenfile approach for map_model, geom, and render layer from a small OSM chunk
- or maybe a visual demo approach with a list of things to manually check
@ -63,6 +66,7 @@
## Code cleanup
- where does 'extern crate' belong? only in main / mod?
- clean up code
- master Map struct
- line type / ditch vec2d / settle on types

View File

@ -6,6 +6,7 @@ authors = ["Dustin Carlino <dabreegster@gmail.com>"]
[dependencies]
aabb-quadtree = "0.1.0"
control = { path = "../control" }
geo = "0.9.1"
geom = { path = "../geom" }
ezgui = { path = "../ezgui" }
map_model = { path = "../map_model" }

View File

@ -3,6 +3,7 @@
extern crate aabb_quadtree;
extern crate control;
extern crate ezgui;
extern crate geo;
extern crate geom;
extern crate glutin_window;
extern crate graphics;

View File

@ -182,6 +182,7 @@ impl SelectionState {
}
SelectionState::SelectedBuilding(id) => {
canvas.draw_mouse_tooltip(g, &draw_map.get_b(id).tooltip_lines(map));
draw_map.get_b(id).draw_sidewalk_path(g, map, geom_map);
}
SelectionState::SelectedCar(id) => {
canvas.draw_mouse_tooltip(g, &sim.car_tooltip(id));

View File

@ -1,15 +1,19 @@
// Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0
extern crate aabb_quadtree;
extern crate geo;
extern crate map_model;
use aabb_quadtree::geom::Rect;
use ezgui::canvas::GfxCtx;
use geom::GeomMap;
use geom::geometry;
use graphics;
use graphics::math::Vec2d;
use graphics::types::Color;
use map_model::{Bounds, BuildingID};
use ordered_float::NotNaN;
use render;
use std::f64;
#[derive(Debug)]
@ -54,4 +58,78 @@ impl DrawBuilding {
pub fn get_bbox(&self) -> Rect {
geometry::get_bbox_for_polygons(&[self.polygon.clone()])
}
// TODO compute these once, and draw them always
// TODO ideally start the path on a side of the building
pub fn draw_sidewalk_path(&self, g: &mut GfxCtx, map: &map_model::Map, geom_map: &GeomMap) {
use geo::prelude::{ClosestPoint, EuclideanDistance};
if let Some(tag) = map.get_b(self.id)
.osm_tags
.iter()
.find(|kv| kv.starts_with("addr:street="))
{
let (_, street_name) = tag.split_at("addr:street=".len());
let bldg_center = self.center();
let center_pt = geo::Point::new(bldg_center[0], bldg_center[1]);
// Find all matching sidewalks with that street name, then find the closest point on
// that sidewalk
let candidates: Vec<(map_model::RoadID, geo::Point<f64>)> = map.all_roads()
.iter()
.filter_map(|r| {
if r.lane_type == map_model::LaneType::Sidewalk
&& map_model::has_osm_tag(&r.osm_tags, "name", street_name)
{
if let geo::Closest::SinglePoint(pt) =
road_to_line_string(r.id, geom_map).closest_point(&center_pt)
{
return Some((r.id, pt));
}
}
None
})
.collect();
if let Some(closest) = candidates
.iter()
.min_by_key(|pair| NotNaN::new(pair.1.euclidean_distance(&center_pt)).unwrap())
{
let path = graphics::Line::new_round(render::DEBUG_COLOR, 1.0);
path.draw(
[center_pt.x(), center_pt.y(), closest.1.x(), closest.1.y()],
&g.ctx.draw_state,
g.ctx.transform,
g.gfx,
);
}
}
}
fn center(&self) -> Vec2d {
let mut x = 0.0;
let mut y = 0.0;
for pt in &self.polygon {
x += pt[0];
y += pt[1];
}
let len = self.polygon.len() as f64;
[x / len, y / len]
}
}
fn road_to_line_string(r: map_model::RoadID, geom_map: &GeomMap) -> geo::LineString<f64> {
let pts: Vec<geo::Point<f64>> = geom_map
.get_r(r)
.lane_center_lines
.iter()
.flat_map(|pair| {
vec![
geo::Point::new(pair.0.x(), pair.0.y()),
geo::Point::new(pair.1.x(), pair.1.y()),
]
})
.collect();
pts.into()
}

View File

@ -35,18 +35,18 @@ impl DrawParcel {
}
}
pub fn draw(&self, g: &mut GfxCtx, (boundary_color, fill_color): (Color, Color)) {
pub fn draw(&self, g: &mut GfxCtx, (boundary_color, _fill_color): (Color, Color)) {
let boundary_poly = graphics::Polygon::new(boundary_color);
for p in &self.boundary_polygons {
boundary_poly.draw(p, &g.ctx.draw_state, g.ctx.transform, g.gfx);
}
let fill_poly = graphics::Polygon::new(fill_color);
/*let fill_poly = graphics::Polygon::new(fill_color);
fill_poly.draw(
&self.fill_polygon,
&g.ctx.draw_state,
g.ctx.transform,
g.gfx,
);
);*/
}
//pub fn contains_pt(&self, x: f64, y: f64) -> bool {}

View File

@ -505,3 +505,7 @@ impl Map {
b
}
}
pub fn has_osm_tag(tags: &Vec<String>, key: &str, value: &str) -> bool {
tags.contains(&format!("{}={}", key, value))
}