work around path traces that're breaking PolyLine

This commit is contained in:
Dustin Carlino 2019-05-24 16:01:00 -07:00
parent 1cdbe0ea81
commit 01a4abb64a
8 changed files with 43 additions and 16 deletions

View File

@ -467,7 +467,7 @@ fn recalc_intersection_geom(id: IntersectionID, map: &Map, g: &mut GfxCtx) {
let (pl1, width1) = wraparound_get(&road_centers, idx); let (pl1, width1) = wraparound_get(&road_centers, idx);
let (pl2, width2) = wraparound_get(&road_centers, idx + 1); let (pl2, width2) = wraparound_get(&road_centers, idx + 1);
let glued = pl1.clone().extend(&pl2.reversed()); let glued = pl1.clone().extend(&pl2.reversed()).unwrap();
let max_width = (*width1).max(*width2); let max_width = (*width1).max(*width2);
let poly = Polygon::new(&glued.to_thick_boundary_pts(max_width)); let poly = Polygon::new(&glued.to_thick_boundary_pts(max_width));
g.draw_polygon(Color::RED.alpha(0.4), &poly); g.draw_polygon(Color::RED.alpha(0.4), &poly);

View File

@ -21,7 +21,7 @@ impl TripsVisualizer {
let trips = ctx.loading_screen("load trip data", |_, mut timer| { let trips = ctx.loading_screen("load trip data", |_, mut timer| {
let popdat: PopDat = abstutil::read_binary("../data/shapes/popdat", &mut timer) let popdat: PopDat = abstutil::read_binary("../data/shapes/popdat", &mut timer)
.expect("Couldn't load popdat"); .expect("Couldn't load popdat");
let mut all_trips = clip_trips(&popdat, ui, &mut timer); let mut all_trips = clip_trips(&popdat, ui, 1_000, &mut timer);
let requests = all_trips let requests = all_trips
.iter() .iter()
.map(|trip| trip.path_req(&ui.primary.map)) .map(|trip| trip.path_req(&ui.primary.map))

View File

@ -30,7 +30,7 @@ impl TripsVisualizer {
], ],
ctx, ctx,
), ),
trips: clip_trips(&popdat, ui, &mut timer), trips: clip_trips(&popdat, ui, 10_000, &mut timer),
// TODO We'll break if there are no matching trips // TODO We'll break if there are no matching trips
current: 0, current: 0,
} }

View File

@ -190,12 +190,21 @@ impl Trip {
} }
} }
pub fn clip_trips(popdat: &popdat::PopDat, ui: &UI, timer: &mut Timer) -> Vec<Trip> { // TODO max_results just temporary for development.
pub fn clip_trips(
popdat: &popdat::PopDat,
ui: &UI,
max_results: usize,
timer: &mut Timer,
) -> Vec<Trip> {
let mut results = Vec::new(); let mut results = Vec::new();
let bounds = ui.primary.map.get_gps_bounds(); let bounds = ui.primary.map.get_gps_bounds();
timer.start_iter("clip trips", popdat.trips.len()); timer.start_iter("clip trips", popdat.trips.len());
for trip in &popdat.trips { for trip in &popdat.trips {
timer.next(); timer.next();
if results.len() == max_results {
continue;
}
if !bounds.contains(trip.from) || !bounds.contains(trip.to) { if !bounds.contains(trip.from) || !bounds.contains(trip.to) {
continue; continue;
} }

View File

@ -38,11 +38,7 @@ impl PolyLine {
// Can't have duplicates! If the polyline ever crosses back on itself, all sorts of things // Can't have duplicates! If the polyline ever crosses back on itself, all sorts of things
// are broken. // are broken.
let seen_pts: HashSet<HashablePt2D> = result let seen_pts = to_set(result.points());
.points()
.iter()
.map(|pt| HashablePt2D::from(*pt))
.collect();
if seen_pts.len() != result.points().len() { if seen_pts.len() != result.points().len() {
panic!("PolyLine has repeat points: {}", result); panic!("PolyLine has repeat points: {}", result);
} }
@ -95,10 +91,17 @@ impl PolyLine {
PolyLine::new(pts) PolyLine::new(pts)
} }
// TODO Rename append, make a prepend that just flips the arguments // Returns None if the two have any duplicate points (besides the last->first).
pub fn extend(self, other: &PolyLine) -> PolyLine { pub fn extend(self, other: &PolyLine) -> Option<PolyLine> {
assert_eq!(*self.pts.last().unwrap(), other.pts[0]); assert_eq!(*self.pts.last().unwrap(), other.pts[0]);
let pl1 = to_set(self.points());
let pl2 = to_set(&other.points()[1..]);
if pl1.intersection(&pl2).next().is_some() {
println!("Can't append, duplicate points... {} and {}", self, other);
return None;
}
// There's an exciting edge case: the next point to add is on self's last line. // There's an exciting edge case: the next point to add is on self's last line.
let same_line = self let same_line = self
.last_line() .last_line()
@ -109,7 +112,7 @@ impl PolyLine {
pts.pop(); pts.pop();
} }
pts.extend(other.pts.iter().skip(1)); pts.extend(other.pts.iter().skip(1));
PolyLine::new(pts) Some(PolyLine::new(pts))
} }
// One or both args might be empty. // One or both args might be empty.
@ -123,6 +126,7 @@ impl PolyLine {
PolyLine::new(first) PolyLine::new(first)
.extend(&PolyLine::new(second)) .extend(&PolyLine::new(second))
.unwrap()
.points() .points()
.clone() .clone()
} }
@ -653,3 +657,7 @@ fn check_angles(orig: &PolyLine, fixed: PolyLine) -> Warn<PolyLine> {
} }
Warn::warnings(fixed, warnings) Warn::warnings(fixed, warnings)
} }
fn to_set(pts: &[Pt2D]) -> HashSet<HashablePt2D> {
pts.iter().map(|pt| HashablePt2D::from(*pt)).collect()
}

