mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-23 17:07:12 +03:00
Make editing maps with transit stops a little more resilient. #372
Transit stop IDs previously were tied to LaneIDs, but those can easily change with edits to the number of lanes on a road. We still may need to re-snap transit stops (if the driving position or sidewalk changes), but this prevents one more common type of problem. This requires regenerating everything, since it's a binary schema change...
This commit is contained in:
parent
0dc8972187
commit
6a5366292f
@ -1,10 +1,13 @@
|
||||
#!/bin/bash
|
||||
# TODO It's probably more useful to now manually run commands from this file.
|
||||
|
||||
set -e
|
||||
|
||||
rm -fv data/input/us/seattle/raw_maps/huge_seattle.bin data/system/us/seattle/maps/huge_seattle.bin data/input/us/seattle/popdat.bin
|
||||
|
||||
RUST_BACKTRACE=1 cargo run --release --bin cli --features importer/scenarios -- regenerate-everything
|
||||
# Or more efficiently:
|
||||
# ./target/release/cli regenerate-everything-externally
|
||||
|
||||
# If a map changes that has external JSON scenarios, enable this!
|
||||
# importer/external_scenarios.sh
|
||||
|
@ -388,13 +388,13 @@ impl App {
|
||||
let road = draw_map.get_r(id);
|
||||
for lane in &road.lanes {
|
||||
agents_on.push(Traversable::Lane(lane.id));
|
||||
for ts in &map.get_l(lane.id).transit_stops {
|
||||
if show_objs.show(&ID::TransitStop(*ts)) {
|
||||
transit_stops.push(draw_map.get_ts(*ts));
|
||||
}
|
||||
}
|
||||
lanes.push(lane);
|
||||
}
|
||||
for ts in &map.get_r(id).transit_stops {
|
||||
if show_objs.show(&ID::TransitStop(*ts)) {
|
||||
transit_stops.push(draw_map.get_ts(*ts));
|
||||
}
|
||||
}
|
||||
roads.push(road);
|
||||
}
|
||||
ID::Intersection(id) => {
|
||||
|
@ -378,11 +378,11 @@ impl DrawMap {
|
||||
ID::Road(id) => {
|
||||
let road = self.get_r(id);
|
||||
for lane in &road.lanes {
|
||||
for ts in &map.get_l(lane.id).transit_stops {
|
||||
transit_stops.push(self.get_ts(*ts));
|
||||
}
|
||||
lanes.push(lane);
|
||||
}
|
||||
for ts in &map.get_r(id).transit_stops {
|
||||
transit_stops.push(self.get_ts(*ts));
|
||||
}
|
||||
roads.push(road);
|
||||
}
|
||||
ID::Intersection(id) => {
|
||||
|
@ -905,7 +905,7 @@ impl Map {
|
||||
// Might need to update bus stops.
|
||||
if enforce_valid {
|
||||
for id in &effects.changed_roads {
|
||||
let stops = self.get_r(*id).all_transit_stops();
|
||||
let stops = self.get_r(*id).transit_stops.clone();
|
||||
for s in stops {
|
||||
let sidewalk_pos = self.get_ts(s).sidewalk_pos;
|
||||
// Must exist, because we aren't allowed to orphan a bus stop.
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! See <https://a-b-street.github.io/docs/tech/map/importing/index.html> for an overview. This module
|
||||
//! covers the RawMap->Map stage.
|
||||
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
||||
|
||||
use structopt::StructOpt;
|
||||
|
||||
@ -155,6 +155,7 @@ impl Map {
|
||||
percent_incline: raw_road.percent_incline,
|
||||
crosswalk_forward: raw_road.crosswalk_forward,
|
||||
crosswalk_backward: raw_road.crosswalk_backward,
|
||||
transit_stops: BTreeSet::new(),
|
||||
};
|
||||
road.speed_limit = road.speed_limit_from_osm();
|
||||
road.access_restrictions = road.access_restrictions_from_osm();
|
||||
|
@ -62,11 +62,12 @@ fn create_stop(
|
||||
.find_closest_lane(sidewalk_lane, |l| vehicle.can_use(l, map))
|
||||
.map(|l| sidewalk_pos.equiv_pos(l, map))
|
||||
{
|
||||
let road = sidewalk_lane.road;
|
||||
let id = TransitStopID {
|
||||
sidewalk: sidewalk_lane,
|
||||
idx: map.get_l(sidewalk_lane).transit_stops.len(),
|
||||
road,
|
||||
idx: map.get_r(road).transit_stops.len(),
|
||||
};
|
||||
map.mut_lane(sidewalk_lane).transit_stops.insert(id);
|
||||
map.mut_road(road).transit_stops.insert(id);
|
||||
map.transit_stops.insert(
|
||||
id,
|
||||
TransitStop {
|
||||
|
@ -282,6 +282,9 @@ impl Map {
|
||||
pub(crate) fn mut_lane(&mut self, id: LaneID) -> &mut Lane {
|
||||
&mut self.roads[id.road.0].lanes[id.offset]
|
||||
}
|
||||
pub(crate) fn mut_road(&mut self, id: RoadID) -> &mut Road {
|
||||
&mut self.roads[id.0]
|
||||
}
|
||||
|
||||
pub fn get_i(&self, id: IntersectionID) -> &Intersection {
|
||||
&self.intersections[id.0]
|
||||
@ -899,9 +902,7 @@ impl Map {
|
||||
self.transit_stops.clear();
|
||||
self.transit_routes.clear();
|
||||
for r in &mut self.roads {
|
||||
for l in &mut r.lanes {
|
||||
l.transit_stops.clear();
|
||||
}
|
||||
r.transit_stops.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use geom::{Distance, Line, PolyLine, Polygon, Pt2D};
|
||||
|
||||
use crate::{
|
||||
osm, DirectedRoadID, Direction, DrivingSide, IntersectionID, Map, MapConfig, Road, RoadID,
|
||||
RoadSideID, SideOfRoad, TransitStopID, TurnType,
|
||||
RoadSideID, SideOfRoad, TurnType,
|
||||
};
|
||||
|
||||
/// From some manually audited cases in Seattle, the length of parallel street parking spots is a
|
||||
@ -247,9 +247,6 @@ pub struct Lane {
|
||||
pub src_i: IntersectionID,
|
||||
pub dst_i: IntersectionID,
|
||||
|
||||
/// Meaningless order
|
||||
pub transit_stops: BTreeSet<TransitStopID>,
|
||||
|
||||
/// {Cars, bikes} trying to start or end here might not be able to reach most lanes in the
|
||||
/// graph, because this is near a border.
|
||||
pub driving_blackhole: bool,
|
||||
|
@ -196,6 +196,9 @@ pub struct Road {
|
||||
/// Is there a tagged crosswalk near each end of the road?
|
||||
pub crosswalk_forward: bool,
|
||||
pub crosswalk_backward: bool,
|
||||
|
||||
/// Meaningless order
|
||||
pub transit_stops: BTreeSet<TransitStopID>,
|
||||
}
|
||||
|
||||
impl Road {
|
||||
@ -423,14 +426,6 @@ impl Road {
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
pub fn all_transit_stops(&self) -> Vec<TransitStopID> {
|
||||
self.lanes
|
||||
.iter()
|
||||
.flat_map(|l| l.transit_stops.iter())
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn is_light_rail(&self) -> bool {
|
||||
self.lanes.len() == 1 && self.lanes[0].lane_type == LaneType::LightRail
|
||||
}
|
||||
@ -589,7 +584,6 @@ impl Road {
|
||||
dst_i,
|
||||
lane_type: lane.lt,
|
||||
dir: lane.dir,
|
||||
transit_stops: BTreeSet::new(),
|
||||
driving_blackhole: false,
|
||||
biking_blackhole: false,
|
||||
});
|
||||
|
@ -7,19 +7,19 @@ use serde::{Deserialize, Serialize};
|
||||
use abstutil::{deserialize_usize, serialize_usize};
|
||||
use geom::Time;
|
||||
|
||||
use crate::{LaneID, Map, PathConstraints, PathRequest, Position};
|
||||
use crate::{LaneID, Map, PathConstraints, PathRequest, Position, RoadID};
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct TransitStopID {
|
||||
pub sidewalk: LaneID,
|
||||
/// As long as this is unique per lane, this value is otherwise meaningless. Not contiguous or
|
||||
pub road: RoadID,
|
||||
/// As long as this is unique per road, this value is otherwise meaningless. Not contiguous or
|
||||
/// ordered in any way.
|
||||
pub(crate) idx: usize,
|
||||
}
|
||||
|
||||
impl fmt::Display for TransitStopID {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "TransitStopID({0}, {1})", self.sidewalk, self.idx)
|
||||
write!(f, "TransitStopID({0}, {1})", self.road, self.idx)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
"scenario": "weekday",
|
||||
"finished_trips": 76640,
|
||||
"cancelled_trips": 0,
|
||||
"total_trip_duration_seconds": 44010529.93400101
|
||||
"total_trip_duration_seconds": 43735836.876801066
|
||||
},
|
||||
{
|
||||
"map": "montlake (in seattle (us))",
|
||||
|
Loading…
Reference in New Issue
Block a user