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
}
}
},
{
"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": [
@ -341,7 +365,7 @@
"latitude": 47.647500000184834
},
"pt2": {
"longitude": -122.30462539972673,
"longitude": -122.30462539972672,
"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
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-->
@ -176,6 +176,9 @@ before the final Map: InitialMap and HalfMap.
lanes, speed limit, or some other reason to preserve the intersection.
- The hint to override parking on a road: the blockface dataset is inaccurate
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

View File

@ -28,6 +28,11 @@ enum State {
osd: Text,
},
BrowsingHints(WarpingItemSlider<Hint>),
BanTurnsBetween {
from: StableRoadID,
selected: Option<ID>,
osd: Text,
},
}
impl State {
@ -95,13 +100,6 @@ impl GUI for UI {
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 {
txt.push(format!(
"[red:{}] is {} long",
@ -169,7 +167,9 @@ impl GUI for UI {
.iter()
.filter_map(|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]
}
Hint::MergeDegenerateIntersection(i) => {
@ -240,6 +240,16 @@ impl GUI for UI {
&mut Timer::new("override parking"),
);
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 {
@ -271,6 +281,43 @@ impl GUI for UI {
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) => {
let poly =
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(
&self.raw.roads[&self.raw.find_r(*r).unwrap()].points,
))
@ -316,6 +363,17 @@ impl GUI for UI {
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::DeleteRoad(_) => "DeleteRoad(...)".to_string(),
Hint::MergeDegenerateIntersection(_) => "MergeDegenerateIntersection(...)".to_string(),
Hint::BanTurnsBetween(_, _) => "BanTurnsBetween(...)".to_string(),
}
}

View File

@ -2,6 +2,11 @@
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
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;

View File

@ -87,6 +87,10 @@ pub fn make_half_map(
parking_lane_fwd: r.parking_lane_fwd,
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 {
let id = LaneID(half_map.lanes.len());

View File

@ -32,6 +32,7 @@ pub struct Road {
pub osm_tags: BTreeMap<String, String>,
pub parking_lane_fwd: bool,
pub parking_lane_back: bool,
pub override_turn_restrictions_to: Vec<StableRoadID>,
}
impl Road {
@ -165,6 +166,7 @@ impl InitialMap {
osm_tags: r.osm_tags.clone(),
parking_lane_fwd: r.parking_lane_fwd,
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);
}
}
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()));
@ -395,6 +409,7 @@ pub enum Hint {
MergeRoad(raw_data::OriginalRoad),
DeleteRoad(raw_data::OriginalRoad),
MergeDegenerateIntersection(raw_data::OriginalIntersection),
BanTurnsBetween(raw_data::OriginalRoad, raw_data::OriginalRoad),
}
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)")
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 {
return false;
}