change turn group representation to prepare for cross-map edits

This commit is contained in:
Dustin Carlino 2020-03-03 17:20:56 -08:00
parent 9525b11b20
commit 0f5ab2f410
7 changed files with 104 additions and 109 deletions

View File

@ -103,26 +103,26 @@ d7e630552af64d49ff58c92a55e09356 data/input/raw_maps/23rd.bin
5d48031ff3b288ecb22bd2a96809a0ab data/input/polygons/ballard.poly 5d48031ff3b288ecb22bd2a96809a0ab data/input/polygons/ballard.poly
0304847f270859fcfc19c8ca122ed793 data/input/polygons/23rd.poly 0304847f270859fcfc19c8ca122ed793 data/input/polygons/23rd.poly
54f5f16e5ec925cb29b4d1405a89ef94 data/input/polygons/downtown.poly 54f5f16e5ec925cb29b4d1405a89ef94 data/input/polygons/downtown.poly
ecfe0b11fe0641a2c092a42ffd488ef6 data/input/screenshots/montlake/02x05_i124.png e510730c57bcc1ed6671cc95ea257585 data/input/screenshots/montlake/02x05_i124.png
37321854140b6b4d19d29e0dcc7b4ed3 data/input/screenshots/montlake/01x06_i26.png 681c82d0767ea71a55ce183c14e816c0 data/input/screenshots/montlake/01x06_i26.png
e105cbb1ee418bfbe469bd8e9afd6da8 data/input/screenshots/montlake/01x01_i19.png 1717bfb53aa375bd3359de6e7db860ff data/input/screenshots/montlake/01x01_i19.png
64ab71bd2defd98dc82874d7dd3df937 data/input/screenshots/montlake/MANIFEST 63a920add8f7d4da115ea56e52677d9b data/input/screenshots/montlake/MANIFEST
39a82b3b5162e86c6bebeb6a7b92dc38 data/input/screenshots/montlake/03x06_i27.png 0ece3a6bc65266c96c10ecb11f6738f9 data/input/screenshots/montlake/03x06_i27.png
54fb9ae739cd4e30a71f478c688987e2 data/input/screenshots/montlake/02x03_i1.png 19394b3b1c0208244cfdcac805414325 data/input/screenshots/montlake/02x03_i1.png
82a93b7ac0e086358944b7b148f0dd2e data/input/screenshots/montlake/02x04_i25.png 612d5c710d77ae2fcd639fc8c1716dac data/input/screenshots/montlake/02x04_i25.png
6154d0d36f9c6ef7bb492f6f3d040a87 data/input/screenshots/montlake/02x02_i289.png 6154d0d36f9c6ef7bb492f6f3d040a87 data/input/screenshots/montlake/02x02_i289.png
9fd973825f6c4a31081bd116d5f758e8 data/input/screenshots/montlake/03x02_i8.png 88423d807e30c66547d7d0bf7dffd788 data/input/screenshots/montlake/03x02_i8.png
7cb13279a40e88500bf56a27649a6ac9 data/input/screenshots/montlake/01x04_i31.png 920eaf9c480d89e68234b399fecce33a data/input/screenshots/montlake/01x04_i31.png
dc10dd940c4f3b41086f7b40983ba25f data/input/screenshots/montlake/combine.sh dc10dd940c4f3b41086f7b40983ba25f data/input/screenshots/montlake/combine.sh
3f22b63ebc3736c1ac08da2a128fcba5 data/input/screenshots/montlake/03x01_i0.png d6db692ef068337e5758de7be568f885 data/input/screenshots/montlake/03x01_i0.png
b4d83fc0ee525b9961c210ba0d945c31 data/input/screenshots/montlake/01x03_i4.png 3ab7c23b54d9bfeac190fc3d5f0c75b1 data/input/screenshots/montlake/01x03_i4.png
568880dceb44433f02fa038d337ea491 data/input/screenshots/montlake/01x02_i20.png 924811cfa5520f1fd3da1ef06b1a5c0c data/input/screenshots/montlake/01x02_i20.png
8061eddd26929189861c6dffbdb92f06 data/input/screenshots/montlake/03x04_i112.png b1929464274d34c3bce5040821f7869d data/input/screenshots/montlake/03x04_i112.png
44557d69a3e330ac11087de204385c1c data/input/screenshots/montlake/03x03_i59.png 94acbdf117cd18491f8360754089da2b data/input/screenshots/montlake/03x03_i59.png
df80ffb7a65491cd2e674facce0ab565 data/input/screenshots/montlake/02x01_i24.png 8b5c174350141b6411fa2f0dcb802b34 data/input/screenshots/montlake/02x01_i24.png
f1f167f53f21d6ba4406e51a9e97b262 data/input/screenshots/montlake/03x05_i2.png 0cfba587f63ae66e59dc6961e4aab07b data/input/screenshots/montlake/03x05_i2.png
4125185f97bcf0b6c2e9a3392db45023 data/input/screenshots/montlake/02x06_i85.png c9958a511d116460d48ff0a4093a7623 data/input/screenshots/montlake/02x06_i85.png
2e4d121b40cc023d1ccc0222a6e5dd39 data/input/screenshots/montlake/01x05_i40.png 6c894ae6c793e96056493524254ea28d data/input/screenshots/montlake/01x05_i40.png
129b460f56f5eb41cab3bfd70fb5fde9 data/input/sidewalks.bin 129b460f56f5eb41cab3bfd70fb5fde9 data/input/sidewalks.bin
5a7e5b1d68b6e4d1637731d1e1c54ccb data/input/google_transit_2018_18_08/stop_times.txt 5a7e5b1d68b6e4d1637731d1e1c54ccb data/input/google_transit_2018_18_08/stop_times.txt
3fce7b5925679b421e5fb85966dbb5cd data/input/google_transit_2018_18_08/routes.txt 3fce7b5925679b421e5fb85966dbb5cd data/input/google_transit_2018_18_08/routes.txt
@ -204,13 +204,13 @@ a5e849fa8883569519976ebfef3ae269 data/system/night_colors.json
517a360397bbb5a7573c2558e78fa4ea data/system/fonts/DejaVuSans.ttf 517a360397bbb5a7573c2558e78fa4ea data/system/fonts/DejaVuSans.ttf
e07df86cef2e721115583d61d1fb68a6 data/system/fonts/Roboto-Bold.ttf e07df86cef2e721115583d61d1fb68a6 data/system/fonts/Roboto-Bold.ttf
11eabca2251325cfc5589c9c6fb57b46 data/system/fonts/Roboto-Regular.ttf 11eabca2251325cfc5589c9c6fb57b46 data/system/fonts/Roboto-Regular.ttf
543ccb8d97828ad8080f8e25c399dcaf data/system/maps/huge_seattle.bin bc26d5fd443d669cfd0456a8a0968b1a data/system/maps/huge_seattle.bin
80fc7213d29f9425c80d1e2f22113aa6 data/system/maps/ballard.bin 2fddde4d3516302952844cdb54a99377 data/system/maps/ballard.bin
15c7082403bee91a2431811f00bde464 data/system/maps/downtown.bin 6954ccbec2c8ccaef6f97795b6970437 data/system/maps/downtown.bin
9e6e6d2d1b7aa17b8a13cd074f4aeaf4 data/system/maps/caphill.bin 6e4f5d242991f28d88e6b9b48dd926c1 data/system/maps/caphill.bin
e1f6f6c288395293378b65f7cd995d1b data/system/maps/montlake.bin b0317f387d3c6f5e6459a920bd7d8db9 data/system/maps/montlake.bin
d5f488eeea910f2c43c6829e98df4430 data/system/maps/intl_district.bin 94883e1fac1efa4d87672468e58b157a data/system/maps/intl_district.bin
0b11365a2af8ebdda5a5d4a3f4d20daf data/system/maps/23rd.bin 4293cd436373faecc82bf1ae652bcb58 data/system/maps/23rd.bin
d71169fc1789707c403e70e6f2cc27d4 data/system/synthetic_maps/signal_double.json d71169fc1789707c403e70e6f2cc27d4 data/system/synthetic_maps/signal_double.json
407cf814c6b5c73b5e1857529b94a204 data/system/synthetic_maps/signal_single.json 407cf814c6b5c73b5e1857529b94a204 data/system/synthetic_maps/signal_single.json
7e3b93d87b5c6cf4788122e7f65ecac1 data/system/synthetic_maps/signal_fan_in.json 7e3b93d87b5c6cf4788122e7f65ecac1 data/system/synthetic_maps/signal_fan_in.json
@ -221,9 +221,9 @@ f9f0a109966db097617a13122ecaa6f3 data/system/scenarios/downtown/weekday.bin
dd54763cfda7fce4c401ae122c6daf57 data/system/scenarios/huge_seattle/weekday.bin dd54763cfda7fce4c401ae122c6daf57 data/system/scenarios/huge_seattle/weekday.bin
47dea892a1c4331da02494d15ce02a02 data/system/scenarios/caphill/weekday.bin 47dea892a1c4331da02494d15ce02a02 data/system/scenarios/caphill/weekday.bin
7d6a8e8f5d716ce8674ed63d27f2da51 data/system/scenarios/montlake/weekday.bin 7d6a8e8f5d716ce8674ed63d27f2da51 data/system/scenarios/montlake/weekday.bin
b50d41d25ba40504df5a56945769bb27 data/system/prebaked_results/23rd/weekday.bin 5f78d73efbabf06aed28c0e80c6b6d5b data/system/prebaked_results/23rd/weekday.bin
c83401e693ea9bb2c437ecdcc33fadbf data/system/prebaked_results/signal_single/tutorial lvl1.bin 39dc5028982cc7ef40da44ec00ab1020 data/system/prebaked_results/signal_single/tutorial lvl1.bin
e8cdc329b7c10914df88ea3d4df6abd0 data/system/prebaked_results/signal_single/tutorial lvl2.bin c4f5661e5c62c0c0ccccc7c2b9f2d365 data/system/prebaked_results/signal_single/tutorial lvl2.bin
b8137879ec00add4cd2a39e8c985420f data/system/prebaked_results/montlake/car vs bike contention.bin b8137879ec00add4cd2a39e8c985420f data/system/prebaked_results/montlake/car vs bike contention.bin
029227cdea45492954e3b1666b0dc5b9 data/system/prebaked_results/montlake/weekday.bin 3cb2adbb509617b15007b92b373a8b97 data/system/prebaked_results/montlake/weekday.bin
994677ade10b0d021f3a0eb91696265c data/system/prebaked_results/montlake/car vs bus contention.bin 7f9aec66506cc24bcf7b2e74dbcf38f4 data/system/prebaked_results/montlake/car vs bus contention.bin

