adding a new hint for extra turn restrictions

This commit is contained in:
Dustin Carlino 2019-08-06 13:21:48 -07:00
parent bf5c45cd72
commit 574e30b3d8
7 changed files with 122 additions and 12 deletions

View File

@ -331,6 +331,30 @@
"latitude": 47.6447682 "latitude": 47.6447682
} }
} }
},
{
"BanTurnsBetween": [
{
"pt1": {
"longitude": -122.2961948,
"latitude": 47.6234769
},
"pt2": {
"longitude": -122.296451,
"latitude": 47.6236649
}
},
{
"pt1": {
"longitude": -122.2965799,
"latitude": 47.6236045
},
"pt2": {
"longitude": -122.2964149,
"latitude": 47.6233284
}
}
]
} }
], ],
"parking_overrides": [ "parking_overrides": [
@ -341,7 +365,7 @@
"latitude": 47.647500000184834 "latitude": 47.647500000184834
}, },
"pt2": { "pt2": {
"longitude": -122.30462539972673, "longitude": -122.30462539972672,
"latitude": 47.6469044999953 "latitude": 47.6469044999953
} }
}, },

View File

@ -6,7 +6,7 @@ become the complex maps in A/B Street. As always,
process generalizes to most cities in OpenStreetMap. Some extra data specific to process generalizes to most cities in OpenStreetMap. Some extra data specific to
Seattle is used, but could be ommitted. Seattle is used, but could be ommitted.
Everything here should be up-to-date as of July 2019. Everything here should be up-to-date as of August 2019.
<!--ts--> <!--ts-->
@ -176,6 +176,9 @@ before the final Map: InitialMap and HalfMap.
lanes, speed limit, or some other reason to preserve the intersection. lanes, speed limit, or some other reason to preserve the intersection.
- The hint to override parking on a road: the blockface dataset is inaccurate - The hint to override parking on a road: the blockface dataset is inaccurate
sometimes, so manually toggle parking on a road. sometimes, so manually toggle parking on a road.
- The ban turns hint: don't allow turns from one road to another. In areas
with many close intersections, there are some U-turns that may be valid in
reality, but quickly cause gridlock in the simulation.
## InitialMap to HalfMap ## InitialMap to HalfMap

View File

