Skip to content

Commit

Permalink
Fix lane geometry after changing the number of lanes. #597
Browse files Browse the repository at this point in the history
  • Loading branch information
dabreegster committed Apr 9, 2021
1 parent 584c1be commit 14609ab
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 75 deletions.
15 changes: 5 additions & 10 deletions game/src/edit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -684,26 +684,21 @@ pub fn apply_map_edits(ctx: &mut EventCtx, app: &mut App, edits: MapEdits) {
DrawMap::regenerate_unzoomed_layer(&app.primary.map, &app.cs, ctx, &mut timer);
}

for l in lanes_deleted {
app.primary.draw_map.delete_lane(l);
}

for r in roads_changed {
let road = app.primary.map.get_r(r);
app.primary.draw_map.roads[r.0].clear_rendering();

// An edit to one lane potentially affects markings in all lanes in the same road, because
// of one-way markings, driving lines, etc.
for l in road.all_lanes() {
app.primary
.draw_map
.lanes
.get_mut(&l)
.unwrap()
.clear_rendering();
app.primary.draw_map.create_lane(l, &app.primary.map);
}
}

for l in lanes_deleted {
app.primary.draw_map.delete_lane(l);
}

for t in turns_deleted {
modified_intersections.insert(t.parent);
}
Expand Down
9 changes: 9 additions & 0 deletions map_gui/src/render/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,15 @@ impl DrawMap {
batch
}

pub fn create_lane(&mut self, l: LaneID, map: &Map) {
let draw = DrawLane::new(map.get_l(l), map);
let item_id = self
.quadtree
.insert_with_box(draw.get_id(), draw.get_outline(map).get_bounds().as_bbox());
self.lane_ids.insert(l, item_id);
self.lanes.insert(l, draw);
}

