cleaning up after polyline trimming

This commit is contained in:
Dustin Carlino 2018-07-23 10:01:35 -07:00
parent 342870f6ab
commit 7ee8ef0d8d
5 changed files with 26 additions and 50 deletions

View File

@ -55,10 +55,6 @@
- first figure out all the trimming cases for the T, outside and inside lanes, etc
- aha, big bug! we only try to trim first/last lines. do the whole polyline.
- can think of an easy fixpoint approach to try first, even though it's inefficient.
- wait, the fixpoint is also incorrect. :(
- before trimming back lines, project out the correct width. sort all those points by angle from the center. thats the intersection polygon? then somehow trim back lines to hit that nicely.
- do the current trim_lines thing, but with lines, not segments? no, there'd be many almost-parallel lines.

View File

@ -270,16 +270,16 @@ impl UI {
fn trim_polyline(&self, g: &mut GfxCtx, _labels: &mut Vec<(Pt2D, String)>) {
let mut vertical_pl = PolyLine::new(vec![
Pt2D::new(1333.9512635794777, 413.3946082988369),
Pt2D::new(1333.994382315137, 412.98183477602896),
Pt2D::new(1334.842742789155, 408.38697863519786),
Pt2D::new(1341.8334675664184, 388.5049183955915),
Pt2D::new(1343.4401359706367, 378.05011956849677),
Pt2D::new(1344.2823018114202, 367.36774792310285),
Pt2D::new(1333.9512635794777, 413.3946082988369),
Pt2D::new(1333.994382315137, 412.98183477602896),
Pt2D::new(1334.842742789155, 408.38697863519786),
Pt2D::new(1341.8334675664184, 388.5049183955915),
Pt2D::new(1343.4401359706367, 378.05011956849677),
Pt2D::new(1344.2823018114202, 367.36774792310285),
]).reversed();
let mut horiz_pl = PolyLine::new(vec![
Pt2D::new(1388.995635038006, 411.7906956729764),
Pt2D::new(1327.388582742321, 410.78740100896965),
Pt2D::new(1388.995635038006, 411.7906956729764),
Pt2D::new(1327.388582742321, 410.78740100896965),
]);
let hit = vertical_pl.intersection(&horiz_pl).unwrap();

View File

@ -181,23 +181,7 @@ impl PolyLine {
.collect()
}
pub fn intersects(&self, other: &PolyLine) -> bool {
// Quadratic
for pair1 in self.pts.windows(2) {
let l1 = Line::new(pair1[0], pair1[1]);
for pair2 in other.pts.windows(2) {
let l2 = Line::new(pair2[0], pair2[1]);
if l1.intersects(&l2) {
return true;
}
}
}
false
}
// index, experimental mode
pub fn intersection(&self, other: &PolyLine) -> Option<Pt2D> {
// Quadratic
for pair1 in self.pts.windows(2) {
let l1 = Line::new(pair1[0], pair1[1]);
for pair2 in other.pts.windows(2) {
@ -212,7 +196,10 @@ impl PolyLine {
// Starts trimming from the head. Assumes the pt is on the polyline somewhere.
pub fn trim_to_pt(&mut self, pt: Pt2D) {
if let Some(idx) = self.pts.windows(2).position(|pair| Line::new(pair[0], pair[1]).contains_pt(pt)) {
if let Some(idx) = self.pts
.windows(2)
.position(|pair| Line::new(pair[0], pair[1]).contains_pt(pt))
{
self.pts.truncate(idx + 1);
self.pts.push(pt);
} else {

View File

@ -6,10 +6,16 @@ use std::collections::hash_map::Entry;
use std::collections::HashMap;
pub(crate) fn trim_lines(roads: &mut Vec<Road>, i: &Intersection) {
let mut shortest_first_polyline: HashMap<RoadID, (PolyLine, si::Meter<f64>)> = HashMap::new();
let mut shortest_last_polyline: HashMap<RoadID, (PolyLine, si::Meter<f64>)> = HashMap::new();
// We update the entire polyline, not the first/last line. A polyline could be trimmed twice --
// once for each intersection it touches. Since the trimming should only affect one endpoint of
// the polyline, it's fine to do these separately and in any order.
let mut shortest_polyline: HashMap<RoadID, (PolyLine, si::Meter<f64>)> = HashMap::new();
fn update_shortest(m: &mut HashMap<RoadID, (PolyLine, si::Meter<f64>)>, r: RoadID, pl: PolyLine) {
fn update_shortest(
m: &mut HashMap<RoadID, (PolyLine, si::Meter<f64>)>,
r: RoadID,
pl: PolyLine,
) {
let new_len = pl.length();
match m.entry(r) {
@ -32,28 +38,17 @@ pub(crate) fn trim_lines(roads: &mut Vec<Road>, i: &Intersection) {
if let Some(hit) = pl1.intersection(&pl2) {
let mut new_pl1 = pl1.clone();
new_pl1.trim_to_pt(hit);
update_shortest(&mut shortest_last_polyline, *incoming, new_pl1);
update_shortest(&mut shortest_polyline, *incoming, new_pl1);
let mut new_pl2 = pl2.clone().reversed();
new_pl2.trim_to_pt(hit);
update_shortest(
&mut shortest_first_polyline,
*outgoing,
new_pl2.reversed(),
);
update_shortest(&mut shortest_polyline, *outgoing, new_pl2.reversed());
}
}
}
// Apply the updates
// TODO ah, do we kinda need to merge the two updates? hmm... shortest last will just kinda
// win. but we do this per intersection, so it should actually be fine! just simplify this.
for (id, pair) in &shortest_first_polyline {
roads[id.0]
.lane_center_pts = pair.0.clone();
}
for (id, pair) in &shortest_last_polyline {
roads[id.0]
.lane_center_pts = pair.0.clone();
for (id, pair) in &shortest_polyline {
roads[id.0].lane_center_pts = pair.0.clone();
}
}

View File

@ -99,9 +99,7 @@ pub(crate) fn make_crosswalks(i: &Intersection, m: &Map, mut turn_id_start: usiz
}
let dst_pt = dst.endpoint(i.id);
// TODO Just the first check ideally, but until line trimming handles polylines, we
// should also do the second check.
if src_pt != dst_pt && !src.lane_center_pts.intersects(&dst.lane_center_pts) {
if src_pt != dst_pt {
continue;
}