Skip to content

Guard against over-refinement of offset curves near cusps#259

Draft
gpeairs wants to merge 3 commits into
mainfrom
gp/cusp-guard
Draft

Guard against over-refinement of offset curves near cusps#259
gpeairs wants to merge 3 commits into
mainfrom
gp/cusp-guard

Conversation

@gpeairs

@gpeairs gpeairs commented Jul 13, 2026

Copy link
Copy Markdown
Member

The curvature of an offset curve can diverge when the offset crosses through the curvature radius of the base curve (that is, near a cusp of the offset curve). This leads to extreme refinement near cusps even when unnecessary for tolerance, now that offset curves are discretized based on their own curvature rather than that of the base curve (following #236).

This PR clamps the effective ratio between curvature radius of base and offset curves used by the marching kernel to discretize the offset curve to R_kernel / R_base = 0.1. While this looks like a relative guard, you can derive a bound on absolute error if you linearize the base curvature radius R near a cusp at arclength s_c (where R = d). The value that we're clamping to a minimum of ε=0.1 is |1 − d·κ(s)| ≈ (|R′|/d)·|s − s_c|, with R′ = dR_base/ds dimensionless and O(1) for a smooth spline. Then the clamp leaves the marching step nearby at Δs = √(8·tol·d·ε), and if this step straddles the cusp, the offset curve's max excursion from the resulting chord is e = |R′|·Δs²/(8d) ≈ ε · |dR/ds| · tol. So 0.1 is pretty conservative and won't hurt well-behaved curves without cusps.

Note that this doesn't repair curves with cusps (e.g. by clipping out any closed region created by self-intersection), so users can still create pathological geometry at their own risk (but now at least they get warnings during rendering). This change just prevents the curve from being sampled excessively near cusps.

Addresses the issue described at the end of the #243 thread as far as over-refinement is concerned, but because the sampled curve may still self-intersect, it does not necessarily survive clipping, in which case curve recovery will still fail. However, even if it succeeded by partial matching of clipped runs, you'd be left with a self-intersecting polygon / negative-area loop.

Edit: Draft while a fix to the cusp warning is in progress.

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.

1 participant