make raw roads directly refer to intersections

This commit is contained in:
Dustin Carlino 2019-01-17 11:10:47 -08:00
parent 3422877d3d
commit 761008b3ac
7 changed files with 70 additions and 60 deletions

View File

@ -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,
});

View File

@ -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[&current];
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);

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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 }

View File

@ -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 {