@ -28,6 +28,11 @@ enum State {
osd: Text, osd: Text,
}, },
BrowsingHints(WarpingItemSlider<Hint>), BrowsingHints(WarpingItemSlider<Hint>),
BanTurnsBetween {
from: StableRoadID,
selected: Option<ID>,
osd: Text,
},
} }
impl State { impl State {
@ -95,13 +100,6 @@ impl GUI for UI {
len, len,
self.hints.parking_overrides.len() self.hints.parking_overrides.len()
)); ));
for i in (1..=5).rev() {
if len >= i {
txt.add_line(describe(&self.hints.hints[len - i]));
} else {
txt.add_line("...".to_string());
}
}
if let Some(ID::Road(r)) = selected { if let Some(ID::Road(r)) = selected {
txt.push(format!( txt.push(format!(
"[red:{}] is {} long", "[red:{}] is {} long",
@ -169,7 +167,9 @@ impl GUI for UI {
.iter() .iter()
.filter_map(|h| { .filter_map(|h| {
let gps_pt = match h { let gps_pt = match h {
Hint::MergeRoad(r) | Hint::DeleteRoad(r) => { Hint::MergeRoad(r)
| Hint::DeleteRoad(r)
| Hint::BanTurnsBetween(r, _) => {
self.raw.roads[&self.raw.find_r(*r)?].points[0] self.raw.roads[&self.raw.find_r(*r)?].points[0]
} }
Hint::MergeDegenerateIntersection(i) => { Hint::MergeDegenerateIntersection(i) => {
@ -240,6 +240,16 @@ impl GUI for UI {
&mut Timer::new("override parking"), &mut Timer::new("override parking"),
); );
self.world = initial_map_to_world(&self.data, ctx); self.world = initial_map_to_world(&self.data, ctx);
} else if ctx
.input
.key_pressed(Key::T, "ban turns between this road and another")
{
self.state = State::BanTurnsBetween {
from: *r,
selected: *selected,
osd: Text::new(),
};
return EventLoopMode::InputOnly;
} }
} }
if let Some(ID::Intersection(i)) = selected { if let Some(ID::Intersection(i)) = selected {
@ -271,6 +281,43 @@ impl GUI for UI {
EventLoopMode::InputOnly EventLoopMode::InputOnly
} }
} }
State::BanTurnsBetween {
from,
ref mut selected,
ref mut osd,
} => {
ctx.canvas.handle_event(ctx.input);
if ctx.redo_mouseover() {
*selected = self.world.mouseover_something(ctx, &HashSet::new());
}
if ctx.input.key_pressed(Key::Escape, "cancel") {
self.state = State::main(ctx);
return EventLoopMode::InputOnly;
} else if let Some(ID::Road(r)) = selected {
// TODO Why do we use data and not raw here?
let (i1, i2) = (self.data.roads[&from].src_i, self.data.roads[&from].dst_i);
let (i3, i4) = (self.data.roads[r].src_i, self.data.roads[r].dst_i);
if from != *r
&& (i1 == i3 || i1 == i4 || i2 == i3 || i2 == i4)
&& ctx.input.key_pressed(Key::T, "ban turns to this road")
{
self.hints.hints.push(Hint::BanTurnsBetween(
self.raw.roads[&from].orig_id(),
self.raw.roads[r].orig_id(),
));
// There's nothing to change about our model here.
self.state = State::main(ctx);
return EventLoopMode::InputOnly;
}
}
*osd = Text::new();
ctx.input.populate_osd(osd);
EventLoopMode::InputOnly
}
} }
} }
@ -295,7 +342,7 @@ impl GUI for UI {
State::BrowsingHints(ref slider) => { State::BrowsingHints(ref slider) => {
let poly = let poly =
match slider.get().1 { match slider.get().1 {
Hint::MergeRoad(r) | Hint::DeleteRoad(r) => { Hint::MergeRoad(r) | Hint::DeleteRoad(r) | Hint::BanTurnsBetween(r, _) => {
PolyLine::new(self.raw.gps_bounds.must_convert( PolyLine::new(self.raw.gps_bounds.must_convert(
&self.raw.roads[&self.raw.find_r(*r).unwrap()].points, &self.raw.roads[&self.raw.find_r(*r).unwrap()].points,
)) ))
@ -316,6 +363,17 @@ impl GUI for UI {
slider.draw(g); slider.draw(g);
} }
State::BanTurnsBetween {
ref selected,
ref osd,
..
} => {
if let Some(id) = selected {
self.world.draw_selected(g, *id);
}
g.draw_blocking_text(osd, ezgui::BOTTOM_LEFT);
}
} }
} }
} }
@ -392,5 +450,6 @@ fn describe(hint: &Hint) -> String {
Hint::MergeRoad(_) => "MergeRoad(...)".to_string(), Hint::MergeRoad(_) => "MergeRoad(...)".to_string(),
Hint::DeleteRoad(_) => "DeleteRoad(...)".to_string(), Hint::DeleteRoad(_) => "DeleteRoad(...)".to_string(),
Hint::MergeDegenerateIntersection(_) => "MergeDegenerateIntersection(...)".to_string(), Hint::MergeDegenerateIntersection(_) => "MergeDegenerateIntersection(...)".to_string(),
Hint::BanTurnsBetween(_, _) => "BanTurnsBetween(...)".to_string(),
} }
} }

View File

@ -2,6 +2,11 @@
set -e set -e
if [ "$1" != "" ]; then
~/npm/node_modules/prettier/bin-prettier.js --write --prose-wrap=always $1;
exit
fi
# Ignore notes; they're not important # Ignore notes; they're not important
for x in `find | grep '.md$' | grep -v design/notes | grep -v TODO_ | grep -v CHANGELOG.md`; do for x in `find | grep '.md$' | grep -v design/notes | grep -v TODO_ | grep -v CHANGELOG.md`; do
~/npm/node_modules/prettier/bin-prettier.js --write --prose-wrap=always $x; ~/npm/node_modules/prettier/bin-prettier.js --write --prose-wrap=always $x;

View File

@ -87,6 +87,10 @@ pub fn make_half_map(
parking_lane_fwd: r.parking_lane_fwd, parking_lane_fwd: r.parking_lane_fwd,
parking_lane_back: r.parking_lane_back, parking_lane_back: r.parking_lane_back,
}; };
for stable_id in &r.override_turn_restrictions_to {
road.turn_restrictions
.push(("no_anything".to_string(), road_id_mapping[stable_id]));
}
for lane in &r.lane_specs { for lane in &r.lane_specs {
let id = LaneID(half_map.lanes.len()); let id = LaneID(half_map.lanes.len());

View File

@ -32,6 +32,7 @@ pub struct Road {
pub osm_tags: BTreeMap<String, String>, pub osm_tags: BTreeMap<String, String>,
pub parking_lane_fwd: bool, pub parking_lane_fwd: bool,
pub parking_lane_back: bool, pub parking_lane_back: bool,
pub override_turn_restrictions_to: Vec<StableRoadID>,
} }
impl Road { impl Road {
@ -165,6 +166,7 @@ impl InitialMap {
osm_tags: r.osm_tags.clone(), osm_tags: r.osm_tags.clone(),
parking_lane_fwd: r.parking_lane_fwd, parking_lane_fwd: r.parking_lane_fwd,
parking_lane_back: r.parking_lane_back, parking_lane_back: r.parking_lane_back,
override_turn_restrictions_to: Vec::new(),
}, },
); );
} }
@ -345,6 +347,18 @@ impl InitialMap {
self.merge_degenerate_intersection(i, timer); self.merge_degenerate_intersection(i, timer);
} }
} }
Hint::BanTurnsBetween(orig1, orig2) => {
if let Some(r1) = raw.find_r(*orig1) {
if let Some(r2) = raw.find_r(*orig2) {
self.roads
.get_mut(&r1)
.unwrap()
.override_turn_restrictions_to
.push(r2);
cnt += 1;
}
}
}
} }
} }
timer.note(format!("Applied {} of {} hints", cnt, hints.hints.len())); timer.note(format!("Applied {} of {} hints", cnt, hints.hints.len()));
@ -395,6 +409,7 @@ pub enum Hint {
MergeRoad(raw_data::OriginalRoad), MergeRoad(raw_data::OriginalRoad),
DeleteRoad(raw_data::OriginalRoad), DeleteRoad(raw_data::OriginalRoad),
MergeDegenerateIntersection(raw_data::OriginalIntersection), MergeDegenerateIntersection(raw_data::OriginalIntersection),
BanTurnsBetween(raw_data::OriginalRoad, raw_data::OriginalRoad),
} }
pub struct LaneSpec { pub struct LaneSpec {

View File

@ -526,7 +526,7 @@ fn does_turn_pass_restrictions(
// //
// Strip off time restrictions (like " @ (Mo-Fr 06:00-09:00, 15:00-18:30)") // Strip off time restrictions (like " @ (Mo-Fr 06:00-09:00, 15:00-18:30)")
match restriction.split(" @ ").next().unwrap() { match restriction.split(" @ ").next().unwrap() {
"no_left_turn" | "no_right_turn" | "no_straight_on" | "no_u_turn" => { "no_left_turn" | "no_right_turn" | "no_straight_on" | "no_u_turn" | "no_anything" => {
if dst == *to { if dst == *to {
return false; return false;
} }