mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 23:15:24 +03:00
start representing access restrictions by mode
This commit is contained in:
parent
2b4bf1172b
commit
2c7440b03f
@ -8,8 +8,8 @@ data/input/raw_maps/huge_austin.bin,5d0fdca0eb9bae5cd5e0955442972bd4,https://www
|
||||
data/input/raw_maps/huge_seattle.bin,22f323f1ce1917df9e261f24f557780f,https://www.dropbox.com/s/r6cj78jq3z7s5bs/huge_seattle.bin.zip?dl=0
|
||||
data/input/raw_maps/lakeslice.bin,c346ac30ad726456802937729af76af4,https://www.dropbox.com/s/uh4oacev5raty9z/lakeslice.bin.zip?dl=0
|
||||
data/input/raw_maps/montlake.bin,b17d1f76d6c5dd4a3af07343ca52590d,https://www.dropbox.com/s/dfcoo90hpwa8osj/montlake.bin.zip?dl=0
|
||||
data/input/raw_maps/south_seattle.bin,aae79f98db1f1db4877fa3ea36dd6799,https://www.dropbox.com/s/fut27hmbobf3fn7/south_seattle.bin.zip?dl=0
|
||||
data/input/raw_maps/udistrict.bin,7a07a32527ebc4577cebdf79f410cfd2,https://www.dropbox.com/s/l6n8blpex76tl9q/udistrict.bin.zip?dl=0
|
||||
data/input/raw_maps/south_seattle.bin,a8ded05512d20fac14cdb8e605c14995,https://www.dropbox.com/s/1m7fkvuyhyev3cw/south_seattle.bin.zip?dl=0
|
||||
data/input/raw_maps/udistrict.bin,eba1715dd8a66ff3fb0a39aa92419d93,https://www.dropbox.com/s/wbudupyrqd1aqg6/udistrict.bin.zip?dl=0
|
||||
data/input/raw_maps/west_seattle.bin,04c347cc62a3c2f078190b98af04c10f,https://www.dropbox.com/s/350gq0dtgvw2lrg/west_seattle.bin.zip?dl=0
|
||||
data/input/screenshots/downtown/01x01.gif,873df007edd02e5967f3917cbe8f342f,https://www.dropbox.com/s/4209gvxkypinlqs/01x01.gif.zip?dl=0
|
||||
data/input/screenshots/downtown/01x02.gif,ec8b579d6cb498a2a85bc2af8b51f390,https://www.dropbox.com/s/9x5qtp86h3uemzm/01x02.gif.zip?dl=0
|
||||
@ -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,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/maps/ballard.bin,dcf893cd9a338f00cb88b5fe2048fe7a,https://www.dropbox.com/s/v4zdc1g5gjz5gyo/ballard.bin.zip?dl=0
|
||||
data/system/maps/downtown.bin,5cfdff22ec0f8961d88054f613ee186a,https://www.dropbox.com/s/mw16rjqikr4u754/downtown.bin.zip?dl=0
|
||||
data/system/maps/downtown_atx.bin,63cba91cbc3366eec68fba251d58a6da,https://www.dropbox.com/s/s2h3p2h5dv6snre/downtown_atx.bin.zip?dl=0
|
||||
data/system/maps/huge_austin.bin,1141475a9b9e6d41b5d483403ce7ddf3,https://www.dropbox.com/s/9cra6p70e5vdc47/huge_austin.bin.zip?dl=0
|
||||
data/system/maps/huge_seattle.bin,2fcc78ca78c6870912a898cafc1120ae,https://www.dropbox.com/s/ks1sdcn3u8jbkri/huge_seattle.bin.zip?dl=0
|
||||
data/system/maps/lakeslice.bin,8a33d642b6af5875e2d48ceb685b84b0,https://www.dropbox.com/s/883ptuk0yga16qh/lakeslice.bin.zip?dl=0
|
||||
data/system/maps/montlake.bin,338597accb3c94c2cd0fd0156b1bbd07,https://www.dropbox.com/s/cxyk0q7e4t048u0/montlake.bin.zip?dl=0
|
||||
data/system/maps/south_seattle.bin,689aa5e980e08a58e86665a7a090ba46,https://www.dropbox.com/s/1prnq73si0xwwdt/south_seattle.bin.zip?dl=0
|
||||
data/system/maps/udistrict.bin,6e1cecb203a4453a2aa85d79b02f9844,https://www.dropbox.com/s/wo49zxaw6z680xp/udistrict.bin.zip?dl=0
|
||||
data/system/maps/west_seattle.bin,04123324605285542d5c6ed668d7c389,https://www.dropbox.com/s/71cexi6kijdxaz2/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
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::app::App;
|
||||
use crate::app::{App, ShowEverything};
|
||||
use crate::common::ColorDiscrete;
|
||||
use crate::common::CommonState;
|
||||
use crate::game::{State, Transition};
|
||||
@ -9,25 +9,31 @@ use ezgui::{
|
||||
};
|
||||
use map_model::RoadID;
|
||||
use maplit::btreeset;
|
||||
use sim::{DontDrawAgents, TripMode};
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
pub struct ZoneEditor {
|
||||
composite: Composite,
|
||||
members: BTreeSet<RoadID>,
|
||||
_members: BTreeSet<RoadID>,
|
||||
unzoomed: Drawable,
|
||||
zoomed: Drawable,
|
||||
}
|
||||
|
||||
impl ZoneEditor {
|
||||
pub fn new(ctx: &mut EventCtx, app: &App, start: RoadID) -> Box<dyn State> {
|
||||
let members = if app.primary.map.get_r(start).is_private() {
|
||||
app.primary.map.road_to_zone(start).members.clone()
|
||||
let (members, allow_through_traffic) = if let Some(z) = app.primary.map.get_r(start).zone {
|
||||
let zone = app.primary.map.get_z(z);
|
||||
(
|
||||
zone.members.clone(),
|
||||
zone.allow_through_traffic
|
||||
.iter()
|
||||
.map(|c| TripMode::from_constraints(*c))
|
||||
.collect(),
|
||||
)
|
||||
} else {
|
||||
// Starting a new zone
|
||||
btreeset! { start }
|
||||
(btreeset! { start }, BTreeSet::new())
|
||||
};
|
||||
// TODO Pull this from the existing zone
|
||||
let allow_thru_trips = BTreeSet::new();
|
||||
|
||||
let (unzoomed, zoomed, legend) = draw_zone(ctx, app, &members);
|
||||
|
||||
@ -45,7 +51,7 @@ impl ZoneEditor {
|
||||
)
|
||||
.draw(ctx)
|
||||
.margin_below(10),
|
||||
checkbox_per_mode(ctx, app, &allow_thru_trips).margin_below(10),
|
||||
checkbox_per_mode(ctx, app, &allow_through_traffic).margin_below(10),
|
||||
Widget::row(vec![
|
||||
Btn::text_fg("Apply").build_def(ctx, hotkey(Key::Enter)),
|
||||
Btn::text_fg("Cancel").build_def(ctx, hotkey(Key::Escape)),
|
||||
@ -57,7 +63,7 @@ impl ZoneEditor {
|
||||
)
|
||||
.aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
|
||||
.build(ctx),
|
||||
members,
|
||||
_members: members,
|
||||
unzoomed,
|
||||
zoomed,
|
||||
})
|
||||
@ -67,14 +73,28 @@ impl ZoneEditor {
|
||||
impl State for ZoneEditor {
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition {
|
||||
ctx.canvas_movement();
|
||||
// Restrict what can be selected.
|
||||
|
||||
// TODO Share with PaintSelect.
|
||||
if ctx.redo_mouseover() {
|
||||
app.recalculate_current_selection(ctx);
|
||||
if let Some(ID::Lane(_)) = app.primary.current_selection {
|
||||
} else if let Some(ID::Road(_)) = app.primary.current_selection {
|
||||
app.primary.current_selection = app.calculate_current_selection(
|
||||
ctx,
|
||||
&DontDrawAgents {},
|
||||
&ShowEverything::new(),
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
);
|
||||
if let Some(ID::Road(_)) = app.primary.current_selection {
|
||||
} else if let Some(ID::Lane(l)) = app.primary.current_selection {
|
||||
app.primary.current_selection = Some(ID::Road(app.primary.map.get_l(l).parent));
|
||||
} else {
|
||||
app.primary.current_selection = None;
|
||||
}
|
||||
if let Some(ID::Road(r)) = app.primary.current_selection {
|
||||
if app.primary.map.get_r(r).is_light_rail() {
|
||||
app.primary.current_selection = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match self.composite.event(ctx) {
|
||||
@ -94,6 +114,7 @@ impl State for ZoneEditor {
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, app: &App) {
|
||||
// TODO The currently selected road is covered up pretty badly
|
||||
if g.canvas.cam_zoom < app.opts.min_zoom_for_detail {
|
||||
g.redraw(&self.unzoomed);
|
||||
} else {
|
||||
@ -112,7 +133,7 @@ fn draw_zone(
|
||||
let mut colorer = ColorDiscrete::new(
|
||||
app,
|
||||
vec![
|
||||
("restricted road", Color::RED),
|
||||
("restricted road", Color::CYAN),
|
||||
("entrance/exit", Color::BLUE),
|
||||
],
|
||||
);
|
||||
|
@ -16,7 +16,7 @@ pub fn info(ctx: &EventCtx, app: &App, details: &mut Details, id: LaneID) -> Vec
|
||||
if !l.is_sidewalk() {
|
||||
kv.push(("Type", l.lane_type.describe().to_string()));
|
||||
}
|
||||
if r.is_private() {
|
||||
if r.zone.is_some() {
|
||||
// TODO Ideally the area name, and be more specific about access restrictions
|
||||
kv.push(("Access", "Private".to_string()));
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ impl DrawLane {
|
||||
}
|
||||
};
|
||||
}
|
||||
if road.is_private() {
|
||||
if road.zone.is_some() {
|
||||
draw.push(cs.private_road.alpha(0.5), polygon.clone());
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ impl DrawMap {
|
||||
all_roads.push(
|
||||
if r.is_light_rail() {
|
||||
cs.light_rail_track
|
||||
} else if r.is_private() {
|
||||
} else if r.zone.is_some() {
|
||||
cs.private_road
|
||||
} else {
|
||||
osm_rank_to_color(cs, r.get_rank())
|
||||
|
@ -20,7 +20,7 @@ impl DrawRoad {
|
||||
let mut draw = GeomBatch::new();
|
||||
let center = r.get_current_center(map);
|
||||
let width = Distance::meters(0.25);
|
||||
let color = if r.is_private() {
|
||||
let color = if r.zone.is_some() {
|
||||
cs.road_center_line.lerp(cs.private_road, 0.5)
|
||||
} else {
|
||||
cs.road_center_line
|
||||
@ -70,12 +70,12 @@ impl Renderable for DrawRoad {
|
||||
if r.center_pts.length() >= Distance::meters(30.0) && name != "???" {
|
||||
// TODO If it's definitely straddling bus/bike lanes, change the color? Or
|
||||
// even easier, just skip the center lines?
|
||||
let fg = if r.is_private() {
|
||||
let fg = if r.zone.is_some() {
|
||||
app.cs.road_center_line.lerp(app.cs.private_road, 0.5)
|
||||
} else {
|
||||
app.cs.road_center_line
|
||||
};
|
||||
let bg = if r.is_private() {
|
||||
let bg = if r.zone.is_some() {
|
||||
app.cs.driving_lane.lerp(app.cs.private_road, 0.5)
|
||||
} else {
|
||||
app.cs.driving_lane
|
||||
|
@ -65,7 +65,7 @@ impl Intersection {
|
||||
}
|
||||
|
||||
pub fn is_private(&self, map: &Map) -> bool {
|
||||
self.roads.iter().all(|r| map.get_r(*r).is_private())
|
||||
self.roads.iter().all(|r| map.get_r(*r).zone.is_some())
|
||||
}
|
||||
|
||||
pub fn get_incoming_lanes<'a>(
|
||||
|
@ -4,7 +4,7 @@ use std::collections::BTreeSet;
|
||||
pub fn make_all_zones(map: &Map) -> Vec<Zone> {
|
||||
let mut queue = Vec::new();
|
||||
for r in map.all_roads() {
|
||||
if r.is_private() {
|
||||
if r.osm_tags.get("access") == Some(&"private".to_string()) {
|
||||
queue.push(r.id);
|
||||
}
|
||||
}
|
||||
@ -36,7 +36,7 @@ fn floodfill(map: &Map, start: RoadID, id: ZoneID) -> Zone {
|
||||
members.insert(current);
|
||||
for r in map.get_next_roads(current) {
|
||||
let r = map.get_r(r);
|
||||
if r.is_private() {
|
||||
if r.osm_tags.get("access") == Some(&"private".to_string()) {
|
||||
queue.push(r.id);
|
||||
} else {
|
||||
borders.insert(map.get_r(current).common_endpt(r));
|
||||
@ -49,5 +49,6 @@ fn floodfill(map: &Map, start: RoadID, id: ZoneID) -> Zone {
|
||||
id,
|
||||
members,
|
||||
borders,
|
||||
allow_through_traffic: BTreeSet::new(),
|
||||
}
|
||||
}
|
||||
|
@ -745,11 +745,6 @@ impl Map {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn road_to_zone(&self, r: RoadID) -> &Zone {
|
||||
// TODO Consider indexing
|
||||
self.zones.iter().find(|z| z.members.contains(&r)).unwrap()
|
||||
}
|
||||
|
||||
pub fn right_shift(&self, pl: PolyLine, width: Distance) -> Warn<PolyLine> {
|
||||
self.driving_side.right_shift(pl, width)
|
||||
}
|
||||
@ -1024,6 +1019,7 @@ fn make_half_map(
|
||||
} else {
|
||||
0
|
||||
},
|
||||
zone: None,
|
||||
};
|
||||
road.speed_limit = road.speed_limit_from_osm();
|
||||
|
||||
@ -1142,6 +1138,11 @@ fn make_half_map(
|
||||
make::buildings::make_all_parking_lots(&raw.parking_lots, &raw.parking_aisles, &map, timer);
|
||||
|
||||
map.zones = make::zones::make_all_zones(&map);
|
||||
for z in &map.zones {
|
||||
for r in &z.members {
|
||||
map.roads[r.0].zone = Some(z.id);
|
||||
}
|
||||
}
|
||||
|
||||
for (idx, a) in raw.areas.iter().enumerate() {
|
||||
map.areas.push(Area {
|
||||
|
@ -161,7 +161,9 @@ fn make_input_graph(
|
||||
for l in map.all_lanes() {
|
||||
let from = nodes.get(Node::Lane(l.id));
|
||||
let mut any = false;
|
||||
if constraints.can_use(l, map) && !map.get_r(l.parent).is_private() {
|
||||
if constraints.can_use(l, map)
|
||||
&& map.get_r(l.parent).allow_through_traffic(constraints, map)
|
||||
{
|
||||
let indices = uber_turn_entrances.get(l.id);
|
||||
if indices.is_empty() {
|
||||
for turn in map.get_turns_for(l.id, constraints) {
|
||||
|
@ -365,7 +365,7 @@ fn glue(step1: PathStep, step2: PathStep, map: &Map) -> TurnID {
|
||||
|
||||
// Who's asking for a path?
|
||||
// TODO This is an awful name.
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum PathConstraints {
|
||||
Pedestrian,
|
||||
Car,
|
||||
@ -385,6 +385,7 @@ impl PathConstraints {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Handle private zones here?
|
||||
pub fn can_use(self, l: &Lane, map: &Map) -> bool {
|
||||
match self {
|
||||
PathConstraints::Pedestrian => l.is_sidewalk(),
|
||||
@ -557,58 +558,63 @@ impl Pathfinder {
|
||||
let start_r = map.get_parent(req.start.lane());
|
||||
let end_r = map.get_parent(req.end.lane());
|
||||
|
||||
if start_r.is_private() && end_r.is_private() {
|
||||
let zone1 = map.road_to_zone(start_r.id);
|
||||
let zone2 = map.road_to_zone(end_r.id);
|
||||
if zone1.id == zone2.id {
|
||||
zone1.pathfind(req, map)
|
||||
if start_r.zone.is_some() && end_r.zone.is_some() {
|
||||
if start_r.zone == end_r.zone {
|
||||
let zone = map.get_z(start_r.zone.unwrap());
|
||||
if !zone.allow_through_traffic.contains(&req.constraints) {
|
||||
return zone.pathfind(req, map);
|
||||
}
|
||||
} else {
|
||||
// TODO Handle paths going between two different zones
|
||||
None
|
||||
}
|
||||
} else if start_r.is_private() {
|
||||
if req.constraints == PathConstraints::Pedestrian {
|
||||
return None;
|
||||
}
|
||||
let zone = map.road_to_zone(start_r.id);
|
||||
let mut borders: Vec<&Intersection> =
|
||||
zone.borders.iter().map(|i| map.get_i(*i)).collect();
|
||||
// TODO Use the CH to pick the lowest overall cost?
|
||||
let pt = req.end.pt(map);
|
||||
borders.sort_by_key(|i| pt.dist_to(i.polygon.center()));
|
||||
|
||||
for i in borders {
|
||||
if let Some(result) = self.pathfind_from_zone(i, req.clone(), zone, map) {
|
||||
validate_continuity(map, &result.steps.iter().cloned().collect());
|
||||
return Some(result);
|
||||
} else if let Some(z) = start_r.zone {
|
||||
let zone = map.get_z(z);
|
||||
if !zone.allow_through_traffic.contains(&req.constraints) {
|
||||
if req.constraints == PathConstraints::Pedestrian {
|
||||
return None;
|
||||
}
|
||||
let mut borders: Vec<&Intersection> =
|
||||
zone.borders.iter().map(|i| map.get_i(*i)).collect();
|
||||
// TODO Use the CH to pick the lowest overall cost?
|
||||
let pt = req.end.pt(map);
|
||||
borders.sort_by_key(|i| pt.dist_to(i.polygon.center()));
|
||||
|
||||
for i in borders {
|
||||
if let Some(result) = self.pathfind_from_zone(i, req.clone(), zone, map) {
|
||||
validate_continuity(map, &result.steps.iter().cloned().collect());
|
||||
return Some(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
} else if end_r.is_private() {
|
||||
if req.constraints == PathConstraints::Pedestrian {
|
||||
return None;
|
||||
}
|
||||
let zone = map.road_to_zone(end_r.id);
|
||||
let mut borders: Vec<&Intersection> =
|
||||
zone.borders.iter().map(|i| map.get_i(*i)).collect();
|
||||
// TODO Use the CH to pick the lowest overall cost?
|
||||
let pt = req.start.pt(map);
|
||||
borders.sort_by_key(|i| pt.dist_to(i.polygon.center()));
|
||||
|
||||
for i in borders {
|
||||
if let Some(result) = self.pathfind_to_zone(i, req.clone(), zone, map) {
|
||||
validate_continuity(map, &result.steps.iter().cloned().collect());
|
||||
return Some(result);
|
||||
} else if let Some(z) = end_r.zone {
|
||||
let zone = map.get_z(z);
|
||||
if !zone.allow_through_traffic.contains(&req.constraints) {
|
||||
if req.constraints == PathConstraints::Pedestrian {
|
||||
return None;
|
||||
}
|
||||
let mut borders: Vec<&Intersection> =
|
||||
zone.borders.iter().map(|i| map.get_i(*i)).collect();
|
||||
// TODO Use the CH to pick the lowest overall cost?
|
||||
let pt = req.start.pt(map);
|
||||
borders.sort_by_key(|i| pt.dist_to(i.polygon.center()));
|
||||
|
||||
for i in borders {
|
||||
if let Some(result) = self.pathfind_to_zone(i, req.clone(), zone, map) {
|
||||
validate_continuity(map, &result.steps.iter().cloned().collect());
|
||||
return Some(result);
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
None
|
||||
} else {
|
||||
match req.constraints {
|
||||
PathConstraints::Pedestrian => self.walking_graph.pathfind(&req, map),
|
||||
PathConstraints::Car => self.car_graph.pathfind(&req, map).map(|(p, _)| p),
|
||||
PathConstraints::Bike => self.bike_graph.pathfind(&req, map).map(|(p, _)| p),
|
||||
PathConstraints::Bus => self.bus_graph.pathfind(&req, map).map(|(p, _)| p),
|
||||
}
|
||||
}
|
||||
|
||||
match req.constraints {
|
||||
PathConstraints::Pedestrian => self.walking_graph.pathfind(&req, map),
|
||||
PathConstraints::Car => self.car_graph.pathfind(&req, map).map(|(p, _)| p),
|
||||
PathConstraints::Bike => self.bike_graph.pathfind(&req, map).map(|(p, _)| p),
|
||||
PathConstraints::Bus => self.bus_graph.pathfind(&req, map).map(|(p, _)| p),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,11 @@ fn make_input_graph(
|
||||
let mut input_graph = InputGraph::new();
|
||||
|
||||
for l in map.all_lanes() {
|
||||
if l.is_sidewalk() && !map.get_r(l.parent).is_private() {
|
||||
if l.is_sidewalk()
|
||||
&& map
|
||||
.get_r(l.parent)
|
||||
.allow_through_traffic(PathConstraints::Pedestrian, map)
|
||||
{
|
||||
let cost = walking_cost(l.length());
|
||||
let n1 = nodes.get(WalkingNode::SidewalkEndpoint(l.id, true));
|
||||
let n2 = nodes.get(WalkingNode::SidewalkEndpoint(l.id, false));
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::raw::{OriginalRoad, RestrictionType};
|
||||
use crate::{osm, BusStopID, IntersectionID, LaneID, LaneType, Map, PathConstraints};
|
||||
use crate::{osm, BusStopID, IntersectionID, LaneID, LaneType, Map, PathConstraints, ZoneID};
|
||||
use abstutil::{Error, Warn};
|
||||
use geom::{Distance, PolyLine, Polygon, Speed};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -93,6 +93,7 @@ pub struct Road {
|
||||
pub complicated_turn_restrictions: Vec<(RoadID, RoadID)>,
|
||||
pub orig_id: OriginalRoad,
|
||||
pub speed_limit: Speed,
|
||||
pub zone: Option<ZoneID>,
|
||||
pub zorder: isize,
|
||||
|
||||
// Invariant: A road must contain at least one child
|
||||
@ -415,10 +416,6 @@ impl Road {
|
||||
!self.children_forwards.is_empty() && self.children_forwards[0].1 == LaneType::LightRail
|
||||
}
|
||||
|
||||
pub fn is_private(&self) -> bool {
|
||||
self.osm_tags.get("access") == Some(&"private".to_string())
|
||||
}
|
||||
|
||||
pub fn common_endpt(&self, other: &Road) -> IntersectionID {
|
||||
if self.src_i == other.src_i || self.src_i == other.dst_i {
|
||||
self.src_i
|
||||
@ -428,4 +425,12 @@ impl Road {
|
||||
panic!("{} and {} don't share an endpoint", self.id, other.id);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn allow_through_traffic(&self, constraints: PathConstraints, map: &Map) -> bool {
|
||||
if let Some(z) = self.zone {
|
||||
map.get_z(z).allow_through_traffic.contains(&constraints)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ pub struct Zone {
|
||||
pub id: ZoneID,
|
||||
pub members: BTreeSet<RoadID>,
|
||||
pub borders: BTreeSet<IntersectionID>,
|
||||
pub allow_through_traffic: BTreeSet<PathConstraints>,
|
||||
}
|
||||
|
||||
impl Zone {
|
||||
|
@ -1391,6 +1391,25 @@ impl TripMode {
|
||||
TripMode::Drive => "Car",
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Collapse these two enums?
|
||||
pub fn to_constraints(self) -> PathConstraints {
|
||||
match self {
|
||||
TripMode::Walk => PathConstraints::Pedestrian,
|
||||
TripMode::Bike => PathConstraints::Bike,
|
||||
TripMode::Transit => PathConstraints::Bus,
|
||||
TripMode::Drive => PathConstraints::Car,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_constraints(c: PathConstraints) -> TripMode {
|
||||
match c {
|
||||
PathConstraints::Pedestrian => TripMode::Walk,
|
||||
PathConstraints::Bike => TripMode::Bike,
|
||||
PathConstraints::Bus => TripMode::Transit,
|
||||
PathConstraints::Car => TripMode::Drive,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
||||
|
Loading…
Reference in New Issue
Block a user