mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 03:35:51 +03:00
Fix lane geometry after changing the number of lanes. #597
This commit is contained in:
parent
584c1be9e0
commit
14609ab157
@ -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);
|
||||
}
|
||||
|
||||
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();
|
||||
@ -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
|
||||
// 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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
@ -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];
|
||||
@ -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.
|
||||
@ -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,
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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;
|
||||
@ -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];
|
||||
@ -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,
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
use std::collections::BTreeSet;
|
||||
use std::fmt;
|
||||
|
||||
use anyhow::Result;
|
||||
@ -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,
|
||||
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user