mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-27 16:36:02 +03:00
tools to debug individual sidewalk corners. fixed some bugs where
sidewalk corners were incorrectly placed in the first place, causing bad drawing. bug due to the same naive adjacent road approach
This commit is contained in:
parent
b68b3117bc
commit
d56f04167b
@ -8,8 +8,6 @@
|
||||
- bad polyline shifting causes jagged lane endings in generalized_trim_back
|
||||
|
||||
- handle small roads again somehow?
|
||||
- work on sidewalk corner drawing, like near o85
|
||||
|
||||
- try it bigger
|
||||
- VERY overeager... ate half of the map
|
||||
- deal with loop roads
|
||||
|
@ -1,11 +1,13 @@
|
||||
use crate::objects::{Ctx, ID};
|
||||
use crate::plugins::{Plugin, PluginCtx};
|
||||
use crate::render::calculate_corners;
|
||||
use ezgui::{GfxCtx, Key, Text};
|
||||
use geom::{Pt2D, Triangle};
|
||||
use geom::{Polygon, Pt2D, Triangle};
|
||||
|
||||
enum Item {
|
||||
Point(Pt2D),
|
||||
Triangle(Triangle),
|
||||
Polygon(Polygon),
|
||||
}
|
||||
|
||||
pub struct DebugPolygon {
|
||||
@ -18,11 +20,12 @@ impl DebugPolygon {
|
||||
pub fn new(ctx: &mut PluginCtx) -> Option<DebugPolygon> {
|
||||
match ctx.primary.current_selection {
|
||||
Some(ID::Intersection(id)) => {
|
||||
let i = ctx.primary.map.get_i(id);
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::X, "debug intersection geometry")
|
||||
{
|
||||
let pts = ctx.primary.map.get_i(id).polygon.points();
|
||||
let pts = i.polygon.points();
|
||||
let mut pts_without_last = pts.clone();
|
||||
pts_without_last.pop();
|
||||
return Some(DebugPolygon {
|
||||
@ -30,6 +33,18 @@ impl DebugPolygon {
|
||||
current: 0,
|
||||
center: Some(Pt2D::center(&pts_without_last)),
|
||||
});
|
||||
} else if ctx
|
||||
.input
|
||||
.contextual_action(Key::F2, "debug sidewalk corners")
|
||||
{
|
||||
return Some(DebugPolygon {
|
||||
items: calculate_corners(i, &ctx.primary.map)
|
||||
.into_iter()
|
||||
.map(Item::Polygon)
|
||||
.collect(),
|
||||
current: 0,
|
||||
center: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
Some(ID::Lane(id)) => {
|
||||
@ -82,7 +97,7 @@ impl Plugin for DebugPolygon {
|
||||
true
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _ctx: &Ctx) {
|
||||
fn draw(&self, g: &mut GfxCtx, ctx: &Ctx) {
|
||||
match self.items[self.current] {
|
||||
Item::Point(pt) => {
|
||||
g.draw_text_at(Text::from_line(format!("{}", self.current)), pt);
|
||||
@ -92,6 +107,10 @@ impl Plugin for DebugPolygon {
|
||||
g.draw_text_at(Text::from_line(format!("{}", self.current)), *pt);
|
||||
}
|
||||
}
|
||||
Item::Polygon(ref poly) => {
|
||||
g.draw_polygon(ctx.cs.get("selected"), poly);
|
||||
g.draw_text_at(Text::from_line(format!("{}", self.current)), poly.center());
|
||||
}
|
||||
}
|
||||
if let Some(pt) = self.center {
|
||||
g.draw_text_at(Text::from_line("c".to_string()), pt);
|
||||
|
@ -121,7 +121,8 @@ fn calculate_crosswalks(
|
||||
crosswalks
|
||||
}
|
||||
|
||||
fn calculate_corners(i: &Intersection, map: &Map) -> Vec<Polygon> {
|
||||
// TODO Temporarily public for debugging.
|
||||
pub fn calculate_corners(i: &Intersection, map: &Map) -> Vec<Polygon> {
|
||||
let mut corners = Vec::new();
|
||||
|
||||
for turn in &map.get_turns_in_intersection(i.id) {
|
||||
|
@ -17,7 +17,7 @@ pub use crate::render::area::DrawArea;
|
||||
use crate::render::bike::DrawBike;
|
||||
use crate::render::car::DrawCar;
|
||||
pub use crate::render::extra_shape::ExtraShapeID;
|
||||
pub use crate::render::intersection::{draw_signal_cycle, draw_signal_diagram};
|
||||
pub use crate::render::intersection::{calculate_corners, draw_signal_cycle, draw_signal_diagram};
|
||||
pub use crate::render::lane::DrawLane;
|
||||
pub use crate::render::map::{AgentCache, DrawMap};
|
||||
pub use crate::render::pedestrian::DrawPedestrian;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::{raw_data, LaneID, LaneType, Map, RoadID, TurnID};
|
||||
use crate::{raw_data, LaneID, LaneType, Map, Road, RoadID, TurnID};
|
||||
use abstutil;
|
||||
use geom::{Distance, Polygon, Pt2D};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
@ -78,16 +78,19 @@ impl Intersection {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn get_roads_sorted_by_incoming_angle(&self, map: &Map) -> Vec<RoadID> {
|
||||
pub fn get_roads_sorted_by_incoming_angle(&self, all_roads: &Vec<Road>) -> Vec<RoadID> {
|
||||
let center = self.polygon.center();
|
||||
let mut roads: Vec<RoadID> = self.roads.iter().cloned().collect();
|
||||
roads.sort_by_key(|id| {
|
||||
let r = map.get_r(*id);
|
||||
let last_line = if r.dst_i == self.id {
|
||||
r.center_pts.last_line()
|
||||
let r = &all_roads[id.0];
|
||||
let endpt = if r.src_i == self.id {
|
||||
r.center_pts.first_pt()
|
||||
} else if r.dst_i == self.id {
|
||||
r.center_pts.last_pt()
|
||||
} else {
|
||||
r.center_pts.first_line().reverse()
|
||||
unreachable!();
|
||||
};
|
||||
last_line.angle().normalized_degrees() as i64
|
||||
endpt.angle_to(center).normalized_degrees() as i64
|
||||
});
|
||||
roads
|
||||
}
|
||||
|
@ -136,11 +136,7 @@ pub fn make_half_map(
|
||||
i.intersection_type = IntersectionType::Border;
|
||||
}
|
||||
|
||||
for t in make::turns::make_all_turns(
|
||||
i,
|
||||
&half_map.roads.iter().collect(),
|
||||
&half_map.lanes.iter().collect(),
|
||||
) {
|
||||
for t in make::turns::make_all_turns(i, &half_map.roads, &half_map.lanes) {
|
||||
assert!(!half_map.turns.contains_key(&t.id));
|
||||
i.turns.push(t.id);
|
||||
half_map.turns.insert(t.id, t);
|
||||
|
@ -8,7 +8,7 @@ use nbez::{Bez3o, BezCurve, Point2d};
|
||||
use std::collections::{BTreeSet, HashSet};
|
||||
use std::iter;
|
||||
|
||||
pub fn make_all_turns(i: &Intersection, roads: &Vec<&Road>, lanes: &Vec<&Lane>) -> Vec<Turn> {
|
||||
pub fn make_all_turns(i: &Intersection, roads: &Vec<Road>, lanes: &Vec<Lane>) -> Vec<Turn> {
|
||||
if i.intersection_type == IntersectionType::Border {
|
||||
return Vec::new();
|
||||
}
|
||||
@ -61,8 +61,8 @@ fn dedupe(turns: Vec<Turn>) -> Vec<Turn> {
|
||||
keep
|
||||
}
|
||||
|
||||
fn make_vehicle_turns(i: &Intersection, all_roads: &Vec<&Road>, lanes: &Vec<&Lane>) -> Vec<Turn> {
|
||||
let roads: Vec<&Road> = i.roads.iter().map(|r| all_roads[r.0]).collect();
|
||||
fn make_vehicle_turns(i: &Intersection, all_roads: &Vec<Road>, lanes: &Vec<Lane>) -> Vec<Turn> {
|
||||
let roads: Vec<&Road> = i.roads.iter().map(|r| &all_roads[r.0]).collect();
|
||||
let mut lane_types: BTreeSet<LaneType> = BTreeSet::new();
|
||||
for r in &roads {
|
||||
let (t1, t2) = r.get_lane_types();
|
||||
@ -143,7 +143,7 @@ fn make_vehicle_turns(i: &Intersection, all_roads: &Vec<&Road>, lanes: &Vec<&Lan
|
||||
}
|
||||
|
||||
fn match_up_lanes(
|
||||
lanes: &Vec<&Lane>,
|
||||
lanes: &Vec<Lane>,
|
||||
i: IntersectionID,
|
||||
incoming: &Vec<LaneID>,
|
||||
outgoing: &Vec<LaneID>,
|
||||
@ -182,11 +182,11 @@ fn match_up_lanes(
|
||||
|
||||
fn make_vehicle_turns_for_dead_end(
|
||||
i: &Intersection,
|
||||
roads: &Vec<&Road>,
|
||||
lanes: &Vec<&Lane>,
|
||||
roads: &Vec<Road>,
|
||||
lanes: &Vec<Lane>,
|
||||
lane_type: LaneType,
|
||||
) -> Vec<Turn> {
|
||||
let road = roads[i.roads.iter().next().unwrap().0];
|
||||
let road = &roads[i.roads.iter().next().unwrap().0];
|
||||
let incoming = filter_vehicle_lanes(road.incoming_lanes(i.id), lane_type);
|
||||
let outgoing = filter_vehicle_lanes(road.outgoing_lanes(i.id), lane_type);
|
||||
if incoming.is_empty() || outgoing.is_empty() {
|
||||
@ -197,29 +197,14 @@ fn make_vehicle_turns_for_dead_end(
|
||||
match_up_lanes(lanes, i.id, &incoming, &outgoing)
|
||||
}
|
||||
|
||||
fn make_walking_turns(i: &Intersection, all_roads: &Vec<&Road>, lanes: &Vec<&Lane>) -> Vec<Turn> {
|
||||
// Sort roads by the angle into the intersection, so we can reason about sidewalks of adjacent
|
||||
// roads.
|
||||
let mut roads: Vec<&Road> = i.roads.iter().map(|id| all_roads[id.0]).collect();
|
||||
roads.sort_by_key(|r| {
|
||||
if r.src_i == i.id {
|
||||
r.center_pts
|
||||
.reversed()
|
||||
.last_line()
|
||||
.angle()
|
||||
.normalized_degrees() as i64
|
||||
} else if r.dst_i == i.id {
|
||||
r.center_pts.last_line().angle().normalized_degrees() as i64
|
||||
} else {
|
||||
panic!(
|
||||
"Incident road {} doesn't have an endpoint at {}",
|
||||
r.id, i.id
|
||||
);
|
||||
}
|
||||
});
|
||||
fn make_walking_turns(i: &Intersection, all_roads: &Vec<Road>, lanes: &Vec<Lane>) -> Vec<Turn> {
|
||||
let roads: Vec<&Road> = i
|
||||
.get_roads_sorted_by_incoming_angle(all_roads)
|
||||
.into_iter()
|
||||
.map(|id| &all_roads[id.0])
|
||||
.collect();
|
||||
|
||||
let mut result: Vec<Turn> = Vec::new();
|
||||
|
||||
for idx1 in 0..roads.len() {
|
||||
if let Some(l1) = get_sidewalk(lanes, roads[idx1].incoming_lanes(i.id)) {
|
||||
// Make the crosswalk to the other side
|
||||
@ -260,7 +245,6 @@ fn make_walking_turns(i: &Intersection, all_roads: &Vec<&Road>, lanes: &Vec<&Lan
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
@ -289,10 +273,10 @@ fn turn_id(parent: IntersectionID, src: LaneID, dst: LaneID) -> TurnID {
|
||||
TurnID { parent, src, dst }
|
||||
}
|
||||
|
||||
fn get_sidewalk<'a>(lanes: &'a Vec<&Lane>, children: &Vec<(LaneID, LaneType)>) -> Option<&'a Lane> {
|
||||
fn get_sidewalk<'a>(lanes: &'a Vec<Lane>, children: &Vec<(LaneID, LaneType)>) -> Option<&'a Lane> {
|
||||
for (id, lt) in children {
|
||||
if *lt == LaneType::Sidewalk {
|
||||
return Some(lanes[id.0]);
|
||||
return Some(&lanes[id.0]);
|
||||
}
|
||||
}
|
||||
None
|
||||
@ -313,9 +297,9 @@ fn filter_lanes(lanes: &Vec<(LaneID, LaneType)>, filter: LaneType) -> Vec<LaneID
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn make_vehicle_turn(lanes: &Vec<&Lane>, i: IntersectionID, l1: LaneID, l2: LaneID) -> Turn {
|
||||
let src = lanes[l1.0];
|
||||
let dst = lanes[l2.0];
|
||||
fn make_vehicle_turn(lanes: &Vec<Lane>, i: IntersectionID, l1: LaneID, l2: LaneID) -> Turn {
|
||||
let src = &lanes[l1.0];
|
||||
let dst = &lanes[l2.0];
|
||||
let turn_type = TurnType::from_angles(src.last_line().angle(), dst.first_line().angle());
|
||||
|
||||
let geom = if turn_type == TurnType::Straight {
|
||||
|
@ -190,7 +190,9 @@ impl ControlTrafficSignal {
|
||||
}
|
||||
|
||||
// Just to refer to these easily, label with directions. Imagine an axis-aligned four-way.
|
||||
let roads = map.get_i(i).get_roads_sorted_by_incoming_angle(map);
|
||||
let roads = map
|
||||
.get_i(i)
|
||||
.get_roads_sorted_by_incoming_angle(map.all_roads());
|
||||
let (north, west, south, east) = (roads[0], roads[1], roads[2], roads[3]);
|
||||
|
||||
// Two-phase with no protected lefts, right turn on red, peds yielding to cars
|
||||
@ -256,7 +258,9 @@ impl ControlTrafficSignal {
|
||||
}
|
||||
|
||||
// Just to refer to these easily, label with directions. Imagine an axis-aligned four-way.
|
||||
let roads = map.get_i(i).get_roads_sorted_by_incoming_angle(map);
|
||||
let roads = map
|
||||
.get_i(i)
|
||||
.get_roads_sorted_by_incoming_angle(map.all_roads());
|
||||
let (north, west, south, east) = (roads[0], roads[1], roads[2], roads[3]);
|
||||
|
||||
// Two-phase with no protected lefts, right turn on red, turning cars yielding to peds
|
||||
|
Loading…
Reference in New Issue
Block a user