mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-25 15:33:44 +03:00
A humble start to deleting lanes. #597
This commit is contained in:
parent
c6906f6153
commit
584c1be9e0
@ -1,5 +1,3 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use maplit::btreeset;
|
||||
|
||||
use abstutil::{prettyprint_usize, Timer};
|
||||
@ -676,7 +674,7 @@ fn make_topcenter(ctx: &mut EventCtx, app: &App) -> Panel {
|
||||
pub fn apply_map_edits(ctx: &mut EventCtx, app: &mut App, edits: MapEdits) {
|
||||
let mut timer = Timer::new("apply map edits");
|
||||
|
||||
let (roads_changed, turns_deleted, turns_added, mut modified_intersections) =
|
||||
let (roads_changed, lanes_deleted, turns_deleted, turns_added, mut modified_intersections) =
|
||||
app.primary.map.must_apply_edits(edits);
|
||||
|
||||
if !roads_changed.is_empty() || !modified_intersections.is_empty() {
|
||||
@ -702,13 +700,14 @@ pub fn apply_map_edits(ctx: &mut EventCtx, app: &mut App, edits: MapEdits) {
|
||||
}
|
||||
}
|
||||
|
||||
let mut lanes_of_modified_turns: BTreeSet<LaneID> = BTreeSet::new();
|
||||
for l in lanes_deleted {
|
||||
app.primary.draw_map.delete_lane(l);
|
||||
}
|
||||
|
||||
for t in turns_deleted {
|
||||
lanes_of_modified_turns.insert(t.src);
|
||||
modified_intersections.insert(t.parent);
|
||||
}
|
||||
for t in &turns_added {
|
||||
lanes_of_modified_turns.insert(t.src);
|
||||
modified_intersections.insert(t.parent);
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,9 @@ pub fn prompt_for_lanes(ctx: &mut EventCtx, road: &Road) -> Box<dyn State<App>>
|
||||
"Define lanes_ltr",
|
||||
lanes_to_string(road),
|
||||
Box::new(move |string, ctx, app| {
|
||||
// We're selecting a lane before this, but the ID is probably about to be invalidated.
|
||||
app.primary.current_selection = None;
|
||||
|
||||
let mut edits = app.primary.map.get_edits().clone();
|
||||
edits.commands.push(app.primary.map.edit_road_cmd(r, |new| {
|
||||
new.lanes_ltr = string_to_lanes(string.clone());
|
||||
|
@ -39,6 +39,8 @@ pub struct DrawMap {
|
||||
pub show_zorder: isize,
|
||||
|
||||
quadtree: QuadTree<ID>,
|
||||
// Remember these so we can delete lanes.
|
||||
lane_ids: HashMap<LaneID, aabb_quadtree::ItemId>,
|
||||
}
|
||||
|
||||
impl DrawMap {
|
||||
@ -140,12 +142,15 @@ impl DrawMap {
|
||||
|
||||
timer.start("create quadtree");
|
||||
let mut quadtree = QuadTree::default(map.get_bounds().as_bbox());
|
||||
let mut lane_ids = HashMap::new();
|
||||
// TODO use iter chain if everything was boxed as a renderable...
|
||||
for obj in &roads {
|
||||
quadtree.insert_with_box(obj.get_id(), obj.get_outline(map).get_bounds().as_bbox());
|
||||
}
|
||||
for (_, obj) in &lanes {
|
||||
let item_id =
|
||||
quadtree.insert_with_box(obj.get_id(), obj.get_outline(map).get_bounds().as_bbox());
|
||||
lane_ids.insert(obj.id, item_id);
|
||||
}
|
||||
for obj in &intersections {
|
||||
quadtree.insert_with_box(obj.get_id(), obj.get_outline(map).get_bounds().as_bbox());
|
||||
@ -187,6 +192,7 @@ impl DrawMap {
|
||||
draw_all_areas,
|
||||
|
||||
quadtree,
|
||||
lane_ids,
|
||||
|
||||
zorder_range: (low_z, high_z),
|
||||
show_zorder: high_z,
|
||||
@ -439,4 +445,10 @@ impl DrawMap {
|
||||
|
||||
batch
|
||||
}
|
||||
|
||||
pub fn delete_lane(&mut self, l: LaneID) {
|
||||
self.lanes.remove(&l).unwrap();
|
||||
let item_id = self.lane_ids.remove(&l).unwrap();
|
||||
self.quadtree.remove(item_id).unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -127,6 +127,7 @@ pub enum EditCmd {
|
||||
|
||||
pub struct EditEffects {
|
||||
pub changed_roads: BTreeSet<RoadID>,
|
||||
pub deleted_lanes: BTreeSet<LaneID>,
|
||||
pub changed_intersections: BTreeSet<IntersectionID>,
|
||||
pub added_turns: BTreeSet<TurnID>,
|
||||
pub deleted_turns: BTreeSet<TurnID>,
|
||||
@ -233,6 +234,7 @@ impl MapEdits {
|
||||
}
|
||||
|
||||
/// Pick apart changed_roads and figure out if an entire road was edited, or just a few lanes.
|
||||
/// Doesn't return deleted lanes.
|
||||
pub fn changed_lanes(&self, map: &Map) -> (BTreeSet<LaneID>, BTreeSet<RoadID>) {
|
||||
let mut lanes = BTreeSet::new();
|
||||
let mut roads = BTreeSet::new();
|
||||
@ -246,6 +248,11 @@ impl MapEdits {
|
||||
roads.insert(r.id);
|
||||
} else {
|
||||
let lanes_ltr = r.lanes_ltr();
|
||||
if lanes_ltr.len() != orig.lanes_ltr.len() {
|
||||
// If a lane was added or deleted, figuring out if any were modified is kind of
|
||||
// unclear -- just mark the entire road.
|
||||
roads.insert(r.id);
|
||||
} else {
|
||||
for (idx, (lt, dir)) in orig.lanes_ltr.into_iter().enumerate() {
|
||||
if lanes_ltr[idx].1 != dir || lanes_ltr[idx].2 != lt {
|
||||
lanes.insert(lanes_ltr[idx].0);
|
||||
@ -253,6 +260,7 @@ impl MapEdits {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(lanes, roads)
|
||||
}
|
||||
}
|
||||
@ -267,6 +275,7 @@ impl EditEffects {
|
||||
pub fn new() -> EditEffects {
|
||||
EditEffects {
|
||||
changed_roads: BTreeSet::new(),
|
||||
deleted_lanes: BTreeSet::new(),
|
||||
changed_intersections: BTreeSet::new(),
|
||||
added_turns: BTreeSet::new(),
|
||||
deleted_turns: BTreeSet::new(),
|
||||
@ -307,7 +316,7 @@ impl EditCmd {
|
||||
let road = &mut map.roads[r.0];
|
||||
road.speed_limit = new.speed_limit;
|
||||
road.access_restrictions = new.access_restrictions.clone();
|
||||
assert_eq!(road.lanes_ltr.len(), new.lanes_ltr.len());
|
||||
if road.lanes_ltr.len() == new.lanes_ltr.len() {
|
||||
for (idx, (lt, dir)) in new.lanes_ltr.clone().into_iter().enumerate() {
|
||||
let lane = map.lanes.get_mut(&road.lanes_ltr[idx].0).unwrap();
|
||||
road.lanes_ltr[idx].2 = lt;
|
||||
@ -321,6 +330,11 @@ impl EditCmd {
|
||||
lane.dir = dir;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
modify_road_width(map, *r, new.lanes_ltr.clone(), effects);
|
||||
}
|
||||
// Re-borrow
|
||||
let road = &mut map.roads[r.0];
|
||||
|
||||
effects.changed_roads.insert(road.id);
|
||||
for i in vec![road.src_i, road.dst_i] {
|
||||
@ -454,6 +468,49 @@ fn recalculate_turns(id: IntersectionID, map: &mut Map, effects: &mut EditEffect
|
||||
}
|
||||
}
|
||||
|
||||
fn modify_road_width(
|
||||
map: &mut Map,
|
||||
r: RoadID,
|
||||
lanes_ltr: Vec<(LaneType, Direction)>,
|
||||
effects: &mut EditEffects,
|
||||
) {
|
||||
let before = map.roads[r.0].lanes_ltr.len();
|
||||
let after = lanes_ltr.len();
|
||||
|
||||
if after < before {
|
||||
// Same as the normal case...
|
||||
let road = &mut map.roads[r.0];
|
||||
for (idx, (lt, dir)) in lanes_ltr.into_iter().enumerate() {
|
||||
let lane = map.lanes.get_mut(&road.lanes_ltr[idx].0).unwrap();
|
||||
road.lanes_ltr[idx].2 = lt;
|
||||
lane.lane_type = lt;
|
||||
|
||||
// Direction change?
|
||||
if road.lanes_ltr[idx].1 != dir {
|
||||
road.lanes_ltr[idx].1 = dir;
|
||||
std::mem::swap(&mut lane.src_i, &mut lane.dst_i);
|
||||
lane.lane_center_pts = lane.lane_center_pts.reversed();
|
||||
lane.dir = dir;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete some stuff!
|
||||
for _ in 0..before - after {
|
||||
let (l, _, _) = road.lanes_ltr.pop().unwrap();
|
||||
map.lanes.remove(&l).unwrap();
|
||||
effects.deleted_lanes.insert(l);
|
||||
}
|
||||
} else {
|
||||
// TODO Adding lanes
|
||||
}
|
||||
|
||||
// TODO We need to recalculate the road center line, all of the lane geometry, the intersection
|
||||
// geometry...
|
||||
|
||||
// TODO We need to update buildings, bus stops, and parking lots -- they may refer to an old
|
||||
// ID.
|
||||
}
|
||||
|
||||
impl Map {
|
||||
pub fn new_edits(&self) -> MapEdits {
|
||||
let mut edits = MapEdits::new();
|
||||
@ -519,11 +576,13 @@ impl Map {
|
||||
edits.save(self);
|
||||
}
|
||||
|
||||
/// Returns (roads_changed, lanes_deleted, turns_deleted, turns_added, modified_intersections)
|
||||
pub fn must_apply_edits(
|
||||
&mut self,
|
||||
new_edits: MapEdits,
|
||||
) -> (
|
||||
BTreeSet<RoadID>,
|
||||
BTreeSet<LaneID>,
|
||||
BTreeSet<TurnID>,
|
||||
BTreeSet<TurnID>,
|
||||
BTreeSet<IntersectionID>,
|
||||
@ -536,14 +595,14 @@ impl Map {
|
||||
}
|
||||
|
||||
// new_edits don't necessarily have to be valid; this could be used for speculatively testing
|
||||
// edits. Returns roads changed, turns deleted, turns added, intersections modified. Doesn't
|
||||
// update pathfinding yet.
|
||||
// edits. Doesn't update pathfinding yet.
|
||||
fn apply_edits(
|
||||
&mut self,
|
||||
mut new_edits: MapEdits,
|
||||
enforce_valid: bool,
|
||||
) -> (
|
||||
BTreeSet<RoadID>,
|
||||
BTreeSet<LaneID>,
|
||||
BTreeSet<TurnID>,
|
||||
BTreeSet<TurnID>,
|
||||
BTreeSet<IntersectionID>,
|
||||
@ -555,6 +614,7 @@ impl Map {
|
||||
BTreeSet::new(),
|
||||
BTreeSet::new(),
|
||||
BTreeSet::new(),
|
||||
BTreeSet::new(),
|
||||
);
|
||||
}
|
||||
|
||||
@ -622,6 +682,7 @@ impl Map {
|
||||
|
||||
(
|
||||
effects.changed_roads,
|
||||
effects.deleted_lanes,
|
||||
effects.deleted_turns,
|
||||
// Some of these might've been added, then later deleted.
|
||||
effects
|
||||
|
@ -84,6 +84,7 @@ pub(crate) const SHOULDER_THICKNESS: Distance = Distance::const_meters(0.5);
|
||||
pub struct Map {
|
||||
roads: Vec<Road>,
|
||||
lanes: BTreeMap<LaneID, Lane>,
|
||||
lane_id_counter: usize,
|
||||
intersections: Vec<Intersection>,
|
||||
#[serde(
|
||||
serialize_with = "serialize_btreemap",
|
||||
|
@ -50,6 +50,7 @@ impl Map {
|
||||
let mut map = Map {
|
||||
roads: Vec::new(),
|
||||
lanes: BTreeMap::new(),
|
||||
lane_id_counter: 0,
|
||||
intersections: Vec::new(),
|
||||
turns: BTreeMap::new(),
|
||||
buildings: Vec::new(),
|
||||
@ -173,7 +174,8 @@ impl Map {
|
||||
|
||||
let mut width_so_far = Distance::ZERO;
|
||||
for lane in &r.lane_specs_ltr {
|
||||
let id = LaneID(map.lanes.len());
|
||||
let id = LaneID(map.lane_id_counter);
|
||||
map.lane_id_counter += 1;
|
||||
|
||||
let (src_i, dst_i) = if lane.dir == Direction::Fwd {
|
||||
(i1, i2)
|
||||
|
@ -145,6 +145,7 @@ impl Map {
|
||||
Map {
|
||||
roads: Vec::new(),
|
||||
lanes: BTreeMap::new(),
|
||||
lane_id_counter: 0,
|
||||
intersections: Vec::new(),
|
||||
turns: BTreeMap::new(),
|
||||
buildings: Vec::new(),
|
||||
|
Loading…
Reference in New Issue
Block a user