Forge two-way streets from existing single-lane one-ways, through the power of narrow lane widths
@@ -63,13 +63,44 @@ pub fn handle_world_outcome(
let mut edits = app.map.get_edits().clone();
edits.commands.push(app.map.edit_road_cmd(r, |new| {
+ // TODO Refactor transformations like this into raw_map. Ungap's maybe_add_bike_lanes is another!
+
let oneway_dir = LaneSpec::oneway_for_driving(&new.lanes_ltr);
- let num_driving_lanes = new
+ let mut num_driving_lanes = new
.lanes_ltr
.iter()
.filter(|lane| lane.lt == LaneType::Driving)
.count();
+ // Pre-processing: if it's one-way backwards and there's only one driving lane,
+ // split it into two narrow pieces
+ if oneway_dir == Some(Direction::Back) && num_driving_lanes == 1 {
+ // TODO If there's parking, use that
+ let idx = new
+ .lanes_ltr
+ .iter()
+ .position(|x| x.lt == LaneType::Driving)
+ .unwrap();
+ new.lanes_ltr[idx].width *= 0.5;
+ new.lanes_ltr.insert(idx, new.lanes_ltr[idx].clone());
+ num_driving_lanes = 2;
+ }
+ // And undo the above
+ if oneway_dir == None && num_driving_lanes == 2 {
+ let idx = new
+ .lanes_ltr
+ .iter()
+ .position(|x| x.lt == LaneType::Driving)
+ .unwrap();
+ // Is it super narrow?
+ // TODO Potentially brittle. SERVICE_ROAD_LANE_THICKNESS is 1.5,
+ // NORMAL_LANE_THICKNESS is 2.5. Half of either one is less than 1.5.
+ if new.lanes_ltr[idx].width < Distance::meters(1.5) {
+ new.lanes_ltr.remove(idx);
+ new.lanes_ltr[idx].width *= 2.0;
+ }
+ }
+
let mut driving_lanes_so_far = 0;
for lane in &mut new.lanes_ltr {
if lane.lt == LaneType::Driving {
@@ -80,22 +111,17 @@ pub fn handle_world_outcome(
lane.dir = Direction::Back;
}
Some(Direction::Back) => {
- // If it's one-way backwards, make it bidirectional (if there are
- // enough lanes) or flip the direction otherwise
- if num_driving_lanes == 1 {
- lane.dir = Direction::Fwd;
- } else {
- // Split the directions down the middle
- if (driving_lanes_so_far as f64) / (num_driving_lanes as f64)
- <= 0.5
+ // If it's one-way backwards, make it bidirectional. Split the
+ // directions down the middle
+ if (driving_lanes_so_far as f64) / (num_driving_lanes as f64) <= 0.5
{
lane.dir = leftmost_dir;
} else {
lane.dir = leftmost_dir.opposite();
}
}
- }
None => {
+ // TODO If it's narrow...
// If it's bidirectional, make it one-way
lane.dir = Direction::Fwd;
}
