mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 09:24:26 +03:00
adding a new hint for extra turn restrictions
This commit is contained in:
parent
bf5c45cd72
commit
574e30b3d8
@ -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
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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());
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user