-
-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Start modelling movements at intersections #93
Changes from all commits
54daaef
56f97fe
7b8ac89
ae3fa6f
c6d6cd7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -214,6 +214,20 @@ pub fn make_arrow(line: Line, thickness: f64, double_ended: bool) -> Option<Poly | |
Some(Polygon::new(LineString::new(pts), Vec::new())) | ||
} | ||
|
||
pub fn thicken_line(line: Line, thickness: f64) -> Polygon { | ||
let angle = angle_of_line(line); | ||
Polygon::new( | ||
LineString::new(vec![ | ||
euclidean_destination_coord(line.start, angle - 90.0, thickness * 0.5), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I should put this in geo... unfortunately I have a big open LineMeasure change in PR limbo that I'd like to resolve first... I'll go kick that to see if it's still alive. 🤔 |
||
euclidean_destination_coord(line.end, angle - 90.0, thickness * 0.5), | ||
euclidean_destination_coord(line.end, angle + 90.0, thickness * 0.5), | ||
euclidean_destination_coord(line.start, angle + 90.0, thickness * 0.5), | ||
euclidean_destination_coord(line.start, angle - 90.0, thickness * 0.5), | ||
]), | ||
Vec::new(), | ||
) | ||
} | ||
|
||
/// Create a polygon covering the world, minus a hole for the input polygon. Assumes the input is | ||
/// in WGS84 and has no holes itself. | ||
pub fn invert_polygon(wgs84_polygon: Polygon) -> Polygon { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
use geo::{Euclidean, Length, Line, LineInterpolatePoint, Point, Polygon}; | ||
use geojson::GeoJson; | ||
|
||
use crate::{ | ||
geo_helpers::{make_arrow, thicken_line}, | ||
Direction, IntersectionID, MapModel, Road, | ||
}; | ||
|
||
impl MapModel { | ||
pub fn get_movements(&self, i: IntersectionID) -> GeoJson { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No biggie so take it or leave it: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To minimize churn, I'll leave this for now. Right now it's a debug mode, but that will probably turn into some kind of "edit turn restrictions at an intersection" mode, and the movements sent over will have a semantic ID that the backend knows how to edit. |
||
let mut features = Vec::new(); | ||
|
||
let intersection = self.get_i(i); | ||
for r1 in &intersection.roads { | ||
for r2 in &intersection.roads { | ||
// TODO Handle u-turns at dead-ends | ||
if r1 == r2 { | ||
continue; | ||
} | ||
let road1 = self.get_r(*r1); | ||
let road2 = self.get_r(*r2); | ||
|
||
// If road1 is one-way, can we go towards i? | ||
let ok1 = match self.directions[r1] { | ||
Direction::BothWays => true, | ||
Direction::Forwards => road1.dst_i == i, | ||
Direction::Backwards => road1.src_i == i, | ||
}; | ||
// If road2 is one-way, can we go away from i? | ||
let ok2 = match self.directions[r2] { | ||
Direction::BothWays => true, | ||
Direction::Forwards => road2.src_i == i, | ||
Direction::Backwards => road2.dst_i == i, | ||
}; | ||
if !ok1 || !ok2 { | ||
continue; | ||
} | ||
|
||
// Is there a turn restriction between this pair? | ||
if intersection.turn_restrictions.contains(&(*r1, *r2)) { | ||
continue; | ||
} | ||
|
||
let polygon = render_arrow(i, road1, road2); | ||
features.push(self.mercator.to_wgs84_gj(&polygon)); | ||
} | ||
} | ||
|
||
GeoJson::from(features) | ||
} | ||
} | ||
|
||
fn render_arrow(i: IntersectionID, road1: &Road, road2: &Road) -> Polygon { | ||
let line = Line::new( | ||
pt_near_intersection(i, road1), | ||
pt_near_intersection(i, road2), | ||
); | ||
let thickness = 2.0; | ||
let double_ended = false; | ||
make_arrow(line, thickness, double_ended).unwrap_or_else(|| thicken_line(line, thickness)) | ||
} | ||
|
||
fn pt_near_intersection(i: IntersectionID, road: &Road) -> Point { | ||
// If the road is long enough, offset from the intersection this much | ||
let distance_away = 10.0; | ||
let len = road.linestring.length::<Euclidean>(); | ||
|
||
if len > distance_away { | ||
let pct = if road.src_i == i { | ||
distance_away / len | ||
} else { | ||
1.0 - (distance_away / len) | ||
}; | ||
return road.linestring.line_interpolate_point(pct).unwrap(); | ||
} | ||
|
||
// If not, just take the other endpoint | ||
let pct = if road.src_i == i { 1.0 } else { 0.0 }; | ||
road.linestring.line_interpolate_point(pct).unwrap() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not very familiar with this logic yet, but should these be
continue
?