This page was generated from doc/euclidean/bezier-non-uniform.ipynb. Interactive online version: Binder badge.

Non-Uniform (Cubic) Bézier Splines#

Very commonly, Bézier splines are used with a parameter range of \(0 \le t \le 1\), which has also been used to derive the basis polynomials and basis matrices in the notebook about De Casteljau’s algorithm.

The parameter range can be re-scaled to any desired parameter range, but since the shape of a Bézier curve is fully defined by its control polygon, this will not change the shape of the curve, but only its speed, and therefore its tangent vectors.

To derive equations for non-uniform tangent vectors, let us quickly re-implement De Casteljau’s algorithm:

[1]:
def lerp(one, two, t):
    return (1 - t) * one + t * two
[2]:
def de_casteljau(points, t):
    while len(points) > 1:
        points = [lerp(a, b, t) for a, b in zip(points, points[1:])]
    return points[0]
[3]:
import sympy as sp
sp.init_printing()

We’ll also use our trusty SymPy tools from utility.py:

[4]:
from utility import NamedExpression

In this notebook we are only looking at cubic Bézier splines. More specifically, we are looking at the fifth spline segment, from \(\boldsymbol{x}_4\) to \(\boldsymbol{x}_5\) within a parameter range from \(t_4\) to \(t_5\), but later we can easily generalize this.

[5]:
control_points = sp.symbols('xbm4 xtildebm4^(+) xtildebm5^(-) xbm5')
control_points
[5]:
$\displaystyle \left( \boldsymbol{x}_{4}, \ \boldsymbol{\tilde{x}}^{(+)}_{4}, \ \boldsymbol{\tilde{x}}^{(-)}_{5}, \ \boldsymbol{x}_{5}\right)$
[6]:
t, t4, t5 = sp.symbols('t t4 t5')

As before, we are using De Casteljau’s algorithm, but this time we are re-scaling the parameter range using the transformation \(t \to \frac{t - t_i}{t_{i+1} - t_i}\):

[7]:
p4 = NamedExpression(
    'pbm4',
    de_casteljau(control_points, (t - t4) / (t5 - t4)))

Tangent Vectors#

As always, the tangent vectors can be obtained by means of the first derivative:

[8]:
pd4 = p4.diff(t)
[9]:
pd4.evaluated_at(t, t4)
[9]:
$\displaystyle \left.{\frac{d}{d t} \boldsymbol{p}_{4}}\right\rvert_{t=t_{4}} = - \frac{3 \boldsymbol{x}_{4}}{- t_{4} + t_{5}} + \frac{3 \boldsymbol{\tilde{x}}^{(+)}_{4}}{- t_{4} + t_{5}}$

This expression for the outgoing tangent vector at \(\boldsymbol{x}_4\) can be generalized to

\begin{equation*} \boldsymbol{\dot{x}}_i^{(+)} = \frac {3 \left(\boldsymbol{\tilde{x}^{(+)}}_i - \boldsymbol{x}_i\right)} {\Delta_i}, \end{equation*}

where \(\Delta_i = t_{i+1} - t_i\).

Similarly, the incoming tangent vector at \(\boldsymbol{x}_5\)

[10]:
pd4.evaluated_at(t, t5)
[10]:
$\displaystyle \left.{\frac{d}{d t} \boldsymbol{p}_{4}}\right\rvert_{t=t_{5}} = \frac{3 \boldsymbol{x}_{5}}{- t_{4} + t_{5}} - \frac{3 \boldsymbol{\tilde{x}}^{(-)}_{5}}{- t_{4} + t_{5}}$

… can be generalized to

\begin{equation*} \boldsymbol{\dot{x}}_i^{(-)} = \frac {3 \left(\boldsymbol{x}_i - \boldsymbol{\tilde{x}^{(-)}}_i\right)} {\Delta_{i-1}}. \end{equation*}

This is similar to the uniform case, the tangent vectors are just divided by the parameter interval.

Control Points From Tangent Vectors#

If the tangent vectors are given in the first place – i.e. when a non-uniform Hermite spline is given, the cubic Bézier control points can be calculated like this:

\begin{align*} \boldsymbol{\tilde{x}^{(+)}}_i &= \boldsymbol{x}_i + \frac{\Delta_i \boldsymbol{\dot{x}}_i^{(+)}}{3} \\ \boldsymbol{\tilde{x}^{(-)}}_i &= \boldsymbol{x}_i - \frac{\Delta_{i-1} \boldsymbol{\dot{x}}_i^{(-)}}{3} \end{align*}