polygonize: optimize visvalingam_whyatt with min-heap#2817
Conversation
PR Review: polygonize: optimize visvalingam_whyatt with min-heapReviewed the heap-based rewrite of Blockers (must fix before merge)None. Suggestions (should fix, not blocking)
Nits (optional improvements)
What looks good
Checklist
|
|
@Melissari1997 [HUMAN] hey the review above is the |
brendancol
left a comment
There was a problem hiding this comment.
[HUMAN] there were a few small changes mentioned in the review-pr comment, besides that, LGTM
|
Thank you! @brendancol |
PR Review: polygonize: optimize visvalingam_whyatt with min-heap (#2817)Blockers (must fix before merge)None. Suggestions (should fix, not blocking)None — all previous findings have been addressed. Nits (optional improvements)None. What looks good
Checklist
Summary: The PR is clean, correct, and complete. No blockers. |
Implement a binary min-heap to improve the complexity of the Visvalingam-Whyatt line simplification algorithm from O(n^2) to O(n log n). The heap is keyed on triangle area, with ties broken by the smallest index to maintain consistency with the previous linear scan implementation. Lazy deletion is used to handle stale entries in the heap when vertices are removed. Added tests to ensure the heap-based implementation produces identical results to the original O(n^2) baseline.
e762bef to
409cc50
Compare
|
@Melissari1997 hey do you have a preference of WhatsApp vs. Slack vs. something else for chat / direct messaging? |
|
I think slack is ok! |
Closes #2539
Summary
Replace the O(n²) linear minimum-area scan in
_visvalingam_whyattwith a binary min-heap keyed on triangle area, achieving O(n log n) scaling for line/polygon simplification.Why this solves the performance problem
The original
_visvalingam_whyattiteratively removes the vertex with the smallest triangle areaOn each iteration it scans all remaining interior vertices to find the minimum — an O(n²) cost.
For polygon rings with tens of thousands of vertices (common in high-resolution rasters), this quadratic scan dominates runtime.
This PR replaces that linear scan with a binary min-heap storing (area, index) pairs:
_heap_pushand_heap_popsift up/down in logarithmic time, so each of the n removals costs O(log n) instead of O(n)._heap_pushedas a fresh entry. When the stale entry is popped later, the removed[idx] flag or a mismatched area tells us to skip it and pop the next one.