Skip to content

Fix winding number solver near endpoints#537

Merged
jneem merged 2 commits intolinebender:mainfrom
jneem:winding-number-instability
Jan 14, 2026
Merged

Fix winding number solver near endpoints#537
jneem merged 2 commits intolinebender:mainfrom
jneem:winding-number-instability

Conversation

@jneem
Copy link
Member

@jneem jneem commented Jan 13, 2026

In the winding number calculation, it when the ray's crossing was close to an endpoint it was possible for the solver to mistakenly put the solution outside of [0.0, 1.0]. This fixes the solver so that it always finds a solution (which it must, because the segment is continuous and we check that its y values span the y we're looking for).

Fixes #531.

Copy link
Member

@tomcur tomcur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good, thanks! A changelog entry mentioning improved robustness would be great.

I'm idly wondering whether there are still adversarial inputs possible at the level of paths (not segments), e.g. where two near-identical and mirrored segments fail slightly differently such that an x is falsely considered inside or outside... for any reasonable horizontal distance to the path edges perhaps not.

@jneem jneem force-pushed the winding-number-instability branch from 032a7e4 to bf26444 Compare January 14, 2026 16:20
@jneem
Copy link
Member Author

jneem commented Jan 14, 2026

As you already alluded to, if the point's x coordinate is very close to the segments then you can definitely get inconsistent answers from adjacent segments, but I think that's ok: the point is close to the boundary anyway and so errors are allowed.

As long as there's a reasonable horizontal distance, I think we're safe against inconsistencies -- I added a little comment to winding_inner giving a hint as to why. But for example, if you have a decreasing-y segment followed by an increasing-y segment and the point's y coordinate is exactly at the vertex or slightly above then (with this PR) we are guaranteed to say that both segments cross the point's y coordinate. If there's a reasonable horizontal distance involved, we'll get the x coordinates correct enough and either get a winding number of 1 - 1 or 0 + 0. On the other hand, if the point's y coordinate is strictly below the vertex then we'll way that neither segment crosses the point's y coordinate.

The other case (increasing-y followed by decreasing-y) handles the exact equality case differently, but it should still be ok 🤞

@jneem jneem added this pull request to the merge queue Jan 14, 2026
Merged via the queue into linebender:main with commit e383503 Jan 14, 2026
15 checks passed
@jneem jneem deleted the winding-number-instability branch January 14, 2026 16:34
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.

Numerical instability in winding number / contains.

2 participants