Fix lane geometry after changing the number of lanes. #597

This commit is contained in:
Dustin Carlino 2021-04-09 09:20:48 -07:00
parent 584c1be9e0
commit 14609ab157
6 changed files with 121 additions and 75 deletions

View File

@ -684,6 +684,10 @@ 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); 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 { for r in roads_changed {
let road = app.primary.map.get_r(r); let road = app.primary.map.get_r(r);
app.primary.draw_map.roads[r.0].clear_rendering(); app.primary.draw_map.roads[r.0].clear_rendering();
@ -691,19 +695,10 @@ pub fn apply_map_edits(ctx: &mut EventCtx, app: &mut App, edits: MapEdits) {
// An edit to one lane potentially affects markings in all lanes in the same road, because // An edit to one lane potentially affects markings in all lanes in the same road, because
// of one-way markings, driving lines, etc. // of one-way markings, driving lines, etc.
for l in road.all_lanes() { for l in road.all_lanes() {
app.primary app.primary.draw_map.create_lane(l, &app.primary.map);
.draw_map
.lanes
.get_mut(&l)
.unwrap()
.clear_rendering();
} }
} }
for l in lanes_deleted {
app.primary.draw_map.delete_lane(l);
}
for t in turns_deleted { for t in turns_deleted {
modified_intersections.insert(t.parent); modified_intersections.insert(t.parent);
} }

View File

@ -446,6 +446,15 @@ impl DrawMap {
batch 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) { pub fn delete_lane(&mut self, l: LaneID) {
self.lanes.remove(&l).unwrap(); self.lanes.remove(&l).unwrap();
let item_id = self.lane_ids.remove(&l).unwrap(); let item_id = self.lane_ids.remove(&l).unwrap();

View File

@ -12,6 +12,7 @@ use geom::{Speed, Time};
pub use self::perma::PermanentMapEdits; pub use self::perma::PermanentMapEdits;
use crate::make::initial::lane_specs::get_lane_specs_ltr; use crate::make::initial::lane_specs::get_lane_specs_ltr;
use crate::make::initial::LaneSpec;
use crate::{ use crate::{
connectivity, AccessRestrictions, BusRouteID, ControlStopSign, ControlTrafficSignal, Direction, connectivity, AccessRestrictions, BusRouteID, ControlStopSign, ControlTrafficSignal, Direction,
IntersectionID, IntersectionType, LaneID, LaneType, Map, MapConfig, PathConstraints, IntersectionID, IntersectionType, LaneID, LaneType, Map, MapConfig, PathConstraints,
@ -477,6 +478,12 @@ fn modify_road_width(
let before = map.roads[r.0].lanes_ltr.len(); let before = map.roads[r.0].lanes_ltr.len();
let after = 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 { if after < before {
// Same as the normal case... // Same as the normal case...
let road = &mut map.roads[r.0]; let road = &mut map.roads[r.0];
@ -504,8 +511,31 @@ fn modify_road_width(
// TODO Adding lanes // TODO Adding lanes
} }
// TODO We need to recalculate the road center line, all of the lane geometry, the intersection // road.center_pts doesn't need to change; we'll keep the true physical center of the road and
// geometry... // 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 // TODO We need to update buildings, bus stops, and parking lots -- they may refer to an old
// ID. // ID.
@ -576,7 +606,7 @@ impl Map {
edits.save(self); 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( pub fn must_apply_edits(
&mut self, &mut self,
new_edits: MapEdits, new_edits: MapEdits,

View File

@ -9,7 +9,7 @@ use abstutil::{Tags, Timer};
use geom::{Bounds, Circle, Distance, PolyLine, Polygon, Pt2D}; use geom::{Bounds, Circle, Distance, PolyLine, Polygon, Pt2D};
pub use self::geometry::intersection_polygon; 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::raw::{OriginalRoad, RawMap, RawRoad};
use crate::{osm, IntersectionType, MapConfig}; use crate::{osm, IntersectionType, MapConfig};

View File

@ -11,8 +11,8 @@ use crate::pathfind::Pathfinder;
use crate::raw::{OriginalRoad, RawMap}; use crate::raw::{OriginalRoad, RawMap};
use crate::{ use crate::{
connectivity, osm, AccessRestrictions, Area, AreaID, AreaType, ControlStopSign, connectivity, osm, AccessRestrictions, Area, AreaID, AreaType, ControlStopSign,
ControlTrafficSignal, Direction, Intersection, IntersectionID, IntersectionType, Lane, LaneID, ControlTrafficSignal, Intersection, IntersectionID, IntersectionType, Lane, LaneID, Map,
Map, MapEdits, Movement, PathConstraints, Position, Road, RoadID, RoutingParams, Turn, Zone, MapEdits, Movement, PathConstraints, Position, Road, RoadID, RoutingParams, Turn, Zone,
}; };
mod bridges; mod bridges;
@ -99,7 +99,7 @@ impl Map {
} }
timer.start_iter("expand roads to lanes", initial_map.roads.len()); 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(); timer.next();
let road_id = road_id_mapping[&r.id]; let road_id = road_id_mapping[&r.id];
@ -137,7 +137,7 @@ impl Map {
.collect(), .collect(),
orig_id: r.id, orig_id: r.id,
lanes_ltr: Vec::new(), lanes_ltr: Vec::new(),
center_pts: r.trimmed_center_pts.clone(), center_pts: r.trimmed_center_pts,
src_i: i1, src_i: i1,
dst_i: i2, dst_i: i2,
speed_limit: Speed::ZERO, speed_limit: Speed::ZERO,
@ -159,65 +159,13 @@ impl Map {
road.speed_limit = road.speed_limit_from_osm(); road.speed_limit = road.speed_limit_from_osm();
road.access_restrictions = road.access_restrictions_from_osm(); road.access_restrictions = road.access_restrictions_from_osm();
let mut total_back_width = Distance::ZERO; for lane in road.create_lanes(r.lane_specs_ltr, &mut map.lane_id_counter) {
for lane in &r.lane_specs_ltr { map.intersections[lane.src_i.0].outgoing_lanes.push(lane.id);
if lane.dir == Direction::Back { map.intersections[lane.dst_i.0].incoming_lanes.push(lane.id);
total_back_width += lane.width; 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); map.roads.push(road);
} }

View File

@ -1,3 +1,4 @@
use std::collections::BTreeSet;
use std::fmt; use std::fmt;
use anyhow::Result; use anyhow::Result;
@ -7,6 +8,7 @@ use serde::{Deserialize, Serialize};
use abstutil::{deserialize_usize, serialize_usize, Tags}; use abstutil::{deserialize_usize, serialize_usize, Tags};
use geom::{Distance, PolyLine, Polygon, Speed}; use geom::{Distance, PolyLine, Polygon, Speed};
use crate::make::initial::LaneSpec;
use crate::raw::{OriginalRoad, RestrictionType}; use crate::raw::{OriginalRoad, RestrictionType};
use crate::{ use crate::{
osm, AccessRestrictions, BusStopID, DrivingSide, IntersectionID, Lane, LaneID, LaneType, Map, osm, AccessRestrictions, BusStopID, DrivingSide, IntersectionID, Lane, LaneID, LaneType, Map,
@ -455,6 +457,68 @@ impl Road {
pub fn is_extremely_short(&self) -> bool { pub fn is_extremely_short(&self) -> bool {
self.center_pts.length() < Distance::meters(2.0) 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 // TODO All of this is kind of deprecated? During the transiton towards lanes_ltr, some pieces