View File

@ -1,18 +1,18 @@
e105cbb1ee418bfbe469bd8e9afd6da8 ../data/input/screenshots/pending_montlake/01x01_i19.png 1717bfb53aa375bd3359de6e7db860ff ../data/input/screenshots/pending_montlake/01x01_i19.png
df80ffb7a65491cd2e674facce0ab565 ../data/input/screenshots/pending_montlake/02x01_i24.png 8b5c174350141b6411fa2f0dcb802b34 ../data/input/screenshots/pending_montlake/02x01_i24.png
3f22b63ebc3736c1ac08da2a128fcba5 ../data/input/screenshots/pending_montlake/03x01_i0.png d6db692ef068337e5758de7be568f885 ../data/input/screenshots/pending_montlake/03x01_i0.png
568880dceb44433f02fa038d337ea491 ../data/input/screenshots/pending_montlake/01x02_i20.png 924811cfa5520f1fd3da1ef06b1a5c0c ../data/input/screenshots/pending_montlake/01x02_i20.png
6154d0d36f9c6ef7bb492f6f3d040a87 ../data/input/screenshots/pending_montlake/02x02_i289.png 6154d0d36f9c6ef7bb492f6f3d040a87 ../data/input/screenshots/pending_montlake/02x02_i289.png
9fd973825f6c4a31081bd116d5f758e8 ../data/input/screenshots/pending_montlake/03x02_i8.png 88423d807e30c66547d7d0bf7dffd788 ../data/input/screenshots/pending_montlake/03x02_i8.png
b4d83fc0ee525b9961c210ba0d945c31 ../data/input/screenshots/pending_montlake/01x03_i4.png 3ab7c23b54d9bfeac190fc3d5f0c75b1 ../data/input/screenshots/pending_montlake/01x03_i4.png
54fb9ae739cd4e30a71f478c688987e2 ../data/input/screenshots/pending_montlake/02x03_i1.png 19394b3b1c0208244cfdcac805414325 ../data/input/screenshots/pending_montlake/02x03_i1.png
44557d69a3e330ac11087de204385c1c ../data/input/screenshots/pending_montlake/03x03_i59.png 94acbdf117cd18491f8360754089da2b ../data/input/screenshots/pending_montlake/03x03_i59.png
7cb13279a40e88500bf56a27649a6ac9 ../data/input/screenshots/pending_montlake/01x04_i31.png 920eaf9c480d89e68234b399fecce33a ../data/input/screenshots/pending_montlake/01x04_i31.png
82a93b7ac0e086358944b7b148f0dd2e ../data/input/screenshots/pending_montlake/02x04_i25.png 612d5c710d77ae2fcd639fc8c1716dac ../data/input/screenshots/pending_montlake/02x04_i25.png
8061eddd26929189861c6dffbdb92f06 ../data/input/screenshots/pending_montlake/03x04_i112.png b1929464274d34c3bce5040821f7869d ../data/input/screenshots/pending_montlake/03x04_i112.png
2e4d121b40cc023d1ccc0222a6e5dd39 ../data/input/screenshots/pending_montlake/01x05_i40.png 6c894ae6c793e96056493524254ea28d ../data/input/screenshots/pending_montlake/01x05_i40.png
ecfe0b11fe0641a2c092a42ffd488ef6 ../data/input/screenshots/pending_montlake/02x05_i124.png e510730c57bcc1ed6671cc95ea257585 ../data/input/screenshots/pending_montlake/02x05_i124.png
f1f167f53f21d6ba4406e51a9e97b262 ../data/input/screenshots/pending_montlake/03x05_i2.png 0cfba587f63ae66e59dc6961e4aab07b ../data/input/screenshots/pending_montlake/03x05_i2.png
37321854140b6b4d19d29e0dcc7b4ed3 ../data/input/screenshots/pending_montlake/01x06_i26.png 681c82d0767ea71a55ce183c14e816c0 ../data/input/screenshots/pending_montlake/01x06_i26.png
4125185f97bcf0b6c2e9a3392db45023 ../data/input/screenshots/pending_montlake/02x06_i85.png c9958a511d116460d48ff0a4093a7623 ../data/input/screenshots/pending_montlake/02x06_i85.png
39a82b3b5162e86c6bebeb6a7b92dc38 ../data/input/screenshots/pending_montlake/03x06_i27.png 0ece3a6bc65266c96c10ecb11f6738f9 ../data/input/screenshots/pending_montlake/03x06_i27.png

