refactoring intersection->roads query

This commit is contained in:
Dustin Carlino 2018-11-07 11:47:30 -08:00
parent 9eb1469c89
commit 6e786d5630
6 changed files with 29 additions and 38 deletions

View File

@ -38,8 +38,8 @@ impl ControlStopSign {
} }
fn smart_assignment(map: &Map, intersection: IntersectionID) -> ControlStopSign { fn smart_assignment(map: &Map, intersection: IntersectionID) -> ControlStopSign {
if map.get_i(intersection).get_roads(map).len() <= 2 { if map.get_i(intersection).roads.len() <= 2 {
return ControlStopSign::for_degenerate_intersection(map, intersection); return ControlStopSign::for_degenerate_and_deadend(map, intersection);
} }
// Higher numbers are higher rank roads // Higher numbers are higher rank roads
@ -127,7 +127,7 @@ impl ControlStopSign {
ss ss
} }
fn for_degenerate_intersection(map: &Map, i: IntersectionID) -> ControlStopSign { fn for_degenerate_and_deadend(map: &Map, i: IntersectionID) -> ControlStopSign {
let mut ss = ControlStopSign { let mut ss = ControlStopSign {
intersection: i, intersection: i,
turns: BTreeMap::new(), turns: BTreeMap::new(),
@ -146,7 +146,7 @@ impl ControlStopSign {
// intersection geometry), sometimes more turns conflict than really should. For now, just // intersection geometry), sometimes more turns conflict than really should. For now, just
// detect and fallback to an all-way stop. // detect and fallback to an all-way stop.
if let Err(err) = ss.validate(map, i) { if let Err(err) = ss.validate(map, i) {
warn!("Giving up on for_degenerate_intersection({}): {}", i, err); warn!("Giving up on for_degenerate_and_deadend({}): {}", i, err);
return ControlStopSign::all_way_stop(map, i); return ControlStopSign::all_way_stop(map, i);
} }

View File

@ -35,7 +35,7 @@ impl DrawIntersection {
crosswalks: calculate_crosswalks(inter.id, map), crosswalks: calculate_crosswalks(inter.id, map),
sidewalk_corners: calculate_corners(inter.id, map), sidewalk_corners: calculate_corners(inter.id, map),
has_traffic_signal: inter.has_traffic_signal, has_traffic_signal: inter.has_traffic_signal,
should_draw_stop_sign: !inter.has_traffic_signal && !inter.is_degenerate(map), should_draw_stop_sign: !inter.has_traffic_signal && !inter.is_degenerate(),
} }
} }

View File

@ -5,7 +5,7 @@ use dimensioned::si;
use geom::Pt2D; use geom::Pt2D;
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::fmt; use std::fmt;
use {LaneID, Map, RoadID, TurnID}; use {LaneID, RoadID, TurnID};
// TODO reconsider pub usize. maybe outside world shouldnt know. // TODO reconsider pub usize. maybe outside world shouldnt know.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
@ -32,6 +32,8 @@ pub struct Intersection {
// TODO narrow down when and why. is it just sidewalks in weird cases? // TODO narrow down when and why. is it just sidewalks in weird cases?
pub incoming_lanes: Vec<LaneID>, pub incoming_lanes: Vec<LaneID>,
pub outgoing_lanes: Vec<LaneID>, pub outgoing_lanes: Vec<LaneID>,
pub roads: BTreeSet<RoadID>,
} }
impl PartialEq for Intersection { impl PartialEq for Intersection {
@ -41,20 +43,12 @@ impl PartialEq for Intersection {
} }
impl Intersection { impl Intersection {
pub fn get_roads(&self, map: &Map) -> BTreeSet<RoadID> { pub fn is_dead_end(&self) -> bool {
let mut roads: BTreeSet<RoadID> = BTreeSet::new(); self.roads.len() == 1
for l in self.incoming_lanes.iter().chain(self.outgoing_lanes.iter()) {
roads.insert(map.get_l(*l).parent);
}
roads
} }
pub fn is_dead_end(&self, map: &Map) -> bool { pub fn is_degenerate(&self) -> bool {
self.get_roads(map).len() == 1 self.roads.len() == 2
}
pub fn is_degenerate(&self, map: &Map) -> bool {
self.get_roads(map).len() == 2
} }
pub fn dump_debug(&self) { pub fn dump_debug(&self) {

View File

@ -1,7 +1,6 @@
use abstutil::wraparound_get; use abstutil::wraparound_get;
use dimensioned::si; use dimensioned::si;
use geom::{Angle, PolyLine, Pt2D}; use geom::{Angle, PolyLine, Pt2D};
use std::collections::BTreeSet;
use std::marker; use std::marker;
use {Intersection, Road, RoadID, LANE_THICKNESS}; use {Intersection, Road, RoadID, LANE_THICKNESS};
@ -12,16 +11,13 @@ const DEGENERATE_INTERSECTION_HALF_LENGTH: si::Meter<f64> = si::Meter {
// The polygon should exist entirely within the thick bands around all original roads -- it just // The polygon should exist entirely within the thick bands around all original roads -- it just
// carves up part of that space, doesn't reach past it. // carves up part of that space, doesn't reach past it.
pub fn intersection_polygon( pub fn intersection_polygon(i: &Intersection, roads: &Vec<Road>) -> Vec<Pt2D> {
i: &Intersection,
road_ids: BTreeSet<RoadID>,
roads: &Vec<Road>,
) -> Vec<Pt2D> {
// Turn all of the incident roads into two PolyLines (the "forwards" and "backwards" borders of // Turn all of the incident roads into two PolyLines (the "forwards" and "backwards" borders of
// the road), both with an endpoint at i.point, and the angle of the last segment of the center // the road), both with an endpoint at i.point, and the angle of the last segment of the center
// line. // line.
let mut lines: Vec<(RoadID, Angle, PolyLine, PolyLine)> = road_ids let mut lines: Vec<(RoadID, Angle, PolyLine, PolyLine)> = i
.into_iter() .roads
.iter()
.map(|id| { .map(|id| {
let r = &roads[id.0]; let r = &roads[id.0];
let fwd_width = LANE_THICKNESS * (r.children_forwards.len() as f64); let fwd_width = LANE_THICKNESS * (r.children_forwards.len() as f64);
@ -37,7 +33,7 @@ pub fn intersection_polygon(
let pl_normal = line.shift(width_normal).unwrap(); let pl_normal = line.shift(width_normal).unwrap();
let pl_reverse = line.reversed().shift(width_reverse).unwrap().reversed(); let pl_reverse = line.reversed().shift(width_reverse).unwrap().reversed();
(id, line.last_line().angle(), pl_normal, pl_reverse) (*id, line.last_line().angle(), pl_normal, pl_reverse)
}).collect(); }).collect();
// Sort the polylines by the angle of their last segment. // Sort the polylines by the angle of their last segment.

View File

@ -57,12 +57,11 @@ fn dedupe(turns: Vec<Turn>) -> Vec<Turn> {
} }
fn make_driving_turns(i: &Intersection, map: &Map) -> Vec<Turn> { fn make_driving_turns(i: &Intersection, map: &Map) -> Vec<Turn> {
if i.is_dead_end(map) { if i.is_dead_end() {
return make_driving_turns_for_dead_end(i, map); return make_driving_turns_for_dead_end(i, map);
} }
// TODO make get_roads do this? let roads: Vec<&Road> = i.roads.iter().map(|r| map.get_r(*r)).collect();
let roads: Vec<&Road> = i.get_roads(map).into_iter().map(|r| map.get_r(r)).collect();
let mut result = Vec::new(); let mut result = Vec::new();
@ -148,7 +147,7 @@ fn match_up_driving_lanes(
} }
fn make_driving_turns_for_dead_end(i: &Intersection, map: &Map) -> Vec<Turn> { fn make_driving_turns_for_dead_end(i: &Intersection, map: &Map) -> Vec<Turn> {
let road = map.get_r(i.get_roads(map).into_iter().next().unwrap()); let road = map.get_r(*i.roads.iter().next().unwrap());
let incoming = filter_driving_lanes(road.incoming_lanes(i.id)); let incoming = filter_driving_lanes(road.incoming_lanes(i.id));
let outgoing = filter_driving_lanes(road.outgoing_lanes(i.id)); let outgoing = filter_driving_lanes(road.outgoing_lanes(i.id));
if incoming.is_empty() || outgoing.is_empty() { if incoming.is_empty() || outgoing.is_empty() {
@ -248,7 +247,7 @@ fn make_turns(
assert_eq!(map.get_l(*l).src_i, parent); assert_eq!(map.get_l(*l).src_i, parent);
} }
let dead_end = map.get_i(parent).is_dead_end(map); let dead_end = map.get_i(parent).is_dead_end();
let mut result = Vec::new(); let mut result = Vec::new();
for src in incoming { for src in incoming {
@ -276,10 +275,10 @@ fn make_walking_turns(i: &Intersection, map: &Map) -> Vec<Turn> {
// Sort roads by the angle into the intersection, so we can reason about sidewalks of adjacent // Sort roads by the angle into the intersection, so we can reason about sidewalks of adjacent
// roads. // roads.
let mut roads: Vec<(RoadID, Angle)> = i let mut roads: Vec<(RoadID, Angle)> = i
.get_roads(map) .roads
.into_iter() .iter()
.map(|id| { .map(|id| {
let r = map.get_r(id); let r = map.get_r(*id);
if r.src_i == i.id { if r.src_i == i.id {
(r.id, r.center_pts.reversed().last_line().angle()) (r.id, r.center_pts.reversed().last_line().angle())

View File

@ -95,6 +95,7 @@ impl Map {
has_traffic_signal: i.has_traffic_signal, has_traffic_signal: i.has_traffic_signal,
incoming_lanes: Vec::new(), incoming_lanes: Vec::new(),
outgoing_lanes: Vec::new(), outgoing_lanes: Vec::new(),
roads: BTreeSet::new(),
}); });
pt_to_intersection.insert(HashablePt2D::from(pt), id); pt_to_intersection.insert(HashablePt2D::from(pt), id);
} }
@ -135,7 +136,9 @@ impl Map {
} }
let (src_i, dst_i) = if lane.reverse_pts { (i2, i1) } else { (i1, i2) }; let (src_i, dst_i) = if lane.reverse_pts { (i2, i1) } else { (i1, i2) };
m.intersections[src_i.0].outgoing_lanes.push(id); m.intersections[src_i.0].outgoing_lanes.push(id);
m.intersections[src_i.0].roads.insert(road_id);
m.intersections[dst_i.0].incoming_lanes.push(id); m.intersections[dst_i.0].incoming_lanes.push(id);
m.intersections[dst_i.0].roads.insert(road_id);
// TODO probably different behavior for oneways // TODO probably different behavior for oneways
// TODO need to factor in yellow center lines (but what's the right thing to even do? // TODO need to factor in yellow center lines (but what's the right thing to even do?
@ -181,8 +184,7 @@ impl Map {
panic!("{:?} is orphaned!", i); panic!("{:?} is orphaned!", i);
} }
let incident_roads = i.get_roads(&m); intersection_polygons.push(make::intersection_polygon(i, &m.roads));
intersection_polygons.push(make::intersection_polygon(i, incident_roads, &m.roads));
} }
for (idx, p) in intersection_polygons.into_iter().enumerate() { for (idx, p) in intersection_polygons.into_iter().enumerate() {
m.intersections[idx].polygon = p; m.intersections[idx].polygon = p;
@ -423,7 +425,7 @@ impl Map {
let r = self.get_r(from); let r = self.get_r(from);
for id in vec![r.src_i, r.dst_i].into_iter() { for id in vec![r.src_i, r.dst_i].into_iter() {
roads.extend(self.get_i(id).get_roads(self)); roads.extend(self.get_i(id).roads.clone());
} }
roads.into_iter().collect() roads.into_iter().collect()