mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 12:12:00 +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);
|
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);
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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,
|
||||||
|
@ -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};
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user