Deconstructing Bézier Curves
blog.pkh.me
blog.pkh.me
- Curves and Surfaces by Bartosz Ciechanowski: https://ciechanow.ski/curves-and-surfaces/ (His whole site is a treasure trove of incredible explanations!)
- Primer on Bézier Curves: https://pomax.github.io/bezierinfo/
https://github.com/solvespace/solvespace/blob/master/src/srf...
It used to culminate in a function for finding a point at the intersection of 3 rational Bezier surfaces, but we had to add something less exciting at the end.
I lately tried to find some options for a hobby project. The only way I could find was to first break the path into a lot of line segments, then do the logical operations between paths and finally convert them back by trying to fit Bézier curves into the resulting line segments.
Conversions back and forth seem less than optimal and can lead to artefacts. There must be a better way.
The 'better way' you're talking about here is the curve clipping algorithm, my version of which is here: https://docs.rs/flo_curves/latest/flo_curves/bezier/fn.curve...
Finding the intersections between individual curves is only the first part of this operation: you also need a way to determine which edges are on the outside of the new path (flo_curves uses raycasting for this, same operation that the OP focuses on, essentially) and deal with a fairly large pile of edge cases - literally edge cases here. Things like overlapping edges, nearly overlapping edges, what happens if a ray passes through an intersection point or directly across a straight edge, precision issues, curves with loops, etc.
I'd love to work with a more mathematical colleague on the error bounds and so on. Ideally one who knows the way of the land regarding academic publication, as I think even what I have now is publishable.
Another good implementation to be aware of is Skia path ops[1], used quite a bit in production, including fonts.
I'd be happy to discuss it though.
I think my approach may be less difficult, as it's based on accepting numerical errors when curves are within epsilon of each other. Thus, a lot of the guts of my algorithm is computing bounds and geometric intervals (adapting some ideas from North's master's thesis[1]). I'm I'm not yet convinced that precise orientation is even possible with cubics.
[1]: https://scholarsarchive.byu.edu/cgi/viewcontent.cgi?article=...
[0] assuming intersection multiplicity degeneracy is handled elsewhere, but maybe not having to do that is what winding number provides?
Cool! Is it going to be a part of Skia or something Google internal?
I wish the accompanying code was more readable though. There’s a lot of one letter variables and unexplained tricks that are difficult to work out.
Ohhh, did you animate them? Were you rendering to SVG?
Inquiring minds want to know.
[1]: https://raphlinus.github.io/curves/2021/02/19/parallel-curve...
referring to how they switch from two coordiates (function arguments) into just the one 'time' argument.
this is most clear in Bartosz Cieachanowski explanation.
then the whole topic gets really going when they add multiple lines all parametrized with the one 'time' argument.