pub fn delete_lane(&mut self, l: LaneID) {
self.lanes.remove(&l).unwrap();
let item_id = self.lane_ids.remove(&l).unwrap();
Expand Down
36 changes: 33 additions & 3 deletions map_model/src/edits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use geom::{Speed, Time};

pub use self::perma::PermanentMapEdits;
use crate::make::initial::lane_specs::get_lane_specs_ltr;
use crate::make::initial::LaneSpec;
use crate::{
connectivity, AccessRestrictions, BusRouteID, ControlStopSign, ControlTrafficSignal, Direction,
IntersectionID, IntersectionType, LaneID, LaneType, Map, MapConfig, PathConstraints,
Expand Down Expand Up @@ -477,6 +478,12 @@ fn modify_road_width(
let before = map.roads[r.0].lanes_ltr.len();
let after = lanes_ltr.len();

// Tell the UI to delete all of the old lanes, then recreate whatever ones survived or were
// created. Even lanes not directly modified will have their geometry shift.
for (l, _, _) in map.roads[r.0].lanes_ltr() {
effects.deleted_lanes.insert(l);
}

if after < before {
// Same as the normal case...
let road = &mut map.roads[r.0];
Expand Down Expand Up @@ -504,8 +511,31 @@ fn modify_road_width(
// TODO Adding lanes
}

// TODO We need to recalculate the road center line, all of the lane geometry, the intersection
// geometry...
// road.center_pts doesn't need to change; we'll keep the true physical center of the road and
// build around it.

// Recalculate lane geometry.
let mut lane_specs_ltr = Vec::new();
let mut lane_ids = Vec::new();
for (id, dir, lt) in map.get_r(r).lanes_ltr() {
lane_specs_ltr.push(LaneSpec {
lt,
dir,
width: map.get_l(id).width,
});
lane_ids.push(id);
}
let mut id_counter = 0;
for (new_lane, id) in map
.get_r(r)
.create_lanes(lane_specs_ltr, &mut id_counter)
.into_iter()
.zip(lane_ids)
{
map.lanes.get_mut(&id).unwrap().lane_center_pts = new_lane.lane_center_pts;
}

// TODO Recalculate intersection geometry.

// TODO We need to update buildings, bus stops, and parking lots -- they may refer to an old
// ID.
Expand Down Expand Up @@ -576,7 +606,7 @@ impl Map {
edits.save(self);
}

/// Returns (roads_changed, lanes_deleted, turns_deleted, turns_added, modified_intersections)
/// Returns (changed_roads, deleted_lanes, deleted_turns, added_turns, changed_intersections)
pub fn must_apply_edits(
&mut self,
new_edits: MapEdits,
Expand Down
2 changes: 1 addition & 1 deletion map_model/src/make/initial/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use abstutil::{Tags, Timer};
use geom::{Bounds, Circle, Distance, PolyLine, Polygon, Pt2D};

pub use self::geometry::intersection_polygon;
use crate::make::initial::lane_specs::LaneSpec;
pub use crate::make::initial::lane_specs::LaneSpec;
use crate::raw::{OriginalRoad, RawMap, RawRoad};
use crate::{osm, IntersectionType, MapConfig};

Expand Down
70 changes: 9 additions & 61 deletions map_model/src/make/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use crate::pathfind::Pathfinder;
use crate::raw::{OriginalRoad, RawMap};
use crate::{
connectivity, osm, AccessRestrictions, Area, AreaID, AreaType, ControlStopSign,
ControlTrafficSignal, Direction, Intersection, IntersectionID, IntersectionType, Lane, LaneID,
Map, MapEdits, Movement, PathConstraints, Position, Road, RoadID, RoutingParams, Turn, Zone,
ControlTrafficSignal, Intersection, IntersectionID, IntersectionType, Lane, LaneID, Map,
MapEdits, Movement, PathConstraints, Position, Road, RoadID, RoutingParams, Turn, Zone,
};

mod bridges;
Expand Down Expand Up @@ -99,7 +99,7 @@ impl Map {
}

timer.start_iter("expand roads to lanes", initial_map.roads.len());
for r in initial_map.roads.values() {
for (_, r) in initial_map.roads {
timer.next();

let road_id = road_id_mapping[&r.id];
Expand Down Expand Up @@ -137,7 +137,7 @@ impl Map {
.collect(),
orig_id: r.id,
lanes_ltr: Vec::new(),
center_pts: r.trimmed_center_pts.clone(),
center_pts: r.trimmed_center_pts,
src_i: i1,
dst_i: i2,
speed_limit: Speed::ZERO,
Expand All @@ -159,65 +159,13 @@ impl Map {
road.speed_limit = road.speed_limit_from_osm();
road.access_restrictions = road.access_restrictions_from_osm();

let mut total_back_width = Distance::ZERO;
for lane in &r.lane_specs_ltr {
if lane.dir == Direction::Back {
total_back_width += lane.width;
}
for lane in road.create_lanes(r.lane_specs_ltr, &mut map.lane_id_counter) {
map.intersections[lane.src_i.0].outgoing_lanes.push(lane.id);
map.intersections[lane.dst_i.0].incoming_lanes.push(lane.id);
road.lanes_ltr.push((lane.id, lane.dir, lane.lane_type));
map.lanes.insert(lane.id, lane);
}
// TODO Maybe easier to use the road's "yellow center line" and shift left/right from
// there.
let road_left_pts = road
.center_pts
.shift_left(r.half_width)
.unwrap_or_else(|_| road.center_pts.clone());

let mut width_so_far = Distance::ZERO;
for lane in &r.lane_specs_ltr {
let id = LaneID(map.lane_id_counter);
map.lane_id_counter += 1;

let (src_i, dst_i) = if lane.dir == Direction::Fwd {
(i1, i2)
} else {
(i2, i1)
};
map.intersections[src_i.0].outgoing_lanes.push(id);
map.intersections[dst_i.0].incoming_lanes.push(id);

road.lanes_ltr.push((id, lane.dir, lane.lt));

let pl =
if let Ok(pl) = road_left_pts.shift_right(width_so_far + (lane.width / 2.0)) {
pl
} else {
error!("{} geometry broken; lane not shifted!", id);
road_left_pts.clone()
};
let lane_center_pts = if lane.dir == Direction::Fwd {
pl
} else {
pl.reversed()
};
width_so_far += lane.width;

map.lanes.insert(
id,
Lane {
id,
lane_center_pts,
width: lane.width,
src_i,
dst_i,
lane_type: lane.lt,
dir: lane.dir,
parent: road_id,
bus_stops: BTreeSet::new(),
driving_blackhole: false,
biking_blackhole: false,
},
);
}
map.roads.push(road);
}

Expand Down
64 changes: 64 additions & 0 deletions map_model/src/objects/road.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::collections::BTreeSet;
use std::fmt;

use anyhow::Result;
Expand All @@ -7,6 +8,7 @@ use serde::{Deserialize, Serialize};
use abstutil::{deserialize_usize, serialize_usize, Tags};
use geom::{Distance, PolyLine, Polygon, Speed};

use crate::make::initial::LaneSpec;
use crate::raw::{OriginalRoad, RestrictionType};
use crate::{
osm, AccessRestrictions, BusStopID, DrivingSide, IntersectionID, Lane, LaneID, LaneType, Map,
Expand Down Expand Up @@ -455,6 +457,68 @@ impl Road {
pub fn is_extremely_short(&self) -> bool {
self.center_pts.length() < Distance::meters(2.0)
}

pub(crate) fn create_lanes(
&self,
lane_specs_ltr: Vec<LaneSpec>,
lane_id_counter: &mut usize,
) -> Vec<Lane> {
let mut total_back_width = Distance::ZERO;
let mut total_width = Distance::ZERO;
for lane in &lane_specs_ltr {
total_width += lane.width;
if lane.dir == Direction::Back {
total_back_width += lane.width;
}
}
// TODO Maybe easier to use the road's "yellow center line" and shift left/right from
// there.
let road_left_pts = self
.center_pts
.shift_left(total_width / 2.0)
.unwrap_or_else(|_| self.center_pts.clone());

let mut width_so_far = Distance::ZERO;
let mut lanes = Vec::new();
for lane in lane_specs_ltr {
let id = LaneID(*lane_id_counter);
*lane_id_counter += 1;

let (src_i, dst_i) = if lane.dir == Direction::Fwd {
(self.src_i, self.dst_i)
} else {
(self.dst_i, self.src_i)
};

let pl = if let Ok(pl) = road_left_pts.shift_right(width_so_far + (lane.width / 2.0)) {
pl
} else {
error!("{} geometry broken; lane not shifted!", id);
road_left_pts.clone()
};
let lane_center_pts = if lane.dir == Direction::Fwd {
pl
} else {
pl.reversed()
};
width_so_far += lane.width;

lanes.push(Lane {
id,
lane_center_pts,
width: lane.width,
src_i,
dst_i,
lane_type: lane.lt,
dir: lane.dir,
parent: self.id,
bus_stops: BTreeSet::new(),
driving_blackhole: false,
biking_blackhole: false,
});
}
lanes
}
}

// TODO All of this is kind of deprecated? During the transiton towards lanes_ltr, some pieces
Expand Down

0 comments on commit 14609ab

Please sign in to comment.