Page 1 sur 1

Courbe de Bézier, accélération, fonction accel(path,real)

MessagePosté: Vendredi 28 Octobre 2011, 14:49
par GMaths
Une rectification en forme d'explication : dans des exemples récents (que je vais devoir modifier), j'ai utilisé la fonction accel... qui semblait fonctionner pour ce que je proposais mais j'ai réalisé après coup que je tombais dans des cas particuliers où l'accélération tangentielle était nulle.

Pour un path (courbe de Bézier), accel ne donne pas l'accélération normale, comme je l'ai cru, mais il correspond à la somme des accélérations normale et tangentielle.

3fab51a5deb1c1a334e7c051e4a79c85.png

Code: Tout sélectionner
unitsize(1.3cm);
pair z0=(0,0), z1=(7,0),
c0=(1,3), c1=(5,5);

// On déduit du quadruplet de points précédents (z0, c0, c1, z1)
// (par construction de 6 milieux) le point z2 sur la courbe de bézier.
// En procédant de même pour les quadruplets (z0, m0, m3, z2)
// et (z2, m4, m2, z1), on obtiendrait deux nouveaux points de la courbe,
// et c'est en continuant ainsi, par récursivité, que la courbe est construite.

pair m0=(z0+c0)/2,
m1=(c0+c1)/2,
m2=(c1+z1)/2,
m3=(m0+m1)/2,
m4=(m1+m2)/2,
z2=(m3+m4)/2;

// Courbe (spline) de Bézier cubique (définie par 4 points).
path CourbeBezier = z0 .. controls c0 and c1 .. z1;
draw(CourbeBezier,2bp+blue);

// Les traits et points de construction
path lignebrisee = z0 -- c0 -- c1 -- z1;
draw(lignebrisee^^m0--m1--m2^^m3--m4,dashed);
dot(lignebrisee^^m0--m1--m2^^m3--m4^^z2,5bp+red);

// Pour finir, on ajoute le nom des points.
label("$z_0$",z0,S); label("$z_1$",z1,S);
label("$c_0$",c0,N); label("$c_1$",c1,N);
label("$m_0$",m0,NW); label("$m_1$",m1,N);
label("$m_2$",m2,NE); label("$m_3$",m3,N);
label("$m_4$",m4,N); label("$z_2$",z2,N);

draw(Label("\tiny $\vec{m_1m_0}$",LeftSide),z2--z2+(m0-m1),Arrow());
draw("\tiny $\vec{m_1m_2}$",z2+(m0-m1)--z2+(m0-m1)+(m2-m1),Arrow());
draw(Label("$\frac{1}{6}\vec{a}=\vec{m_1m_0}+\vec{m_1m_2}$",LeftSide),z2--(z2+accel(CourbeBezier,dirtime(CourbeBezier,m4-m3))/6),Arrow());
draw("$\frac{1}{3}\vec{v}=\vec{m_3m_4}$",z2--(z2+(m4-m3)),Arrow());

shipout(bbox(3mm,white));

Edition du 31/10/11 : Attention !! il y a une erreur dans le code de cette figure (que je signale dans un message qui suit) mais je la laisse pour la cohérence du sujet.

Comme c'est indiqué sur la figure, accel au point $z_2$ correspond à $6\left(\vec{m_1m_0}+\vec{m_1m_2}\right)$.

Je n'ai pas trouvé de fonction donnant le vecteur vitesse $\vec{v}$, censé être égale à $3\vec{m_3m_4}$. La fonction dir ne donne que le vecteur unitaire qui colinéaire et de même sens que $\vec{v}$.