View File

@ -131,7 +131,7 @@ impl State for TrafficSignalEditor {
TurnPriority::Banned => { TurnPriority::Banned => {
if phase.could_be_protected(id, &orig_signal.turn_groups) { if phase.could_be_protected(id, &orig_signal.turn_groups) {
Some(TurnPriority::Protected) Some(TurnPriority::Protected)
} else if id.crosswalk.is_some() { } else if id.crosswalk {
None None
} else { } else {
Some(TurnPriority::Yield) Some(TurnPriority::Yield)
@ -139,7 +139,7 @@ impl State for TrafficSignalEditor {
} }
TurnPriority::Yield => Some(TurnPriority::Banned), TurnPriority::Yield => Some(TurnPriority::Banned),
TurnPriority::Protected => { TurnPriority::Protected => {
if id.crosswalk.is_some() { if id.crosswalk {
Some(TurnPriority::Banned) Some(TurnPriority::Banned)
} else { } else {
Some(TurnPriority::Yield) Some(TurnPriority::Yield)
@ -155,12 +155,7 @@ impl State for TrafficSignalEditor {
pri pri
), ),
) { ) {
phase.edit_group( phase.edit_group(&orig_signal.turn_groups[&id], pri);
&orig_signal.turn_groups[&id],
pri,
&orig_signal.turn_groups,
&app.primary.map,
);
self.command_stack.push(orig_signal.clone()); self.command_stack.push(orig_signal.clone());
self.redo_stack.clear(); self.redo_stack.clear();
self.top_panel = make_top_panel(true, false, ctx); self.top_panel = make_top_panel(true, false, ctx);
@ -275,16 +270,16 @@ impl State for TrafficSignalEditor {
self.composite.draw(g); self.composite.draw(g);
self.top_panel.draw(g); self.top_panel.draw(g);
if let Some(id) = self.group_selected { if let Some(id) = self.group_selected {
let osd = if id.crosswalk.is_some() { let osd = if id.crosswalk {
Text::from(Line(format!( Text::from(Line(format!(
"Crosswalk across {}", "Crosswalk across {}",
app.primary.map.get_r(id.from).get_name() app.primary.map.get_r(id.from.id).get_name()
))) )))
} else { } else {
Text::from(Line(format!( Text::from(Line(format!(
"Turn from {} to {}", "Turn from {} to {}",
app.primary.map.get_r(id.from).get_name(), app.primary.map.get_r(id.from.id).get_name(),
app.primary.map.get_r(id.to).get_name() app.primary.map.get_r(id.to.id).get_name()
))) )))
}; };
CommonState::draw_custom_osd(g, app, osd); CommonState::draw_custom_osd(g, app, osd);
@ -536,7 +531,7 @@ fn edit_entire_signal(app: &App, i: IntersectionID, suspended_sim: Sim) -> Box<d
let editor = state.downcast_mut::<TrafficSignalEditor>().unwrap(); let editor = state.downcast_mut::<TrafficSignalEditor>().unwrap();
let orig_signal = app.primary.map.get_traffic_signal(editor.i); let orig_signal = app.primary.map.get_traffic_signal(editor.i);
let mut new_signal = orig_signal.clone(); let mut new_signal = orig_signal.clone();
if new_signal.convert_to_ped_scramble(&app.primary.map) { if new_signal.convert_to_ped_scramble() {
editor.command_stack.push(orig_signal.clone()); editor.command_stack.push(orig_signal.clone());
editor.redo_stack.clear(); editor.redo_stack.clear();
editor.top_panel = make_top_panel(true, false, ctx); editor.top_panel = make_top_panel(true, false, ctx);
@ -750,7 +745,7 @@ fn check_for_missing_groups(
let num_missing = missing.len(); let num_missing = missing.len();
let mut phase = Phase::new(); let mut phase = Phase::new();
for g in missing { for g in missing {
if g.crosswalk.is_some() { if g.crosswalk {
phase.protected_groups.insert(g); phase.protected_groups.insert(g);
} else { } else {
phase.yield_groups.insert(g); phase.yield_groups.insert(g);

View File

@ -31,7 +31,7 @@ pub fn draw_signal_phase(
match signal_style { match signal_style {
TrafficSignalStyle::GroupArrows => { TrafficSignalStyle::GroupArrows => {
for g in &phase.yield_groups { for g in &phase.yield_groups {
assert!(g.crosswalk.is_none()); assert!(!g.crosswalk);
batch.push( batch.push(
yield_bg_color, yield_bg_color,
signal.turn_groups[g] signal.turn_groups[g]
@ -49,12 +49,12 @@ pub fn draw_signal_phase(
} }
let mut dont_walk = BTreeSet::new(); let mut dont_walk = BTreeSet::new();
for g in signal.turn_groups.keys() { for g in signal.turn_groups.keys() {
if g.crosswalk.is_some() { if g.crosswalk {
dont_walk.insert(g); dont_walk.insert(g);
} }
} }
for g in &phase.protected_groups { for g in &phase.protected_groups {
if g.crosswalk.is_none() { if !g.crosswalk {
batch.push( batch.push(
protected_color, protected_color,
signal.turn_groups[g] signal.turn_groups[g]
@ -87,7 +87,7 @@ pub fn draw_signal_phase(
} }
TrafficSignalStyle::Sidewalks => { TrafficSignalStyle::Sidewalks => {
for g in &phase.yield_groups { for g in &phase.yield_groups {
assert!(g.crosswalk.is_none()); assert!(!g.crosswalk);
batch.push( batch.push(
yield_bg_color, yield_bg_color,
signal.turn_groups[g] signal.turn_groups[g]
@ -104,8 +104,13 @@ pub fn draw_signal_phase(
); );
} }
for g in &phase.protected_groups { for g in &phase.protected_groups {
if let Some(t) = g.crosswalk { if g.crosswalk {
make_crosswalk(batch, app.primary.map.get_t(t), &app.primary.map, &app.cs); make_crosswalk(
batch,
app.primary.map.get_t(signal.turn_groups[g].members[0]),
&app.primary.map,
&app.cs,
);
} else { } else {
batch.push( batch.push(
protected_color, protected_color,

View File

@ -38,6 +38,7 @@ pub struct Intersection {
pub incoming_lanes: Vec<LaneID>, pub incoming_lanes: Vec<LaneID>,
pub outgoing_lanes: Vec<LaneID>, pub outgoing_lanes: Vec<LaneID>,
// TODO Maybe DirectedRoadIDs
pub roads: BTreeSet<RoadID>, pub roads: BTreeSet<RoadID>,
} }

View File

@ -213,7 +213,7 @@ impl ControlTrafficSignal {
let straight = turn_groups let straight = turn_groups
.values() .values()
.find(|g| g.turn_type == TurnType::Straight)?; .find(|g| g.turn_type == TurnType::Straight)?;
let (north, south) = (straight.id.from, straight.id.to); let (north, south) = (straight.id.from.id, straight.id.to.id);
let mut roads = map.get_i(i).roads.clone(); let mut roads = map.get_i(i).roads.clone();
roads.remove(&north); roads.remove(&north);
roads.remove(&south); roads.remove(&south);
@ -430,10 +430,10 @@ impl ControlTrafficSignal {
let mut phase = Phase::new(); let mut phase = Phase::new();
for group in turn_groups.values() { for group in turn_groups.values() {
if group.turn_type == TurnType::Crosswalk { if group.turn_type == TurnType::Crosswalk {
if group.id.from == adj1 || group.id.from == adj2 { if group.id.from.id == adj1 || group.id.from.id == adj2 {
phase.protected_groups.insert(group.id); phase.protected_groups.insert(group.id);
} }
} else if group.id.from == r { } else if group.id.from.id == r {
phase.yield_groups.insert(group.id); phase.yield_groups.insert(group.id);
} }
} }
@ -452,13 +452,13 @@ impl ControlTrafficSignal {
} }
// Returns true if this did anything // Returns true if this did anything
pub fn convert_to_ped_scramble(&mut self, map: &Map) -> bool { pub fn convert_to_ped_scramble(&mut self) -> bool {
let orig = self.clone(); let orig = self.clone();
let mut all_walk_phase = Phase::new(); let mut all_walk_phase = Phase::new();
for g in self.turn_groups.values() { for g in self.turn_groups.values() {
if g.turn_type == TurnType::Crosswalk { if g.turn_type == TurnType::Crosswalk {
all_walk_phase.edit_group(g, TurnPriority::Protected, &self.turn_groups, map); all_walk_phase.edit_group(g, TurnPriority::Protected);
} }
} }
@ -541,23 +541,15 @@ impl Phase {
} }
} }
pub fn edit_group( pub fn edit_group(&mut self, g: &TurnGroup, pri: TurnPriority) {
&mut self,
g: &TurnGroup,
pri: TurnPriority,
turn_groups: &BTreeMap<TurnGroupID, TurnGroup>,
map: &Map,
) {
let mut ids = vec![g.id]; let mut ids = vec![g.id];
if g.turn_type == TurnType::Crosswalk { if g.turn_type == TurnType::Crosswalk {
for t in &map.get_t(g.id.crosswalk.unwrap()).other_crosswalk_ids { ids.push(TurnGroupID {
ids.push( from: g.id.to,
*turn_groups to: g.id.from,
.keys() parent: g.id.parent,
.find(|id| id.crosswalk == Some(*t)) crosswalk: true,
.unwrap(), });
);
}
} }
for id in ids { for id in ids {
self.protected_groups.remove(&id); self.protected_groups.remove(&id);
@ -599,7 +591,7 @@ fn make_phases(
for (roads, turn_type, protected) in specs.into_iter() { for (roads, turn_type, protected) in specs.into_iter() {
for group in turn_groups.values() { for group in turn_groups.values() {
if !roads.contains(&group.id.from) || turn_type != group.turn_type { if !roads.contains(&group.id.from.id) || turn_type != group.turn_type {
continue; continue;
} }
@ -610,8 +602,6 @@ fn make_phases(
} else { } else {
TurnPriority::Yield TurnPriority::Yield
}, },
&turn_groups,
map,
); );
} }
} }

View File

@ -1,4 +1,4 @@
use crate::{IntersectionID, LaneID, Map, RoadID}; use crate::{DirectedRoadID, IntersectionID, LaneID, Map};
use abstutil::MultiMap; use abstutil::MultiMap;
use geom::{Angle, Distance, PolyLine, Pt2D}; use geom::{Angle, Distance, PolyLine, Pt2D};
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
@ -114,13 +114,14 @@ impl Turn {
} }
} }
// One road usually has 4 crosswalks, each a singleton TurnGroup. We need all of the information
// here to keep each crosswalk separate.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct TurnGroupID { pub struct TurnGroupID {
pub from: RoadID, pub from: DirectedRoadID,
pub to: RoadID, pub to: DirectedRoadID,
// If this is true, there's only one member. There are separate TurnGroups for each side of a pub parent: IntersectionID,
// crosswalk! The TurnID is embedded here so the two crosswalks have different IDs. pub crosswalk: bool,
pub crosswalk: Option<TurnID>,
} }
// TODO Unclear how this plays with different lane types // TODO Unclear how this plays with different lane types
@ -138,17 +139,18 @@ pub struct TurnGroup {
impl TurnGroup { impl TurnGroup {
pub(crate) fn for_i(i: IntersectionID, map: &Map) -> BTreeMap<TurnGroupID, TurnGroup> { pub(crate) fn for_i(i: IntersectionID, map: &Map) -> BTreeMap<TurnGroupID, TurnGroup> {
let mut results = BTreeMap::new(); let mut results = BTreeMap::new();
let mut groups: MultiMap<(RoadID, RoadID), TurnID> = MultiMap::new(); let mut groups: MultiMap<(DirectedRoadID, DirectedRoadID), TurnID> = MultiMap::new();
for turn in map.get_turns_in_intersection(i) { for turn in map.get_turns_in_intersection(i) {
let from = map.get_l(turn.id.src).parent; let from = map.get_l(turn.id.src).get_directed_parent(map);
let to = map.get_l(turn.id.dst).parent; let to = map.get_l(turn.id.dst).get_directed_parent(map);
match turn.turn_type { match turn.turn_type {
TurnType::SharedSidewalkCorner => {} TurnType::SharedSidewalkCorner => {}
TurnType::Crosswalk => { TurnType::Crosswalk => {
let id = TurnGroupID { let id = TurnGroupID {
from, from,
to, to,
crosswalk: Some(turn.id), parent: i,
crosswalk: true,
}; };
results.insert( results.insert(
id, id,
@ -193,7 +195,8 @@ impl TurnGroup {
let id = TurnGroupID { let id = TurnGroupID {
from, from,
to, to,
crosswalk: None, parent: i,
crosswalk: false,
}; };
results.insert( results.insert(
id, id,
@ -214,8 +217,8 @@ impl TurnGroup {
// Polyline points FROM intersection // Polyline points FROM intersection
pub fn src_center_and_width(&self, map: &Map) -> (PolyLine, Distance) { pub fn src_center_and_width(&self, map: &Map) -> (PolyLine, Distance) {
let r = map.get_r(self.id.from); let r = map.get_r(self.id.from.id);
let dir = r.dir_and_offset(self.members[0].src).0; let dir = self.id.from.forwards;
// Points towards the intersection // Points towards the intersection
let pl = if dir { let pl = if dir {
r.get_current_center(map) r.get_current_center(map)
@ -242,11 +245,8 @@ impl TurnGroup {
let pl = pl.shift_right((leftmost + rightmost) / 2.0).unwrap(); let pl = pl.shift_right((leftmost + rightmost) / 2.0).unwrap();
// Flip direction, so we point away from the intersection // Flip direction, so we point away from the intersection
let pl = if self let pl = if self.id.crosswalk
.id && map.get_l(self.members[0].src).src_i == self.members[0].parent
.crosswalk
.map(|t| map.get_l(t.src).src_i == t.parent)
.unwrap_or(false)
{ {
pl pl
} else { } else {
@ -276,7 +276,11 @@ impl TurnGroup {
} }
} }
fn turn_group_geom(polylines: Vec<&PolyLine>, from: RoadID, to: RoadID) -> PolyLine { fn turn_group_geom(
polylines: Vec<&PolyLine>,
from: DirectedRoadID,
to: DirectedRoadID,
) -> PolyLine {
let num_pts = polylines[0].points().len(); let num_pts = polylines[0].points().len();
for pl in &polylines { for pl in &polylines {
if num_pts != pl.points().len() { if num_pts != pl.points().len() {