-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Better numerical robustness for stroking #304
Conversation
A number of fixes to improve stroke robustness. Infinite recursion on curve fit is avoided by checking whether subdivision has hit the floating point limit. That said, the quality of curve fit is poor when the input is discontinuous (which does happen for degenerate cubics with cusps, where all points are co-linear). Thus, in stroking, the degenerate cases are detected and drawn with special-case logic (do_linear). This uses existing drawing capabilities to draw the degenerate cubic with lines and round joins. Finally, do_join mistakenly detected a half-turn as zero turn, as it was only considering the cross product (which vanishes). Fixes #300
Nice! Since I already have a vello branch hacked up to integrate this, I’ll test on the sample scenes later today and then give this a proper review. |
Hmm, these are obviously false positives, but I've desk-checked the code and tried to write a repro (I originally suspected a case where one control point is coincident with an endpoint) and am not finding anything. I'll dig more deeply. Could you perhaps upload your vello branch? (doesn't have to be cleaned up in any way) |
I am only able to repro when I set unreasonably high tolerance values, so I am wondering if we can rule that out. The break between detection and not is happening exactly where I'd expect when I vary the tolerance. That said, I am seeing some distorted rendering when the chord and the tangent don't match, so will probably refine that (and, ideally, write a test). |
Yes, I also noticed that setting tolerance too low would result in what look like inverted offsets where the curve becomes too thick. I think I’ve been testing with 0.01 |
I'd appreciate isolated failing examples. Clearly there's more work to be done to validate this, and perhaps I should invest time to make a test suite (I can see that coming in handy when moving to GPU). But right now I just want to get something "good enough" landed. |
I'll try to extract a failing case or two from tiger if I can identify them. |
I was missing the case where the chord reference doesn't match the chord; when it does, the cross-product is clearly zero, but otherwise there are cases where the other two cross-products are zero but the chord isn't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for getting this done! Haven’t gone over the math in detail but this looks solid at a glance and produces correct results in all scenes now. Let’s get it merged.
🚢
A number of fixes to improve stroke robustness.
Infinite recursion on curve fit is avoided by checking whether subdivision has hit the floating point limit. That said, the quality of curve fit is poor when the input is discontinuous (which does happen for degenerate cubics with cusps, where all points are co-linear).
Thus, in stroking, the degenerate cases are detected and drawn with special-case logic (do_linear). This uses existing drawing capabilities to draw the degenerate cubic with lines and round joins.
Finally, do_join mistakenly detected a half-turn as zero turn, as it was only considering the cross product (which vanishes).
Fixes #300