Repository navigation
Break long ear fans in the hashed loop - #212
Merged
Merged
Conversation
Since 3.1.0 (mapbox#195) the loop continues from the vertex after a cut ear, so on a convex run every ear is cut from the same vertex. The fan triangles are long, their z-order range covers a large part of the polygon, and each hashed ear check scans O(n) points: a regular 10k-gon is triangulated in quadratic time. After 32 ears cut in a row, step one vertex further if that vertex is convex (past a reflex one the loop would walk the ring to the next ear). Shorter fans are left alone: 119,677 of the 119,680 polygons in the tiles fixture get the same triangles as before.
No vertex of a strictly convex ring is reflex, so no point can block an ear and every point check passes; cutting an ear keeps the ring convex. The loop now skips the point checks for such a ring until the first candidate fails, instead of stepping past the apex of a long fan. The output is the same as in 3.2.4 index for index.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #211.
After 32 ears cut in a row, the hashed loop now steps one vertex further if that vertex is convex. That ends the fan described in #211. Shorter fans and polygons with up to 80 vertices (the non-hashed path) are not affected. 119,677 of the 119,680 polygons in the tiles fixture get the same triangles as before, and all test expectations still hold.
Median ms per call; each cell shows two separate runs as
first ; second:bench/bench-tiles.jsThe one slowdown I found: right after a regular 10k-gon in the same process, a 10k circle with a ±15 % random radius takes 9.21 ; 8.90 ms vs 6.83 ; 6.66 ms on 3.2.4. In a fresh process both take 7.3 ; 7.1 ms; see Details.
Details
ear = next.next. It fixes circles too, but a comb with n/4 deep teeth gets slower than in 3.2.4: 10k takes 114 ; 106 → 181 ; 182 ms.isEarHashedrather than more work, so I left it out of scope.ear = next.nextrestored does the same work on it as this PR, so that gap does not come from the fan.Apple M3 Pro, Node v26.8.2, load average 1.4–3.4.