The animations make it very intuitive to understand what's happening. Once you get that it's trivial to turn that into a parametric formula (`x(t)` and `y(t)`, not `f(x)`) to calculate all the points along the curve.
Start by understanding quadratic beziers, they're pretty straightforward. Then when you move to cubic ones realize that it's just adding one more level of interpolation.
The hurdle for me was realizing that it's impossible to calculate the corresponding y position given the x position for all 2d curves, because there may be multiple y positions. Instead think of it as little steps that get you from the beginning to the end.
I also learned from this one which I think is simpler but not as detailed
https://webglfundamentals.org/webgl/lessons/webgl-3d-geometr...
Do you have a project which might be able to make use of this? What sort of work do you do?
I am bookmarking this for re-reading later because I hope it will help me to understand how to implement Bézier curves in a tool I've been working on for controlling a CNC machine/creating files for cutting on a CNC:
https://github.com/WillAdams/gcodepreview
(but first I have to get arcs working)
def bezier(t, *points):
if len(points) <= 1:
return points[0]
next_set = []
for i in range(1, len(points)):
next_set.append([p[0] + t * (p[1] - p[0]) for p in zip(points[i - 1], points[i])])
return bezier(t, *next_set)
That'll compute a point along your bezier curve. The `t` parameter is how far along the curve you want to go, 0 <= t <= 1. You can give it as many dimensions and whatever order (number of handles) you want. So for example, to get a cubic bezier curve on a 2d plane from (0, 0) to (1, 1) with handles at (1, 0), (0, 1) (an aggressive ease-in/ease-out curve) with 9 segments (10 points) you'd run: n = 10
for t in range(n):
print(
bezier(
t / (n - 1),
(0, 0),
(1, 0),
(0, 1),
(1, 1)
))
I think that's right. I did it from memory. Obviously don't mix 2d and 3d, but it should work if all points have the same number of dimensions.I was also able to do this in OpenScad. The technique is the same. I was 3d printing a router template for rounding off corners of tables that used splines like this so it wasn't as obvious where the corners started and ended. I think ~40 points was accurate enough for me, but I was hitting the corner with sandpaper afterwards.
Like I said, arcs are next (once I finish a re-write as a "Literate Program", 'cause managing stuff spread across three files has gotten to be a pain. I'm going to try the docmfp package as something straight-forward enough for me to wrap my mind around and which I can use on pretty much any computer I'm inclined to.