Courbes de Bézier


In [ ]:
%matplotlib inline

import ipywidgets
from ipywidgets import interact

Courbe de Bézier quadratique (degré 2)

Écriture paramétrique

La forme paramétrique d'une courbe de Bézier quadratique s'écrit comme une combinaison affine de ses 3 points de contrôle $\mathbf{P}_1$, $\mathbf{P}_2$ et $\mathbf{P}_3 \in \mathbb{R}^2$: $$ \begin{align} f: & \mathbb{R} \to \mathbb{R}^2 \ & \mathbf{f}(t) \mapsto \mathbf{P_1} (1-t)^2

   + 2\mathbf{P_2} t (1-t)
   + \mathbf{P_3} t^2

\end{align} $$ pour $0 \leq t \leq 1$.

TODO...

Courbe de Bézier cubique (degré 3)

Écriture paramétrique

La forme paramétrique d'une courbe de Bézier cubique s'écrit comme une combinaison affine de ses 4 points de contrôle $\mathbf{P}_1$, $\mathbf{P}_2$, $\mathbf{P}_3$ et $\mathbf{P}_4 \in \mathbb{R}^2$: $$ \begin{align} f: & \mathbb{R} \to \mathbb{R}^2 \\ & \mathbf{f}(t) \mapsto \mathbf{P}_1 (1-t)^3 + 3 \mathbf{P}_2 t(1-t)^2 + 3 \mathbf{P}_3 t^2 (1-t) + \mathbf{P}_4 t^3 \end{align} $$ pour $0 \leq t \leq 1$.


In [ ]:
import numpy as np

p1 = np.array([0, 0])
p2 = np.array([0, 1])
p3 = np.array([1, 1])
p4 = np.array([1, 0])

def f(t):
    return p1 * (1.-t)**3 + 3. * p2 * t * (1.-t)**2 + 3. * p3 * t**2 * (1.-t) + p4 * t**3
            
plt.plot(*p1, "xr")
plt.plot(*p2, "xr")
plt.plot(*p3, "xr")
plt.plot(*p4, "xr")

offset = np.array([0.02, 0.02])

plt.text(*(p1 + offset), r"$P_1$")
plt.text(*(p2 + offset), r"$P_2$")
plt.text(*(p3 + offset), r"$P_3$")
plt.text(*(p4 + offset), r"$P_4$")

XY = np.array([f(t) for t in np.linspace(0., 1., 100)])    # TODO: improve this

plt.plot(*XY.T)

plt.xlim(-0.1, 1.1)
plt.ylim(-0.1, 1.1)

plt.show()

In [ ]:
# TODO

Exemple illustré


In [ ]:
class CubicBezierCurve:
    def __init__(self, p1, p2, p3, p4):
        self.p1 = p1
        self.p2 = p2
        self.p3 = p3
        self.p4 = p4
        
        self.color_deg1 = 'gray'
        self.color_deg2 = 'g'
        self.color_deg3 = 'b'
    
    def __call__(self, t):
        return self.p1 * (1.-t)**3 \
               + 3. * self.p2 * t * (1.-t)**2 \
               + 3. * self.p3 * t**2 * (1.-t) \
               + self.p4 * t**3
                
    def init_plot(self, ax=None):
        if ax is None:
            fig, ax = plt.subplots()
        
        ax.plot(*np.array([self.p1, self.p2]).T, marker='x', color=self.color_deg1)
        ax.plot(*np.array([self.p2, self.p3]).T, marker='x', color=self.color_deg1)
        ax.plot(*np.array([self.p3, self.p4]).T, marker='x', color=self.color_deg1)

        offset = np.array([0.02, 0.02])

        ax.text(*(self.p1 + offset), r"$P_1$")
        ax.text(*(self.p2 + offset), r"$P_2$")
        ax.text(*(self.p3 + offset), r"$P_3$")
        ax.text(*(self.p4 + offset), r"$P_4$")

        T = np.linspace(0., 1., 100)
        XY = np.array([self(t) for t in T])    # TODO: improve this

        ax.plot(*XY.T, 'r:', alpha=0.5)

        points = np.array([self.p1, self.p2, self.p3, self.p4])
        ax.set_xlim(points[:,0].min() - 0.1, points[:,0].max() + 0.1)
        ax.set_ylim(points[:,1].min() - 0.1, points[:,1].max() + 0.1)
        
        return ax
    
    def plot(self, t, ax=None):
        if ax is None:
            fig, ax = plt.subplots()
            
        p12 = self.p1 + t * (self.p2 - self.p1)
        p23 = self.p2 + t * (self.p3 - self.p2)
        p34 = self.p3 + t * (self.p4 - self.p3)
        
        p1223 = p12 + t * (p23 - p12)
        p2334 = p23 + t * (p34 - p23)
        
        ax.plot(*np.array([p12, p23, p34]).T, marker='.', color=self.color_deg2)
        ax.plot(*np.array([p1223, p2334]).T, marker='.', color=self.color_deg3)
        
        ax.plot(*self(t).T, 'or')

p1 = np.array([0, 0])
p2 = np.array([0, 1])
p3 = np.array([1, 1])
p4 = np.array([1, 0])
f = CubicBezierCurve(p1, p2, p3, p4)

ax = f.init_plot()
f.plot(0.25, ax)

plt.show();

Exemple interactif


In [ ]:
@interact(t=(0., 1., 0.01))
def square(t):
    p1 = np.array([0, 0])
    p2 = np.array([0, 1])
    p3 = np.array([1, 1])
    p4 = np.array([1, 0])
    f = CubicBezierCurve(p1, p2, p3, p4)

    ax = f.init_plot()
    f.plot(t, ax)

    plt.show();

Courbes de Bézier quartique (degré 4)

TODO...