Reorder points when converting a PolyLine to a Polygon, so that the

result is usually a Ring. This gets lanes to render in the GeoJSON
export. #440

Ideally all Polygons would be expressed as an outer Ring and some
optional inner Rings. There are a few cases where this is hard, and we
instead just rely on the triangulation for rendering and point
containment and give up on GeoJSON export.

Not regenerating all maps yet -- zero screenshot diff, the map file does
change, but not sure how.
This commit is contained in:
Dustin Carlino 2021-01-01 15:03:09 -08:00
parent 302ec94e3d
commit 6119042b4f
2 changed files with 15 additions and 13 deletions

View File

@ -79,8 +79,8 @@ impl Polygon {
}
}
// TODO No guarantee points forms a ring. In fact, the main caller is PolyLine, and it's NOT
// true there yet.
// TODO No guarantee points forms a ring. In fact, the main caller is from SVG->lyon parsing,
// and it's NOT true there yet.
pub fn precomputed(points: Vec<Pt2D>, indices: Vec<usize>) -> Polygon {
assert!(indices.len() % 3 == 0);
Polygon {

View File

@ -445,13 +445,15 @@ impl PolyLine {
result
}
/// The resulting polygon is manually triangulated and doesn't have a valid outer Ring.
/// The resulting polygon is manually triangulated and may not have a valid outer Ring (but it
/// usually does).
pub fn make_polygons(&self, width: Distance) -> Polygon {
// TODO How to tune this?
self.make_polygons_with_miter_threshold(width, MITER_THRESHOLD)
}
/// The resulting polygon is manually triangulated and doesn't have a valid outer Ring.
/// The resulting polygon is manually triangulated and may not have a valid outer Ring (but it
/// usually does).
pub fn make_polygons_with_miter_threshold(
&self,
width: Distance,
@ -459,22 +461,22 @@ impl PolyLine {
) -> Polygon {
// TODO Don't use the angle corrections yet -- they seem to do weird things.
let side1 = self.shift_with_sharp_angles(width / 2.0, miter_threshold);
let side2 = self.shift_with_sharp_angles(-width / 2.0, miter_threshold);
let mut side2 = self.shift_with_sharp_angles(-width / 2.0, miter_threshold);
assert_eq!(side1.len(), side2.len());
let side2_offset = side1.len();
// Order the points so that they form a ring. No deduplication yet, though.
let len = 2 * side1.len();
let mut points = side1;
side2.reverse();
points.extend(side2);
points.push(points[0]);
let mut indices = Vec::new();
// Walk along the first side, making two triangles each step. This is easy to understand
// with a simple diagram, which I should eventually draw in ASCII art here.
for high_idx in 1..self.pts.len() {
// Duplicate first point, since that's what graphics layer expects
indices.extend(vec![high_idx, high_idx - 1, side2_offset + high_idx - 1]);
indices.extend(vec![
side2_offset + high_idx,
side2_offset + high_idx - 1,
high_idx,
]);
indices.extend(vec![high_idx, high_idx - 1, len - high_idx]);
indices.extend(vec![len - high_idx, len - high_idx - 1, high_idx]);
}
Polygon::precomputed(points, indices)
}