Skip to content

Ystripes#1101

Open
sethhillbrand wants to merge 3 commits into
AngusJohnson:mainfrom
sethhillbrand:ystripes
Open

Ystripes#1101
sethhillbrand wants to merge 3 commits into
AngusJohnson:mainfrom
sethhillbrand:ystripes

Conversation

@sethhillbrand

@sethhillbrand sethhillbrand commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Hi @AngusJohnson !

A while ago, I wrote a point-in-polygon implementation for KiCad that uses ystripes. It works really well to speed things up relative to our various other algorithms that we used. Eventually, one of our clients came to us with a slow zone fill even in the new system. Profiling showed that one of the bottlenecks was in assigning hierarchy in PolyTrees for boolean ops.

To fix this, I adapted the ystripes algorithm to Clipper2 and tested with our realworld data (as well as the existing Clipper2 adversarial data). Because the algorithm doesn't work well for small polygons, it has a fail-safe that falls back to the original algo at 64 edges. For this reason, we see a worst-case speed-up of 1.0x.

What follows is my testing data on a Intel Core i9-13900KF · Debian 13 (kernel 6.12) · single-threaded, best of 5 results for both baseline and y-stripe.

Language / Build Workload Previous (baseline) Current (Y-stripe) Speedup
C++ (-O2) subtract — 286k pts, parent owns 1341 children 516 ms 122 ms 4.2×
C++ (-O2) inflate — 195k pts 887 ms 448 ms 2.0×
C# (Release, .NET 8) subtract — 286k pts 553 ms 176 ms 3.15×
C# (Release, .NET 8) inflate — 195k pts 877 ms 454 ms 1.93×
Delphi (fpc -O2) synthetic — 20k-vertex outer, 1472 holes 84 ms 10 ms 8.4×

I couldn't find a QA system for Delphi, so I just made a small self-contained app that tested this.

I wrote this originally in C++ and ported to C# and Delphi (which are not my native languages) so please let me know if I made any mistakes. They both compile, run correctly per the QA. The C++ version is tested in KiCad as well.

StripeIndex buckets a ring's edges into horizontal Y stripes so PolyTree nesting
tests child vertices in ~O(sqrt n) instead of O(n) per query. Wired into
owner/split containment behind an edge-count threshold, with a brute-force
fallback for small or adversarial rings. Includes unit, differential, and
real-world QA.
Mirrors the C++ StripeIndex: per-ring Y-stripe bucketing for PolyTree nesting
with a brute-force fallback below the edge-count threshold. Adds the StripeIndex
test suite.
Mirrors the C++ StripeIndex: per-ring Y-stripe bucketing for PolyTree nesting
with a brute-force fallback below the edge-count threshold. Adds a standalone
console QA program.
@AngusJohnson

AngusJohnson commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Hi Seth.
Thank you again for your very helpful contributions to this library. And these changes evidently significantly improve performance. But they also require significant changes to the code that I'd like to understand before merging. However, since I'm currently tied up with another project that is taking much longer than I expected, I'm not sure when I'll get an opportunity to look at this (I'm guessing another few weeks at least). Cheers.

@sethhillbrand

Copy link
Copy Markdown
Contributor Author

@AngusJohnson take your time and let me know if I can help at all

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants