This page was generated from doc/euclidean/kochanek-bartels-properties.ipynb. Interactive online version: Binder badge.

Properties of Kochanek–Bartels Splines§

Kochanek–Bartels splines (a.k.a. TCB splines) are interpolating cubic polynomial splines, with three user-defined parameters per vertex (of course they can also be chosen to be the same three values for the whole spline), which can be used to change the shape and velocity of the spline.

These three parameters are called \(T\) for “tension”, \(C\) for “continuity” and \(B\) for “bias”. With the default values of \(C = 0\) and \(B = 0\), a Kochanek–Bartels spline is identical to a cardinal spline. If the “tension” parameter also has its default value \(T = 0\), it is also identical to a Catmull–Rom spline.

TODO: comparison of T with “tension” parameter of cardinal splines

[1]:
import splines

helper.py

[2]:
from helper import plot_spline_2d
[3]:
import matplotlib.pyplot as plt
import numpy as np

def plot_tcb(*tcb, ax=None):
    """Plot four TCB examples."""
    if ax is None:
        ax = plt.gca()
    vertices = [
        (-2.5, 0),
        (-1, 1.5),
        (0, 0.1),
        (1, 1.5),
        (2.5, 0),
        (1, -1.5),
        (0, -0.1),
        (-1, -1.5),
    ]
    for idx, tcb in zip([1, 7, 3, 5], tcb):
        all_tcb = np.zeros((len(vertices), 3))
        all_tcb[idx] = tcb
        s = splines.KochanekBartels(
            vertices, tcb=all_tcb, endconditions='closed')
        label = ', '.join(
            f'{name} = {value}'
            for name, value in zip('TCB', tcb)
            if value)
        plot_spline_2d(s, chords=False, label=label, ax=ax)
    plot_spline_2d(
        splines.KochanekBartels(vertices, endconditions='closed'),
        color='lightgrey', chords=False, ax=ax)
    lines = [l for l in ax.get_lines() if not l.get_label().startswith('_')]
    # https://matplotlib.org/tutorials/intermediate/legend_guide.html#multiple-legends-on-the-same-axes
    ax.add_artist(ax.legend(
        handles=lines[:2], bbox_to_anchor=(0, 0., 0.5, 1),
        loc='center', numpoints=3))
    ax.legend(
        handles=lines[2:], bbox_to_anchor=(0.5, 0., 0.5, 1),
        loc='center', numpoints=3)

Tension§

[4]:
plot_tcb((0.5, 0, 0), (1, 0, 0), (-0.5, 0, 0), (-1, 0, 0))
../_images/euclidean_kochanek-bartels-properties_8_0.svg

Continuity§

TODO: When \(C_i = 0\), we are back at a Catmull–Rom spline. When \(C_i = -1\), we get a tangent like in a piecewise linear curve. When \(C_i = 1\), we get some weird “inverse corners”.

[5]:
plot_tcb((0, -0.5, 0), (0, -1, 0), (0, 0.5, 0), (0, 1, 0))
../_images/euclidean_kochanek-bartels-properties_11_0.svg

\(T = 1\) and \(C = -1\): similar shape (a.k.a. “image”), different timing:

[6]:
plot_tcb((1, 0, 0), (0, -1, 0), (0.5, 0, 0), (0, -0.5, 0))
../_images/euclidean_kochanek-bartels-properties_13_0.svg

shape in “corners” is similar, but speed is different! with re-parameterization (TODO: link), it doesn’t make too much of a difference.

A value of \(C=-1\) on adjacent vertices leads to linear segments:

[7]:
vertices1 = [(0, 0), (1, 1), (0, 2), (2, 2), (3, 1), (2, 0)]
s1 = splines.KochanekBartels(vertices1, tcb=(0, -1, 0), endconditions='closed')
plot_spline_2d(s1, chords=False)
../_images/euclidean_kochanek-bartels-properties_16_0.svg

Bias§

“overshoot”: -1 is full “undershoot”

[8]:
plot_tcb((0, 0, 0.5), (0, 0, 1), (0, 0, -0.5), (0, 0, -1))
../_images/euclidean_kochanek-bartels-properties_19_0.svg

Bias \(-1\) followed by \(+1\) can be used to achieve linear segments between two control points:

[9]:
vertices2 = [(0, 0), (1.5, 0), (1, 1), (0, 0.5)]
tcb2 = [(0, 0, -1), (0, 0, 1), (0, 0, -1), (0, 0, 1)]
s2 = splines.KochanekBartels(vertices2, tcb=tcb2, endconditions='closed')
plot_spline_2d(s2, chords=False)
../_images/euclidean_kochanek-bartels-properties_21_0.svg

A sequence of \(B=-1\), \(C=-1\) and \(B=+1\) can be used to get two adjacent linear segments:

[10]:
vertices3 = [(0, 0), (1, 0), (0, 0.5)]
tcb3 = [(0, 0, -1), (0, -1, 0), (0, 0, 1)]
s3 = splines.KochanekBartels(vertices3, tcb=tcb3, endconditions='closed')
plot_spline_2d(s3, chords=False)
../_images/euclidean_kochanek-bartels-properties_23_0.svg

Combinations§

accumulated tension and continuity vs. opposite T and C:

[11]:
plot_tcb((1, -1, 0), (-1, 1, 0), (-1, -1, 0), (1, 1, 0))
../_images/euclidean_kochanek-bartels-properties_26_0.svg
[12]:
plot_tcb((1, 0, 1), (-1, 0, 1), (0, -1, 1), (0, 1, -1))
../_images/euclidean_kochanek-bartels-properties_27_0.svg

TODO: expain non-intuitive cases