mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-01 02:33:54 +03:00
refactoring intersection->roads query
This commit is contained in:
parent
9eb1469c89
commit
6e786d5630
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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.
|
||||||
|
@ -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())
|
||||||
|
@ -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()
|
||||||
|
Loading…
Reference in New Issue
Block a user