mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-29 01:13:53 +03:00
make raw roads directly refer to intersections
This commit is contained in:
parent
3422877d3d
commit
761008b3ac
@ -55,6 +55,8 @@ pub fn osm_to_raw_roads(
|
||||
points: pts,
|
||||
osm_tags: tags,
|
||||
// We'll fill this out later
|
||||
i1: raw_data::StableIntersectionID(0),
|
||||
i2: raw_data::StableIntersectionID(0),
|
||||
parking_lane_fwd: false,
|
||||
parking_lane_back: false,
|
||||
});
|
||||
|
@ -1,5 +1,4 @@
|
||||
use abstutil::{MultiMap, Timer};
|
||||
use geom::HashablePt2D;
|
||||
use map_model::raw_data;
|
||||
use std::collections::HashSet;
|
||||
|
||||
@ -8,10 +7,11 @@ pub fn remove_disconnected_roads(map: &mut raw_data::Map, timer: &mut Timer) {
|
||||
// This is a simple floodfill, not Tarjan's. Assumes all roads bidirectional.
|
||||
// All the usizes are indices into the original list of roads
|
||||
|
||||
let mut next_roads: MultiMap<HashablePt2D, raw_data::StableRoadID> = MultiMap::new();
|
||||
let mut next_roads: MultiMap<raw_data::StableIntersectionID, raw_data::StableRoadID> =
|
||||
MultiMap::new();
|
||||
for (id, r) in &map.roads {
|
||||
next_roads.insert(r.first_pt().to_hashable(), *id);
|
||||
next_roads.insert(r.last_pt().to_hashable(), *id);
|
||||
next_roads.insert(r.i1, *id);
|
||||
next_roads.insert(r.i2, *id);
|
||||
}
|
||||
|
||||
let mut partitions: Vec<Vec<raw_data::StableRoadID>> = Vec::new();
|
||||
@ -30,10 +30,10 @@ pub fn remove_disconnected_roads(map: &mut raw_data::Map, timer: &mut Timer) {
|
||||
current_partition.push(current);
|
||||
|
||||
let current_r = &map.roads[¤t];
|
||||
for other_r in next_roads.get(current_r.first_pt().to_hashable()).iter() {
|
||||
for other_r in next_roads.get(current_r.i1).iter() {
|
||||
queue_roads.push(*other_r);
|
||||
}
|
||||
for other_r in next_roads.get(current_r.last_pt().to_hashable()).iter() {
|
||||
for other_r in next_roads.get(current_r.i2).iter() {
|
||||
queue_roads.push(*other_r);
|
||||
}
|
||||
}
|
||||
@ -47,8 +47,8 @@ pub fn remove_disconnected_roads(map: &mut raw_data::Map, timer: &mut Timer) {
|
||||
println!("Removing disconnected partition with {} roads", p.len());
|
||||
for id in p {
|
||||
let r = map.roads.remove(id).unwrap();
|
||||
next_roads.remove(r.first_pt().to_hashable(), *id);
|
||||
next_roads.remove(r.last_pt().to_hashable(), *id);
|
||||
next_roads.remove(r.i1, *id);
|
||||
next_roads.remove(r.i2, *id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,14 +56,9 @@ pub fn remove_disconnected_roads(map: &mut raw_data::Map, timer: &mut Timer) {
|
||||
// TODO retain for BTreeMap, please!
|
||||
let remove_intersections: Vec<raw_data::StableIntersectionID> = map
|
||||
.intersections
|
||||
.iter()
|
||||
.filter_map(|(id, i)| {
|
||||
if next_roads.get(i.point.to_hashable()).is_empty() {
|
||||
Some(*id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.keys()
|
||||
.filter(|id| next_roads.get(**id).is_empty())
|
||||
.cloned()
|
||||
.collect();
|
||||
for id in remove_intersections {
|
||||
map.intersections.remove(&id);
|
||||
|
@ -84,9 +84,12 @@ pub fn split_up_roads(
|
||||
map.buildings = buildings;
|
||||
map.areas = areas;
|
||||
|
||||
for (idx, pt) in intersections.iter().enumerate() {
|
||||
let mut pt_to_intersection: HashMap<HashablePt2D, raw_data::StableIntersectionID> =
|
||||
HashMap::new();
|
||||
for (idx, pt) in intersections.into_iter().enumerate() {
|
||||
let id = raw_data::StableIntersectionID(idx);
|
||||
map.intersections.insert(
|
||||
raw_data::StableIntersectionID(idx),
|
||||
id,
|
||||
raw_data::Intersection {
|
||||
point: LonLat::new(pt.x(), pt.y()),
|
||||
elevation: elevation.get(pt.x(), pt.y()) * si::M,
|
||||
@ -94,21 +97,27 @@ pub fn split_up_roads(
|
||||
label: None,
|
||||
},
|
||||
);
|
||||
pt_to_intersection.insert(pt, id);
|
||||
}
|
||||
|
||||
// Now actually split up the roads based on the intersections
|
||||
for orig_road in &roads {
|
||||
let mut r = orig_road.clone();
|
||||
r.points.clear();
|
||||
r.i1 = pt_to_intersection[&orig_road.points[0].to_hashable()];
|
||||
|
||||
for pt in &orig_road.points {
|
||||
r.points.push(pt.clone());
|
||||
if r.points.len() > 1 && intersections.contains(&pt.to_hashable()) {
|
||||
// Start a new road
|
||||
map.roads
|
||||
.insert(raw_data::StableRoadID(map.roads.len()), r.clone());
|
||||
r.points.clear();
|
||||
r.points.push(pt.clone());
|
||||
if r.points.len() > 1 {
|
||||
if let Some(i2) = pt_to_intersection.get(&pt.to_hashable()) {
|
||||
r.i2 = *i2;
|
||||
// Start a new road
|
||||
map.roads
|
||||
.insert(raw_data::StableRoadID(map.roads.len()), r.clone());
|
||||
r.points.clear();
|
||||
r.i1 = *i2;
|
||||
r.points.push(pt.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
assert!(r.points.len() == 1);
|
||||
|
@ -71,8 +71,8 @@ fn tooltip_lines(obj: ID, ctx: &Ctx) -> Text {
|
||||
);
|
||||
txt.add_line(format!("From OSM way {}", r.osm_way_id));
|
||||
txt.add_line(format!(
|
||||
"Parent {} (stable ID {}) points to {}",
|
||||
r.id, r.stable_id.0, r.dst_i
|
||||
"Parent {} (originally {}) points to {}",
|
||||
r.id, r.stable_id, r.dst_i
|
||||
));
|
||||
txt.add_line(format!(
|
||||
"Lane goes from {} to {}",
|
||||
@ -93,7 +93,7 @@ fn tooltip_lines(obj: ID, ctx: &Ctx) -> Text {
|
||||
txt.add_line(id.to_string());
|
||||
let i = map.get_i(id);
|
||||
txt.add_line(format!("Roads: {:?}", i.roads));
|
||||
txt.add_line(format!("Stable ID {}", i.stable_id.0));
|
||||
txt.add_line(format!("Originally {}", i.stable_id));
|
||||
}
|
||||
ID::Turn(id) => {
|
||||
let t = map.get_t(id);
|
||||
|
@ -4,8 +4,8 @@ use crate::{
|
||||
Turn, TurnID, LANE_THICKNESS,
|
||||
};
|
||||
use abstutil::Timer;
|
||||
use geom::{GPSBounds, HashablePt2D, PolyLine, Pt2D};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
||||
use geom::{GPSBounds, PolyLine, Pt2D};
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
pub struct HalfMap {
|
||||
pub roads: Vec<Road>,
|
||||
@ -27,8 +27,8 @@ pub fn make_half_map(
|
||||
turns: BTreeMap::new(),
|
||||
};
|
||||
|
||||
let mut pt_to_intersection: HashMap<HashablePt2D, IntersectionID> = HashMap::new();
|
||||
|
||||
let mut intersection_id_mapping: BTreeMap<raw_data::StableIntersectionID, IntersectionID> =
|
||||
BTreeMap::new();
|
||||
for (idx, (stable_id, i)) in data.intersections.iter().enumerate() {
|
||||
let id = IntersectionID(idx);
|
||||
let pt = Pt2D::from_gps(i.point, &gps_bounds).unwrap();
|
||||
@ -46,7 +46,7 @@ pub fn make_half_map(
|
||||
outgoing_lanes: Vec::new(),
|
||||
roads: BTreeSet::new(),
|
||||
});
|
||||
pt_to_intersection.insert(HashablePt2D::from(pt), id);
|
||||
intersection_id_mapping.insert(*stable_id, id);
|
||||
}
|
||||
|
||||
let mut counter = 0;
|
||||
@ -60,8 +60,8 @@ pub fn make_half_map(
|
||||
.map(|coord| Pt2D::from_gps(*coord, &gps_bounds).unwrap())
|
||||
.collect(),
|
||||
);
|
||||
let i1 = pt_to_intersection[&HashablePt2D::from(road_center_pts.first_pt())];
|
||||
let i2 = pt_to_intersection[&HashablePt2D::from(road_center_pts.last_pt())];
|
||||
let i1 = intersection_id_mapping[&r.i1];
|
||||
let i2 = intersection_id_mapping[&r.i2];
|
||||
|
||||
if i1 == i2 {
|
||||
// TODO Cul-de-sacs should be valid, but it really makes pathfinding screwy
|
||||
|
@ -5,13 +5,25 @@ use geom::{GPSBounds, LonLat};
|
||||
use gtfs::Route;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
|
||||
// Stable IDs don't get compacted as we merge and delete things.
|
||||
//#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, PartialOrd, Ord, Clone, Copy, Hash)]
|
||||
pub struct StableRoadID(pub usize);
|
||||
impl fmt::Display for StableRoadID {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "StableRoadID({0})", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, PartialOrd, Ord, Clone, Copy, Hash)]
|
||||
pub struct StableIntersectionID(pub usize);
|
||||
impl fmt::Display for StableIntersectionID {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "StableIntersectionID({0})", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub struct Map {
|
||||
@ -73,6 +85,9 @@ impl Map {
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub struct Road {
|
||||
// The first and last point may not match up with i1 and i2.
|
||||
pub i1: StableIntersectionID,
|
||||
pub i2: StableIntersectionID,
|
||||
pub points: Vec<LonLat>,
|
||||
pub osm_tags: BTreeMap<String, String>,
|
||||
pub osm_way_id: i64,
|
||||
@ -81,14 +96,6 @@ pub struct Road {
|
||||
}
|
||||
|
||||
impl Road {
|
||||
pub fn first_pt(&self) -> LonLat {
|
||||
self.points[0]
|
||||
}
|
||||
|
||||
pub fn last_pt(&self) -> LonLat {
|
||||
*self.points.last().unwrap()
|
||||
}
|
||||
|
||||
pub fn get_spec(&self) -> RoadSpec {
|
||||
let (fwd, back) = get_lane_types(self);
|
||||
RoadSpec { fwd, back }
|
||||
|
@ -2,10 +2,10 @@ use aabb_quadtree::QuadTree;
|
||||
use abstutil::{deserialize_btreemap, read_binary, serialize_btreemap, write_json, Timer};
|
||||
use dimensioned::si;
|
||||
use ezgui::{Canvas, Color, GfxCtx, Text};
|
||||
use geom::{Circle, HashablePt2D, LonLat, PolyLine, Polygon, Pt2D};
|
||||
use geom::{Circle, LonLat, PolyLine, Polygon, Pt2D};
|
||||
use map_model::{raw_data, IntersectionType, LaneType, RoadSpec, LANE_THICKNESS};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::collections::BTreeMap;
|
||||
use std::mem;
|
||||
|
||||
const INTERSECTION_RADIUS: f64 = 5.0;
|
||||
@ -15,7 +15,7 @@ const CENTER_LINE_THICKNESS: f64 = 0.5;
|
||||
const HIGHLIGHT_COLOR: Color = Color::CYAN;
|
||||
|
||||
pub type BuildingID = usize;
|
||||
pub type IntersectionID = usize;
|
||||
pub type IntersectionID = raw_data::StableIntersectionID;
|
||||
pub type RoadID = (IntersectionID, IntersectionID);
|
||||
pub type Direction = bool;
|
||||
|
||||
@ -339,6 +339,8 @@ impl Model {
|
||||
map.roads.insert(
|
||||
raw_data::StableRoadID(idx),
|
||||
raw_data::Road {
|
||||
i1: r.i1,
|
||||
i2: r.i2,
|
||||
points: vec![
|
||||
pt(self.intersections[&r.i1].center),
|
||||
pt(self.intersections[&r.i2].center),
|
||||
@ -351,9 +353,9 @@ impl Model {
|
||||
);
|
||||
}
|
||||
|
||||
for (idx, i) in self.intersections.values().enumerate() {
|
||||
for (id, i) in &self.intersections {
|
||||
map.intersections.insert(
|
||||
raw_data::StableIntersectionID(idx),
|
||||
*id,
|
||||
raw_data::Intersection {
|
||||
point: pt(i.center),
|
||||
elevation: 0.0 * si::M,
|
||||
@ -390,26 +392,21 @@ impl Model {
|
||||
let gps_bounds = data.get_gps_bounds();
|
||||
|
||||
let mut m = Model::new();
|
||||
let mut pt_to_intersection: HashMap<HashablePt2D, IntersectionID> = HashMap::new();
|
||||
let mut quadtree = QuadTree::default(gps_bounds.to_bounds().as_bbox());
|
||||
|
||||
for (idx, i) in data.intersections.values().enumerate() {
|
||||
let center = Pt2D::from_gps(i.point, &gps_bounds).unwrap();
|
||||
for (id, raw_i) in &data.intersections {
|
||||
let center = Pt2D::from_gps(raw_i.point, &gps_bounds).unwrap();
|
||||
let i = Intersection {
|
||||
center,
|
||||
intersection_type: i.intersection_type,
|
||||
label: i.label.clone(),
|
||||
intersection_type: raw_i.intersection_type,
|
||||
label: raw_i.label.clone(),
|
||||
};
|
||||
quadtree.insert_with_box(ID::Intersection(idx), i.circle().get_bounds().as_bbox());
|
||||
m.intersections.insert(idx, i);
|
||||
pt_to_intersection.insert(center.into(), idx);
|
||||
quadtree.insert_with_box(ID::Intersection(*id), i.circle().get_bounds().as_bbox());
|
||||
m.intersections.insert(*id, i);
|
||||
}
|
||||
|
||||
for r in data.roads.values() {
|
||||
let i1 = pt_to_intersection[&Pt2D::from_gps(r.points[0], &gps_bounds).unwrap().into()];
|
||||
let i2 = pt_to_intersection[&Pt2D::from_gps(*r.points.last().unwrap(), &gps_bounds)
|
||||
.unwrap()
|
||||
.into()];
|
||||
let (i1, i2) = (r.i1, r.i2);
|
||||
m.roads.insert(
|
||||
(i1, i2),
|
||||
Road {
|
||||
@ -453,7 +450,7 @@ impl Model {
|
||||
|
||||
impl Model {
|
||||
pub fn create_i(&mut self, center: Pt2D) {
|
||||
let id = self.intersections.len();
|
||||
let id = raw_data::StableIntersectionID(self.intersections.len());
|
||||
self.intersections.insert(
|
||||
id,
|
||||
Intersection {
|
||||
|
Loading…
Reference in New Issue
Block a user