TODO
In [ ]:
%matplotlib inline
import ipywidgets
from ipywidgets import interact
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...
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
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();
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();
TODO...