Re: Courbe de Bézier - Accélération - Fonction accel(path,re

MessagePosté: Vendredi 28 Octobre 2011, 15:14
par GMaths
L'explication sera encore à parfaire car si là, cela fonctionne :

64c8534025d9492b29a8b1f92b89c083.png

Code: Tout sélectionner
unitsize(1cm);

pair z0=(0,0), z1=(7,0),
c0=(5,3), c1=(5,5);

// On déduit du quadruplet de points précédents (z0, c0, c1, z1)
// (par construction de 6 milieux) le point z2 sur la courbe de bézier.
// En procédant de même pour les quadruplets (z0, m0, m3, z2)
// et (z2, m4, m2, z1), on obtiendrait deux nouveaux points de la courbe,
// et c'est en continuant ainsi, par récursivité, que la courbe est construite.

pair m0=(z0+c0)/2,
m1=(c0+c1)/2,
m2=(c1+z1)/2,
m3=(m0+m1)/2,
m4=(m1+m2)/2,
z2=(m3+m4)/2;

// Courbe (spline) de Bézier cubique (définie par 4 points).
path CourbeBezier = z0 .. controls c0 and c1 .. z1;
draw(CourbeBezier,2bp+blue);

// Les traits et points de construction
path lignebrisee = z0 -- c0 -- c1 -- z1;
draw(lignebrisee^^m0--m1--m2^^m3--m4,dashed);
dot(lignebrisee^^m0--m1--m2^^m3--m4^^z2,5bp+red);

// Pour finir, on ajoute le nom des points.
label("$z_0$",z0,S); label("$z_1$",z1,S);
label("$c_0$",c0,N); label("$c_1$",c1,N);
label("$m_0$",m0,NW); label("$m_1$",m1,N);
label("$m_2$",m2,NE); label("$m_3$",m3,N);
label("$m_4$",m4,N); label("$z_2$",z2,N);

draw(Label("\tiny $\vec{m_1m_0}$",LeftSide),z2--z2+(m0-m1),Arrow());
draw("\tiny $\vec{m_1m_2}$",z2+(m0-m1)--z2+(m0-m1)+(m2-m1),Arrow());
draw(Label("$\frac{1}{6}\vec{a}=\vec{m_1m_0}+\vec{m_1m_2}$",LeftSide),z2--(z2+accel(CourbeBezier,dirtime(CourbeBezier,m4-m3))/6),Arrow());
draw("$\frac{1}{3}\vec{v}=\vec{m_3m_4}$",z2--(z2+(m4-m3)),Arrow());

shipout(bbox(3mm,white));


par contre là, cela explose :

a48bd69003611b7baf55615c38b88a1e.png

Code: Tout sélectionner
unitsize(1cm);

pair z0=(0,0), z1=(7,0),
c0=(5,2), c1=(5,5);

// On déduit du quadruplet de points précédents (z0, c0, c1, z1)
// (par construction de 6 milieux) le point z2 sur la courbe de bézier.
// En procédant de même pour les quadruplets (z0, m0, m3, z2)
// et (z2, m4, m2, z1), on obtiendrait deux nouveaux points de la courbe,
// et c'est en continuant ainsi, par récursivité, que la courbe est construite.

pair m0=(z0+c0)/2,
m1=(c0+c1)/2,
m2=(c1+z1)/2,
m3=(m0+m1)/2,
m4=(m1+m2)/2,
z2=(m3+m4)/2;

// Courbe (spline) de Bézier cubique (définie par 4 points).
path CourbeBezier = z0 .. controls c0 and c1 .. z1;
draw(CourbeBezier,2bp+blue);

// Les traits et points de construction
path lignebrisee = z0 -- c0 -- c1 -- z1;
draw(lignebrisee^^m0--m1--m2^^m3--m4,dashed);
dot(lignebrisee^^m0--m1--m2^^m3--m4^^z2,5bp+red);

// Pour finir, on ajoute le nom des points.
label("$z_0$",z0,S); label("$z_1$",z1,S);
label("$c_0$",c0,N); label("$c_1$",c1,N);
label("$m_0$",m0,NW); label("$m_1$",m1,N);
label("$m_2$",m2,NE); label("$m_3$",m3,N);
label("$m_4$",m4,N); label("$z_2$",z2,N);

draw(Label("\tiny $\vec{m_1m_0}$",LeftSide),z2--z2+(m0-m1),Arrow());
draw("\tiny $\vec{m_1m_2}$",z2+(m0-m1)--z2+(m0-m1)+(m2-m1),Arrow());
draw(Label("$\frac{1}{6}\vec{a}=\vec{m_1m_0}+\vec{m_1m_2}$",LeftSide),z2--(z2+accel(CourbeBezier,dirtime(CourbeBezier,m4-m3))/6),Arrow());
draw("$\frac{1}{3}\vec{v}=\vec{m_3m_4}$",z2--(z2+(m4-m3)),Arrow());

shipout(bbox(3mm,white));


Je reverrai cela plus tard.

De la lecture sur le sujet qu'il faudra que je lise... pour comprendre pourquoi cela ne fonctionne pas dans certains cas.

Re: Courbe de Bézier - Accélération - Fonction accel(path,re

MessagePosté: Lundi 31 Octobre 2011, 15:40
par GMaths
J'ai refait les calculs :
courbe_bezier.pdf
(46.69 Kio) Téléchargé 94 fois


J'ai refait un cas moins particulier : on peut choisir t.

38ac8c572494b0a5e6fe4ef37f58afb3.png

Code: Tout sélectionner
unitsize(1cm); pair z0=(0,0), z1=(9,0), c0=(1,5), c1=(5,5); real t=.45; pair m0=(1-t)*z0+t*c0, m1=(1-t)*c0+t*c1, m2=(1-t)*c1+t*z1, m3=(1-t)*m0+t*m1, m4=(1-t)*m1+t*m2, z2=(1-t)*m3+t*m4; path CourbeBezier = z0 .. controls c0 and c1 .. z1; draw(CourbeBezier,2bp+blue); path lignebrisee = z0 -- c0 -- c1 -- z1; draw(lignebrisee^^m0--m1--m2^^m3--m4,dashed); dot(lignebrisee^^m0--m1--m2^^m3--m4^^z2,5bp+red); label("$M_0$",z0,S); label("$M_1$",z1,S); label("$C_0$",c0,N); label("$C_1$",c1,N); label("$Q_0(m_0)$",m0,NW); label("$Q_1(m_1)$",m1,N); label("$Q_2(m_2)$",m2,NE); label("$Q_3(m_3)$",m3,N); label("$Q_4(m_4)$",m4,N); label("$P(z_2)$",z2,N); draw(Label("$\vec{Q_1Q_0}$",LeftSide),z2--z2+(m0-m1),Arrow()); draw("$\vec{Q_1Q_2}$",z2+(m0-m1)--z2+(m0-m1)+(m2-m1),Arrow()); draw(Label("$\tiny\frac{1}{6}\vec{a}=\vec{Q_1Q_0}+\vec{Q_1Q_2}$",LeftSide), z2--(z2+accel(CourbeBezier,t)/6),Arrow()); draw("$\tiny\frac{1}{3}\vec{v}=\vec{Q_3Q_4}$",z2--(z2+(m4-m3)),Arrow());


Attention, j'ai trouvé l'erreur signalée précédemment : l'emploi de dirtime ne fonctionnait pas dans des cas particuliers où il y a des tangentes qui sont parallèles. Le "time" renvoyé n'était pas celui du point étudié.
En plus, la solution était tout simplement de remplacer :
Code: Tout sélectionner
z2--(z2+accel(CourbeBezier,dirtime(CourbeBezier,m4-m3))/6)

par
Code: Tout sélectionner
z2--(z2+accel(CourbeBezier,t)/6)

(avec t=1/2 dans mon premier exemple (moins général que le second) ; je ne sais plus pourquoi j'avais eu l'impression que le "time" du point n'était pas simplement 1/2 dans mon premier cas... ce qui m'avait amené à ce délire avec "dirtime". Passons.).

Re: Courbe de Bézier - Accélération - Fonction accel(path,re

MessagePosté: Jeudi 03 Novembre 2011, 18:52
par GMaths
Pour être complet sur le sujet de la fonction accel, un exemple du champ de vecteurs "accélération" pour un path donné (courbe de Bézier par morceaux)
avec les constructions de ces vecteurs en trois points particuliers (conformément à l'égalité vectorielle donnée sur la figure précédente).

Image

Code: Tout sélectionner
import geometry;
size(15cm,0);
path p=(-5,0)..(20,0)..(20,10)..(0,20)..(-15,10)..(-5,15)..cycle;
draw("p",p); dot(p,2bp+black);
pair po, pa;
for(real k=0; k<length(p); k+=.01)
{
  po=point(p,k);
  pa = po+(accel(p,k))/6;
  draw(po--pa,red);
}
void acceleration(path p, int k, real t){
     pair z0=point(p,k),
          c0=postcontrol(p,k),
          z1=point(p,k+1),
          c1=precontrol(p,k+1),
          m0=(1-t)*z0+t*c0,
          m1=(1-t)*c0+t*c1,
          m2=(1-t)*c1+t*z1,
          m3=(1-t)*m0+t*m1,
          m4=(1-t)*m1+t*m2,
          z2=(1-t)*m3+t*m4;
     path CourbeBezier = z0 .. controls c0 and c1 .. z1;
     draw(CourbeBezier,1bp+blue);
     path lignebrisee = z0 -- c0 -- c1 -- z1;
     draw(lignebrisee^^m0--m1--m2^^m3--m4,linetype("4 4"));
     dot(z0^^z1^^z2,blue); dot(c0^^c1,gray);
     dot(m0--m1--m2^^m3--m4,green);
     draw(z2--(z2+accel(CourbeBezier,t)/6),.8bp+.5green,Arrow());
}
acceleration(p,1,.75);
acceleration(p,3,.75);
acceleration(p,5,.75);
addMargins(2mm,2mm);