Bézier curves in Julia with animations

I think many heard about Bézier curves but maybe some of you didn’t and I heard about it but wasn’t really sure what they are and how they work.
During my Geometric Modelling and Animations course in university we had some lectures on it and I did some coding for homeworks and also to understand a bit more about it. During the last days I published my animations on Twitter and asked whether you’re interested in a post. There was quite a bit feedback on that so here it is!

Let us start with a basic Bézier curve:

simple Bézier curve

Before I show you what Bézier curves are we should probably have a short look what a basic curve is. A curve can be described by a parameterized description as:

b(t)=(x(t),y(t))Tt1tt2

whereas b is a vector and x,y are polynomial functions like

x(t)=a0+a1t+a2t2++antn

Now the idea is to compute the values on the curve from t1=0 to t2=1 using a different basis not simply t0,,tn.
For Bézier curves this basis are defined as:

Bin(t):=(ni)ti(1t)ni,0in

and is called Bernstein basis.

Which looks a bit random for now but they have some interesting properties:

  • B0n(t)+B1n(t)++Bnn(t)=1
  • $B_0^n(0) = 1, B_n^n(1)=1

which means when we write down the complete formula to compute b(t):

b(t)=i=0nBinbi

where bi are our control points. Now the second property just means that b(0)=b0 and b(0)=bn

I think it would be nice to actually see the basis functions:

Bernstein basis

Now we can combine it with our control points to obtain:

Bézier using Bernstein basis

Besides the change in color you probably don’t see a difference to the first plot even though that was plotted differently.

I know some of you are here for code so I’ll show you the bernstein code:

using Plots
# for the LaTeX labels in the legend
using LaTeXStrings 

function compute_bernstein(i,n; steps=100)
    return [binomial(n,i)*t^i*(1-t)^(n-i) for t in LinRange(0,1,steps)]
end

function compute_bernstein_poly(px,py; steps=100)
    n = length(px)-1
    bernsteins = [compute_bernstein(i,n) for i=0:n]
    x_vals = [sum(px[k]*bernsteins[k][t] for k=1:n+1) for t=1:steps]
    y_vals = [sum(py[k]*bernsteins[k][t] for k=1:n+1) for t=1:steps]
    return x_vals, y_vals
end

function plot_with_bernstein(px,py; steps=100, subplot=1)
    x_vals, y_vals = compute_bernstein_poly(px,py; steps=steps)
    plot!(x_vals, y_vals, color=:blue, label="",subplot=subplot)
end

function main()
    px = [0, 3, 7]
    py = [2, 9, 3]

    plot(;size=(700,500), axisratio=:equal, legendfont=font(13))
    plot!(px, py, linetype=:scatter, label="control points")
    plot_with_bernstein(px,py)
    png("using_bernstein")
end

Pretty basic so far. Now combining the two and animate:

Bernstein gif

Actually I’m not too sure about how to interpret the colored animating part on the lower plot with the different bernstein polynomials but I think it looks interesting and I never saw that before. The three dots red, green and blue some up to the black in both ways.

Anyway I think the interesting things are still missing. First of all we only have 3 control points at…