be a little smarter about finding hits with the boundary

This commit is contained in:
Dustin Carlino 2019-10-25 13:54:09 -07:00
parent 77d0647b4f
commit e03e3393dd
2 changed files with 26 additions and 19 deletions

View File

@ -370,19 +370,27 @@ fn glue_multipolygon(mut pts_per_way: Vec<Vec<Pt2D>>, boundary: &Ring) -> Vec<Po
polygons.push(Polygon::new(&result));
return polygons;
}
// Some ways of the multipolygon must be clipped out. First try to trace along the boundary.
let result_pl = PolyLine::new(result);
let hits = boundary.all_intersections(&result_pl);
if hits.len() != 2 {
if let Some(poly) = glue_to_boundary(PolyLine::new(result.clone()), boundary) {
polygons.push(poly);
} else {
// Give up and just connect the ends directly.
let mut pts = result_pl.points().clone();
pts.push(pts[0]);
polygons.push(Polygon::new(&pts));
return polygons;
result.push(result[0]);
polygons.push(Polygon::new(&result));
}
let trimmed_result = result_pl.trim_to_endpts(hits[0], hits[1]);
let boundary_glue = boundary.get_shorter_slice_btwn(hits[0], hits[1]);
polygons
}
fn glue_to_boundary(result_pl: PolyLine, boundary: &Ring) -> Option<Polygon> {
// Some ways of the multipolygon must be clipped out. First try to trace along the boundary.
let hit1 = boundary.first_intersection(&result_pl)?;
let hit2 = boundary.first_intersection(&result_pl.reversed())?;
if hit1 == hit2 {
return None;
}
let trimmed_result = result_pl.trim_to_endpts(hit1, hit2);
let boundary_glue = boundary.get_shorter_slice_btwn(hit1, hit2);
let mut trimmed_pts = trimmed_result.points().clone();
if trimmed_result.last_pt() == boundary_glue.first_pt() {
@ -394,8 +402,7 @@ fn glue_multipolygon(mut pts_per_way: Vec<Vec<Pt2D>>, boundary: &Ring) -> Vec<Po
trimmed_pts.extend(boundary_glue.reversed().points().clone());
}
assert_eq!(trimmed_pts[0], *trimmed_pts.last().unwrap());
polygons.push(Polygon::new(&trimmed_pts));
polygons
Some(Polygon::new(&trimmed_pts))
}
fn read_osmosis_polygon(path: &str) -> RawMap {

View File

@ -41,16 +41,16 @@ impl Ring {
PolyLine::new_for_ring(self.pts.clone()).make_polygons(thickness)
}
pub fn all_intersections(&self, other: &PolyLine) -> Vec<Pt2D> {
let mut hits = Vec::new();
for l1 in self.pts.windows(2).map(|pair| Line::new(pair[0], pair[1])) {
for l2 in other.lines() {
// Searches other in order
pub fn first_intersection(&self, other: &PolyLine) -> Option<Pt2D> {
for l1 in other.lines() {
for l2 in self.pts.windows(2).map(|pair| Line::new(pair[0], pair[1])) {
if let Some(pt) = l1.intersection(&l2) {
hits.push(pt);
return Some(pt);
}
}
}
hits
None
}
pub fn get_shorter_slice_btwn(&self, pt1: Pt2D, pt2: Pt2D) -> PolyLine {