View File

@ -128,14 +128,14 @@ fn merge(
.original_center_pts .original_center_pts
.get_slice_starting_at(r.trimmed_center_pts.last_pt()) .get_slice_starting_at(r.trimmed_center_pts.last_pt())
{ {
r.trimmed_center_pts = r.trimmed_center_pts.clone().extend(&append); r.trimmed_center_pts = r.trimmed_center_pts.clone().extend(&append).unwrap();
} }
} else { } else {
if let Some(prepend) = r if let Some(prepend) = r
.original_center_pts .original_center_pts
.get_slice_ending_at(r.trimmed_center_pts.first_pt()) .get_slice_ending_at(r.trimmed_center_pts.first_pt())
{ {
r.trimmed_center_pts = prepend.extend(&r.trimmed_center_pts); r.trimmed_center_pts = prepend.extend(&r.trimmed_center_pts).unwrap();
} }
} }
} }

View File

@ -215,8 +215,16 @@ impl Path {
self.steps[i].slice(map, start_dist_this_step, dist_remaining) self.steps[i].slice(map, start_dist_this_step, dist_remaining)
{ {
if pts_so_far.is_some() { if pts_so_far.is_some() {
let pts = pts_so_far.unwrap().extend(&new_pts); if let Some(pts) = pts_so_far.unwrap().extend(&new_pts) {
pts_so_far = Some(pts); pts_so_far = Some(pts);
} else {
println!(
"Adding {:?} to {:?} causes duplicate points!",
self.steps[i],
self.steps.iter().take(i).collect::<Vec<&PathStep>>()
);
return None;
}
} else { } else {
pts_so_far = Some(new_pts); pts_so_far = Some(new_pts);
} }

View File

@ -3,6 +3,8 @@ fn main() {
let mut popdat = popdat::PopDat::import_all(&mut timer); let mut popdat = popdat::PopDat::import_all(&mut timer);
// TODO Productionize this. // TODO Productionize this.
// https://file.ac/cLdO7Hp_OB0/ has trips_2014.csv. https://file.ac/Xdjmi8lb2dA/ has the 2014
// inputs.
let parcels = popdat::psrc::import_parcels( let parcels = popdat::psrc::import_parcels(
"/home/dabreegster/Downloads/psrc/2014/landuse/parcels_urbansim.txt", "/home/dabreegster/Downloads/psrc/2014/landuse/parcels_urbansim.txt",
&mut timer, &mut timer,