Skip to content

Commit

Permalink
WIP #204
Browse files Browse the repository at this point in the history
  • Loading branch information
dabreegster committed Feb 18, 2023
1 parent 687ee0e commit 3a6457f
Show file tree
Hide file tree
Showing 11 changed files with 3,444 additions and 2 deletions.
51 changes: 50 additions & 1 deletion osm2streets/src/geometry/general_case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use geom::{InfiniteLine, PolyLine, Pt2D};

use super::{polygon_from_corners, Results};
use crate::road::RoadEdge;
use crate::{InputRoad, RoadID};
use crate::{InputRoad, RoadID, CommonEndpoint};

/// Handles intersections with at least 3 roads.
pub fn trim_to_corners(
Expand All @@ -16,10 +16,19 @@ pub fn trim_to_corners(
// TODO Take Road instead of InputRoad to avoid this
let mut sorted_roads = Vec::new();
let mut orig_centers = BTreeMap::new();
let mut intersection_endpoints = BTreeMap::new();
for id in &sorted_road_ids {
let road = &roads[id];
sorted_roads.push(road.to_road());
orig_centers.insert(*id, road.center_line.clone());

if results.intersection_id.0 == 5 {
//info!("one of sorted input roads is {id}");
}

// What does overwriting mean?
intersection_endpoints.insert(road.src_i, road.center_line.first_pt());
intersection_endpoints.insert(road.dst_i, road.center_line.last_pt());
}

// Look at every adjacent pair of edges
Expand All @@ -41,6 +50,33 @@ pub fn trim_to_corners(
// Fix upstream.
if one.pl.last_pt() == two.pl.last_pt() {
pt = one.pl.last_pt();
error!("the weird case!!! {}, {}, {}", one.road, two.road, results.intersection_id);
}


// Do the roads form a loop?
if CommonEndpoint::new((roads[&one.road].src_i, roads[&one.road].dst_i), (roads[&two.road].src_i, roads[&two.road].dst_i)) == CommonEndpoint::Both {
let should_be_small = intersection_endpoints[&results.intersection_id].dist_to(pt);
// The other intersection
let other_i = if roads[&one.road].src_i == results.intersection_id {
roads[&one.road].dst_i
} else {
roads[&one.road].src_i
};
let should_be_large = intersection_endpoints[&other_i].dist_to(pt);

error!("WARNING! we have a loop. this side {should_be_small}, other side {should_be_large}");

// hit point closer to the wrong side
if should_be_small > should_be_large {
continue;
}
}


results.debug.push((pt, format!("X from {} and {} at {}", one.road, two.road, results.intersection_id)));
if results.intersection_id.0 == 5 || results.intersection_id.0 == 9 {
info!("X from {} {:?} and {} {:?} at {}... {}", one.road, one.side, two.road, two.side, results.intersection_id, pt);
}

// For both edges, project perpendicularly back to the original center, and trim back
Expand All @@ -61,10 +97,20 @@ pub fn trim_to_corners(
for trim_to in all_intersection_infinite(&center_away, &perp) {
trim_candidates.extend(center_away.get_slice_starting_at(trim_to));
}

if results.intersection_id.0 == 5 {
//info!("btwn {} {:?} and {} {:?} for {}, we have trim candidates {:?}", one.road, one.side, two.road, two.side, side.road, trim_candidates.iter().map(|pl| pl.length()).collect::<Vec<_>>());
for x in &trim_candidates {
//results.debug_pl.push((x.clone(), "trimcan".to_string()));
}
}


// Find the candidate producing the minimal trim, aka, the hit closest to the
// intersection.
if let Some(mut trimmed) =
trim_candidates.into_iter().max_by_key(|pl| pl.length())
//trim_candidates.into_iter().min_by_key(|pl| pl.first_pt().dist_to(pt))
{
// Every road has two sides, so we'll generate two potential trims. Take
// the shortest.
Expand All @@ -73,6 +119,9 @@ pub fn trim_to_corners(
if roads[&side.road].dst_i == results.intersection_id {
trimmed = trimmed.reversed();
}
if results.intersection_id.0 == 5 || results.intersection_id.0 == 9 {
info!("trimming {} from {} to {}, due to hit btwn {} {:?} and {} {:?} at {}", side.road, roads[&side.road].center_line.length(), trimmed.length(), one.road, one.side, two.road, two.side, results.intersection_id);
}
roads.get_mut(&side.road).unwrap().center_line = trimmed;
}
}
Expand Down
2 changes: 2 additions & 0 deletions osm2streets/src/geometry/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ pub struct Results {
pub trim_ends: BTreeMap<RoadID, Distance>,
/// Extra points with labels to debug the algorithm
pub debug: Vec<(Pt2D, String)>,
pub debug_pl: Vec<(PolyLine, String)>,
}

/// Trims back all roads connected to the intersection, and generates a polygon for the
Expand All @@ -115,6 +116,7 @@ pub fn intersection_polygon(
intersection_id,
intersection_polygon: Polygon::dummy(),
debug: Vec::new(),
debug_pl: Vec::new(),
trimmed_center_pts: BTreeMap::new(),
trim_starts: BTreeMap::new(),
trim_ends: BTreeMap::new(),
Expand Down
10 changes: 9 additions & 1 deletion osm2streets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,10 @@ impl StreetNetwork {
}

pub(crate) fn start_debug_step<I: Into<String>>(&mut self, label: I) {
let label = label.into();
info!("debug step {label} ----------");
let copy = DebugStreets {
label: label.into(),
label,
streets: StreetNetwork {
roads: self.roads.clone(),
intersections: self.intersections.clone(),
Expand Down Expand Up @@ -193,6 +195,12 @@ impl StreetNetwork {
step.points.push((pt, label.into()));
}
}

pub(crate) fn debug_pl<I: Into<String>>(&mut self, pl: PolyLine, label: I) {
if let Some(step) = self.debug_steps.last_mut() {
step.polylines.push((pl, label.into()));
}
}
}

#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
Expand Down
3 changes: 3 additions & 0 deletions osm2streets/src/operations/update_geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ impl StreetNetwork {
for (pt, label) in results.debug {
self.debug_point(pt, label);
}
for (pl, label) in results.debug_pl {
self.debug_pl(pl, label);
}
}
Err(err) => {
error!("Can't make intersection geometry for {}: {}", i.id, err);
Expand Down
8 changes: 8 additions & 0 deletions osm2streets/src/road.rs
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,8 @@ pub(crate) struct RoadEdge {
/// Pointed into the intersection
pub pl: PolyLine,
pub lane: LaneSpec,
// TODO abusing the type
pub side: DrivingSide,
}

impl RoadEdge {
Expand All @@ -578,13 +580,19 @@ impl RoadEdge {
road: road.id,
pl: road.center_line.must_shift_left(road.half_width()),
lane: road.lane_specs_ltr[0].clone(),
side: DrivingSide::Left,
};
let mut right = RoadEdge {
road: road.id,
pl: road.center_line.must_shift_right(road.half_width()),
lane: road.lane_specs_ltr.last().unwrap().clone(),
side: DrivingSide::Right,
};
// TODO If road.src_i == road.dst_i == i, what happens?
if road.dst_i == i {
if road.src_i == i {
error!("!!!!!!! RoadEdge found road {}, loop on {}", road.id, i);
}
edges.push(right);
edges.push(left);
} else {
Expand Down
1 change: 1 addition & 0 deletions street-explorer/js/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export function loadTests() {
"bristol_contraflow_cycleway",
"bristol_sausage_links",
"cycleway_rejoin_road",
"degenerate_bug",
"fremantle_placement",
"i5_exit_ramp",
"kingsway_junction",
Expand Down
1 change: 1 addition & 0 deletions tests/src/degenerate_bug/boundary.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-2.535191,51.47669],[-2.537364,51.475727],[-2.538341,51.474921],[-2.537759,51.474204],[-2.53404,51.475671],[-2.533891,51.476376],[-2.535191,51.47669]]]}}]}
Loading

0 comments on commit 3a6457f

Please sign in to comment.