CoreAnimation et CGPath : faire une "pause"

AliGatorAliGator Membre, Modérateur
13:49 modifié dans API UIKit #1
Bonjour,

J'ai une subview (de type UIImageView) que je souhaite animer pour la déplacer en suivant un CGPath donné (courbe de bézier), tout en faisant en sorte que son orientation suive le path.
Jusque là , pas de problème, les CAKeyframeAnimations sont là  pour ça, en définissant la propriété "path" de cette animation avec mon CGPath et mettant le rotationMode à  kCAAnimationRotateAuto.

Mais là  où ça se corse, c'est que j'aimerais faire une pause dans mon animation. En effet j'ai plusieurs vues à  animer en même temps, dont les positions et orientations de chacune sont définies par un tableau de "CarPosInfo" (une classe perso qui définit entre autres la position et l'orientation de ma vue à  un temps T donné, à  une keyframe quoi).
Ainsi, je calcule mon CGPath de trajectoire pour chacune de mes vues en fonction du tableau de "CarPosInfo" qui lui est associé, ajustant mes controlPoints de mon CGPath de sorte que la tangente à  ma courbe de bézier corresponde à  l'orientation souhaitée de ma vue à  ce point.

Ca marche bien, j'arrive à  faire animer ma vue de sorte qu'elle suive la trajectoire avec la bonne orientation à  l'endroit de mes points clés. Mais le souci vient des cas où j'ai, pour une de mes vues, un point clé identique entre 2 keyframes. Autrement dit, pendant que les autre vues continuent à  s'animer, je veux qu'une de mes vues "fasse une pause" et s'arrête à  l'endroit où elle est (pendant que les autres, elles, avancent d'une frame N à  la frame N+1).

Si je garde mon principe actuel, j'ajoute une courbe (AddCurveToPoint) du point P... au même point P. Oui mais voilà , du coup lors de l'animation, le rotationMode kCAAnimationRotateAuto du coup n'aime pas, car il ne sait pas voir la tangente locale, forcément... (donc en résultat, ma vue est horizontale, même si localement elle devrait avoir une autre orientation).

Donc du coup je vois pas comment faire cette "pause".... Des idées ?

(Bon je sais pas si mon énoncé a été très bien exprimé, si vous avez besoin que j'éclaircisse...)

Réponses

  • Philippe49Philippe49 Membre
    13:49 modifié #2
    Et en insérant  P à  P+epsilon.T, cela devrait conserver la tangente ?
    T=(P'-P)/||P'-P|| où P' est le point suivant normalement P
  • schlumschlum Membre
    13:49 modifié #3
    J'ai pas trop compris ta technique de calcul, mais si le problème est de calculer un point ou une tangente d'une courbe de Bézier, ce sont des calculs assez simples :

    P(t) = P0*(1-t)^3+3*P1*t*(1-t)^2+3*P2*t^2*(1-t)+P3*t^3
    Avec t entre 0 et 1, la courbe allant de P0 à  P3 avec P1 et P2 comme points de contrôle.

    Pour avoir la tangente, il suffit de dériver en t si mes cours de prépa ne sont pas trop loin  :o
  • schlumschlum Membre
    13:49 modifié #4
    J'ai fait le calcul pour la dérivée, j'espère qu'il est pas faux... Dur de se remettre aux calculs de dérivées  ;D

    P'(t) = 3*(P3*t^2+P2*t*(2-3*t)+P1*(t-1)*(3*t-1)-P0*(1-t)^2)

    En 0, ça donne 3*(P1-P0)
    En 1, ça donne 3*(P3-P2)
    En 1/2, ça donne (3/4)*((P3-P0)+(P2-P1))

    Ce qui ne me semble pas illogique  :p
  • AliGatorAliGator Membre, Modérateur
    13:49 modifié #5
    Non non non stop schlum, le problème n'est pas de calculer la tangente, d'autant que la définition d'un bezierPath utilise des points de contrôle... qui représentent la tangente à  cette courbe en ce point !!
    Ainsi quand ton CGPath est au point A et que tu demandes CGPathAddCurveToPoint(Ca, Cb, B), tu lui fournis le point de contrôle Ca au point A et le point de contrôle Cb au point B... Eh bien la demi-droite [A,Ca) est tangente à  ta courbe au point A, et [B,Cb) est tangente à  ta courbe au point B. Ce qui m'arrange, puisque c'est cette contrainte de tangence qui m'intéresse, pour imposer l'orientation de ma vue.


    Non le souci c'est que je construis mon CGPath par des points clés définis par une position et un angle (point de départ défini par CGPathMoveToPoint, et points suivants définis par CGPathAddCurveToPoint). Je vais ainsi du point A, en partant d'une orientation de rA radians, au point B, avec une orientation de rB radians... puis continue vers le point C, orientation rC radians... quand ensuite je construit ma CAKeyframeAnimation en lui demandant d'utiliser ce path pour animer le mouvement, ça marche très bien.

    Oui mais si le point B et le point C sont identiques, là  ça déconne, car si ma vue reste bien alors au même endroit, son orientation part en c**ille.


    Exemple pour mieux comprendre : Si j'ai ma vue en (0,10), orienté selon un angle a (disons grosso-modo vers la gauche), au moment T, et qu'au moment T+∆T je la veux en (0,20) un peu plus bas, même orientation a : alors la courbe de bézier de ma trajectoire va faire un S, partant vers la gauche, tournant dans le sens inverse des aiguilles d'une montre de 180°, puis dans l'autre sens de 180°, pour se retrouver au point B, encore orienté vers la gauche. Ok ?
    Maintenant imaginons qu'on rapproche le point B non plus en (0,20) mais en (0,10+k)... au cas limite où k temps vers 0, on retrouve mon cas des points qui se confondent... Mais le problème c'est que même dans cet espace infinitésimal, ma courbe de bézier a cette forme de S. Certes elle est concentrée en un point unique, mais quand la CAKeyframeAnimation utilise ce path, il n'empêche qu'elle semble tout de même suivre cette forme en S, puisque ma vue même si elle reste sur place va quand même tourner à  180° dans un sens, puis dans l'autre, pour revenir à  son orientation originale... dont j'aurais bien voulu qu'elle ne change jamais !
  • AliGatorAliGator Membre, Modérateur
    avril 2009 modifié #6
    Extrait de mon code (contenu dans une boucle "for" qui parcourt chacune de mes points clés (définissant chacun une position + une orientation de ma vue à  ces moments clés).
    - prevPos est le point de départ,
    - nextPos est le point d'arrivée à  la "frame" suivante,
    Et voilà  donc comment je rajoute à  mon CGPath la courbe allant de la position prevPos.position, orienté selon l'angle prevPos.angle, à  la position nextPos.position, orienté à  l'arrivée selon l'angle nextPos.angle :
    [tt]// coefficient influançant la courbure selon la distance entre les 2 points
    float L = 1+CGDistance(prevPos.position,nextPos.position)/2; // CGDistance : fonction perso pour calculer la distance euclidienne
    // coefficient pour influencer la courbure selon la différence d'angle
    float k = 1+fabs(nextPos.angle-prevPos.angle)/M_PI;

    // points de contrôle de départ et d'arrivée
    CGPoint cp1 = CGPointMake(prevPos.position.x   +L*cos(prevPos.angle) , prevPos.position.y   +L*sin(prevPos.angle));
    CGPoint cp2 = CGPointMake(nextPos.position.x -k*L*cos(nextPos.angle) , nextPos.position.y -k*L*sin(nextPos.angle));

    // Et enfin donc ma courbe de bézier définissant la trajectoire de prevPos à  nextPos
    CGPathAddCurveToPoint(path, NULL,cp1.x, cp1.y,cp2.x, cp2.y,nextPos.position.x, nextPos.position.y);[/tt]


    --

    Je pense que la solution la plus proche pour l'instant est celle de Philippe49, à  savoir utiliser l'artifice qui consiste, si mes 2 points se confondent, à  déplacer mon 2e points d'une valeur FLT_EPSILON avant de continuer mes calculs comme si de rien était.

    PS : Si vous avez des conseils pour adapter mes coefficients L et k*L pour ajuster la courbe... Le but est d'avoir une trajectoire entre (position1, angle1) et (position2, angle2) la plus naturelle possible (mes vues représentent des voitures, la trajectoire celle de la voiture donc).
  • Philippe49Philippe49 Membre
    13:49 modifié #7
    1) Si tu veux arrêter un mouvement momentanément :

    Quand tu fais un Bezierpath A,cp1,cp2,B, la tangente en B relie cp2 à  B.
    Si tu passes  en B sans boucle, tu suis la direction de la tangente en prenant une curve  B,B+epsilon*(B-cp2),B+epsilon*(B-cp2),B+2*epsilon*(B-cp2)
    ou même faire un simple segment de raccordement. Si epsilon est assez petit, mais pas trop, à  mon avis le point ne bougera pas, et la tangente sera la même.


    2)  Si tu veux raccorder deux keyframes

    A ce moment là , il faut raccorder en B les formules par
    lastB-lastCp2 positivement colinéaires à   newCp2-newB
  • AliGatorAliGator Membre, Modérateur
    13:49 modifié #8
    dans 1238882343:

    1) Si tu veux arrêter un mouvement momentanément :

    Quand tu fais un Bezierpath A,cp1,cp2,B, la tangente en B relie cp2 à  B.
    Oui je suis bien d'accord, c'est grosso modo ce que j'expliquais à  schlum au début de mon message plus haut : c'est justement ce qui m'arrange, j'ai juste à  calculer cp1 = {Ax+cos(Ω),Ay+sin(Ω)} en gros à  qques coeffs près pour que ma courbe corresponde à  ce que je veux dans le cas générique.

    dans 1238882343:
    Si tu passes  en B sans boucle, tu suis la direction de la tangente en prenant une curve  B,B+epsilon*(B-cp2),B+epsilon*(B-cp2),B+2*epsilon*(B-cp2)
    ou même faire un simple segment de raccordement. Si epsilon est assez petit, mais pas trop, à  mon avis le point ne bougera pas, et la tangente sera la même.
    Oui je pense que c'est ce que je vais finir par faire... d'autant que ça me gênais quand même de déplacer ma vue d'un pixel pour ça... mais un déplacement de ε=FLT_EPSILON ne devrais pas se voir lors du rendu, tout en permettant à  ce que l'animation ne fasse pas de boucle non voulue

    dans 1238882343:

    2)  Si tu veux raccorder deux keyframes

    A ce moment là , il faut raccorder en B les formules par
    lastB-lastCp2 positivement colinéaires à   newCp2-newB
    Heu là  j'ai pas tout compris... qu'est ce que tu appelles lastB/lastCp2 et newCp2/newB ?
    C'est pas ce que je fais dans mon calcul (cf mon extrait de code post précédent) ?
  • AliGatorAliGator Membre, Modérateur
    avril 2009 modifié #9
    Bon j'ai implémenté la solution avec le décalage d'un petit epsilon, ça marchotte...
    Pour info voilà  mon bout de code (CarPosInfo est une classe perso qui stocke essentiellement la position et l'angle de ma vue) :
    CarPosInfo* prevPos = (CarPosInfo*)[frames objectAtIndex:startFrame];<br />	CGPoint prevDrawPt = prevPos.position;<br />	CarPosInfo* nextPos = nil;<br />	CGPoint nextDrawPt;<br />	static const float eps = 1.f;<br />	<br />	CGMutablePathRef path = CGPathCreateMutable();<br />	CGPathMoveToPoint(path, NULL, prevDrawPt.x, prevDrawPt.y);<br />	NSLog(@&quot;trajectory from frame %d to %d : starts at %@&quot;,startFrame,endFrame,NSStringFromCGPoint(prevDrawPt));<br /><br />	for(NSInteger i=startFrame+1;i&lt;=endFrame;i++)<br />	{<br />		nextPos = (CarPosInfo*)[frames objectAtIndex:i];<br />		if (CGPointEqualToPoint(nextPos.position, prevPos.position))<br />		{<br />			nextDrawPt = CGPointMake(prevDrawPt.x+eps*cos(nextPos.angle), prevDrawPt.y+eps*sin(nextPos.angle));<br />		} else {<br />			nextDrawPt = nextPos.position;<br />		}<br /><br />		float L = MAX(1,CGDistance(prevDrawPt,nextDrawPt)/2);<br />		CGPoint cp1 = CGPointMake(prevDrawPt.x +L*cos(prevPos.angle) , prevDrawPt.y +L*sin(prevPos.angle));<br />		CGPoint cp2 = CGPointMake(nextDrawPt.x -L*cos(nextPos.angle) , nextDrawPt.y -L*sin(nextPos.angle));<br />		CGPathAddCurveToPoint(path, NULL,cp1.x, cp1.y,cp2.x, cp2.y,nextDrawPt.x, nextDrawPt.y);<br />			<br />		NSLog(@&quot;                          then curves to %@ (in fact %@)&quot;,NSStringFromCGPoint(nextPos.position), NSStringFromCGPoint(nextDrawPt));<br />		prevPos = nextPos;<br />		prevDrawPt = nextDrawPt;<br />	}<br />	return path; // don&#39;t forget to CGPathRelease it !<br />}
    
    Le truc c'est que j'utilise donc une valeur [tt]eps[/tt], qui me permet de décaler mon point d'un petit delta (enfin epsilon plutôt ^^) pour éviter la boucle... mais si je met moins que 1.f comme valeur (je pensais en particulier à  qqch comme 0.1 voire même FLT_EPSILON pensant qu'il faisait les calculs côté subpixels), bah ça marche pas, il faut un minimum de un pixel... du coup ça reste visible comme décalage, ça m'embête un peu (d'autant que ce n'est que pour l'animation, à  la fin je remet la vraie position, donc s'il y a un décalage il est visible).

    Donc je pense que pour le moment je vais garder cette solution, mais à  terme je vais décomposer moi-même mon animation keyframe par keyframe. Ca m'embête un peu juste pour ce détail en plus ça va être un peu plus ch*ant à  gérer mais bon.

    D'autant que je vais aussi avoir à  gérer le cas où l'on demande de changer de frame avant la fin de l'animation précédente : genre je demande de passer de la frame 1 à  la 5, ça commence l'animation... et si je demande ensuite à  passer à  la frame 3 avant la fin de la première animation... ça doit interrompre la première animation et repartir de l'endroit où c'était rendu pour aller à  la frame 3, et là  au lieu de ça ça part en vrille, je pense que ça compose les animations... donc bon encore un truc à  régler !
  • Philippe49Philippe49 Membre
    avril 2009 modifié #10
    dans 1238892107:

    D'autant que je vais aussi avoir à  gérer le cas où l'on demande de changer de frame avant la fin de l'animation précédente : genre je demande de passer de la frame 1 à  la 5, ça commence l'animation... et si je demande ensuite à  passer à  la frame 3 avant la fin de la première animation... ça doit interrompre la première animation et repartir de l'endroit où c'était rendu pour aller à  la frame 3, et là  au lieu de ça ça part en vrille, je pense que ça compose les animations... donc bon encore un truc à  régler !

    Interrompre une animation ? je doute, il faudrait agir dans le thread de cette animation. Enchaà®ner oui. 



    On peut chercher si on peut définir les ticks avec CAMediaTimingFunction, (comme NSAnimation avec les progressMarks) dans le non-documenté ?

    [EDIT] Rien de bien enthousiasmant
    @interface CAMediaTimingFunction : NSObject &lt;NSCoding&gt;<br />{<br />&nbsp; &nbsp; struct CAMediaTimingFunctionPrivate *_priv;<br />}<br /><br />+ (id)functionWithControlPoints:(float)fp8:(float)fp12:(float)fp16:(float)fp20;<br />+ (id)functionWithName:(id)fp8;<br />- (id)initWithControlPoints:(float)fp8:(float)fp12:(float)fp16:(float)fp20;<br />- (void)dealloc;<br />- (void)finalize;<br />- (void)_getPoints:(float *)fp8;<br />- (void)getControlPointAtIndex:(unsigned long)fp8 values:(float [2])fp12;<br />- (void)encodeWithCoder:(id)fp8;<br />- (id)initWithCoder:(id)fp8;<br /><br />@end<br /><br />@interface CAMediaTimingFunction (CAMediaTimingFunctionPrivate)<br />- (float)_solveForInput:(float)fp8;<br />@end<br />
    
  • schlumschlum Membre
    avril 2009 modifié #11
    dans 1238880774:

    Non non non stop schlum, le problème n'est pas de calculer la tangente, d'autant que la définition d'un bezierPath utilise des points de contrôle... qui représentent la tangente à  cette courbe en ce point !!


    Oui, évidemment, on le retrouve d'ailleurs dans mon calcul en t=0 et t=1... Mais c'est fortement imprécis, non ?
    Tu n'as la tangente que sur les points donnés, et pas entre... Du coup si tu as des points trop espacés (ou même si tu fais un zoom sur ta courbe), ça va faire n'importe quoi.
    Après, si tu n'as que des points très proches, je ne vois pas l'intérêt d'une courbe de Bézier, une approximation par segments est tout à  fait correcte... et fonctionne même quand les points sont trop proches.
  • schlumschlum Membre
    avril 2009 modifié #12
    Ah, je viens de comprendre que tu fais l'inverse de ce qui me semblait logique pour un jeu de courses de voitures, à  savoir définir le circuit par des courbes de Bézier pour pouvoir ensuite avoir la position et l'orientation en tout point.

    Donc tu définis ton circuit par des tableaux de positions / orientations pour créer le chemin de Bézier (je suppose un point avant et après chaque tournant...).

    Mais en plein milieu d'un tournant, ton orientation doit être faussée non ?
  • AliGatorAliGator Membre, Modérateur
    13:49 modifié #13
    Alors il ne s'agit pas d'un jeu de courses de voiture, il s'agit de permettre à  l'utilisateur de décrire la trajectoire approximative d'une voiture en définissant 4 ou 5 positions et orientations clés.
    L'utilisateur se positionne sur la "frame" 1, indique par toucher sur l'écran la position de la ou des voiture(s) et leur orientation au temps T=1, puis se positionne sur la frame 2 et fait la même chose... au fur et à  mesure, la trajectoire estimée est tracée, et à  la fin il peut lancer une animation pour voir la/les voiture(s) bouger de la première à  la dernière frame.

    Quand j'utilisateur change de frame, si c'est la première fois qu'il ton sur cette frame (création de la frame), je reprend la position et orientation de la frame précédente... mais s'il navigue de frame en frame pour revenir sur ses pas, réavancer, etc... c'est là  que je rajoute une animation pour passer d'une frame à  l'autre. De même, quand il a fini et qu'il veut animer le tout, je lance l'animation complète qui va de la frame 1 à  la dernière frame.

    Je tâche de sortir ça de mon projet et de faire un projet à  part pour vous le poster, ça sera sans doute plus propre si vous voulez avoir une idée plu claire.
  • schlumschlum Membre
    13:49 modifié #14
    OK, j'ai compris globalement la chose (j'avais pas vu que l'animation gérait toute seule l'orientation).

    Et si au lieu de faire un "addCurveToPoint", tu fais un "addLineToPoint", ça ne résout pas le problème ?
  • AliGatorAliGator Membre, Modérateur
    13:49 modifié #15
    dans 1238951746:

    OK, j'ai compris globalement la chose (j'avais pas vu que l'animation gérait toute seule l'orientation).

    Et si au lieu de faire un "addCurveToPoint", tu fais un "addLineToPoint", ça ne résout pas le problème ?
    Non c'est ce que j'avais essayé, ainsi qu'un moveToPoint, mais rien.

    Mais j'ai fini par régler le problème, je ne fais plus un gros path, mais décompose mon animation frame par frame et ne fait mes paths que de la frame N à  la frame N+1.
    Du coup si à  un moment de mon animation complète, entre la frame N et la frame N+1, ma position ne change pas, bah j'anime simplement pas ma vue entre ces 2 frames, puis je reprend en faisant un CGPath pour la frame N+1 à  N+2...

    J'ai fait un projet séparé au propre où j'ai tout refactoré, ça commence à  prendre forme, je poste ça ensuite pour info.
  • AliGatorAliGator Membre, Modérateur
    13:49 modifié #16
    Bon voilà  le mini-projet que j'ai fait pour extraire ce bout de truc.
    Description
    Quand vous lancez, vous avez deux vues représentant des voitures A et B, et vous pouvez les déplacer par un touch, et changer leur orientation par un multitouch.
    Ma classe SketchView représente la vue principale avec le plan, et contient 2 "CarView"s en subviews. CarPosInfo me sert pour stocker une position+orientation d'une voiture à  un instant T (une CarView contient un tableau de 5 CarPosInfos car y'a maxi 5 frames)

    Utilisation
    Dans la toolbar en bas vous pouvez passer ensuite à  la frame suivante (si c'est la première fois que vous allez dessus, les positions et orientations des voitures sont recopiées de la frame précédente), et modifier la position et orientation des voitures. La trajectoire commence alors à  apparaà®tre, au fur et à  mesure que vous rajoutez des frames et déplacez les voitures entre ces frames.

    Ensuite si vous passez d'une frame à  l'autre c'est animé en suivant la trajectoire, et avec le bouton "Play" vous pouvez animer toutes les frames de 0 à  N (animation plus lente que la manuelle)

    Conclusion
    Donc ça a fini par marcher, il me reste juste un petit truc qui m'embête, c'est que mes CGPath vont de la position N à  la position N+1, tant pour tracer la trajectoire que pour l'animation... du coup le temps de lancer l'animation, je dois repositionner temporairement mes vues en 0,0 (transform = Identity), et la restaurer à  la fin de l'animation.
    D'une part je trouve pas ça super propre, et de plus parfois on voit (oh c'est juste un flash très court mais quand même) la voiture en (0,0) juste avant qu'elle soit restaurée à  la position de fin...
    Je vois pas trop comment zapper ce problème, si vous avez une idée...
  • schlumschlum Membre
    13:49 modifié #17
    Si c'est un projet iPhone, je ne pourrai pas le lancer... Suis toujours sur G5 moi  :) (et pas encore installé le SDK sur mon MacBook Pro de boulot...)
  • AliGatorAliGator Membre, Modérateur
    13:49 modifié #18
    C'est en effet le cas, c'est un projet iPhone ;)
    Bon tu peux lire le code, il est pas si méchant, mais bon, la flemme de le porter sur mac ^^
  • CeetixCeetix Membre
    13:49 modifié #19
    Et tu penses que c'est le même systeme si je veux pour mon projet Graphe dessiner mes arcs ?
  • AliGatorAliGator Membre, Modérateur
    13:49 modifié #20
    Bah pour dessiner un arc courbe entre 2 points, un simple bezierpath suffit, et en effet c'est un peu le même principe. Tu crées un CGPath, tu le fais commencer au point A, puis tu lui demandes d'ajouter une Curve jusqu'au point B, en ajustant tes "control points" selon la tronche du chemin que tu veux.
    Bon dans mon programme c'était un peu plus complexe car d'une part je veux construire mon CGPath pour une animation CoreAnimation ensuite, et surtout je veux prendre en compte l'orientation de mes vues représentant mes voitures. Alors que pour par exemple un arbre genre B-Tree, les controlpoints sont tout trouvés, il suffit qu'ils soivent à  la verticale des points à  relier puisque ton path est principalement vertical dans son orientation.
  • CeetixCeetix Membre
    13:49 modifié #21
    Moi j'ai fait des NSBezierPath avec un curveToPoint et j'aimerai bien qu'on voit l'arc se dessiner quand on en ajoute un. Un petit effet rapide mais sympa.
  • AliGatorAliGator Membre, Modérateur
    13:49 modifié #22
    Je te propose d'ouvrir alors un autre sujet, ça sera plus adapté. J'ai bien plusieurs idées, toutes imparfaites ou alors bien casse-gueule à  implémenter, mais autant faire ça dans un sujet dédié.

    D'autant que moi j'ai pas fini avec celui là  :)
    Bah oui, j'ai toujours un problème, c'est que (j'ai essayé sur un vrai iPhone et non plus dans le simulateur, et là  c'est flagrant) à  la fin de mon animation, je vois ma vue en (0,0) " pendant juste un cycle de runloop/drawing " avant qu'elle ait le temps de se remettre à  la position finale. C'est bref, mais on voit quand même que pendant un cycle de rendu la vue est en (0,0), là  où je l'avais mise au début de mon animation " pour que sa propriété "transform" ne gène pas l'animation si elle n'est pas l'identité (si je le fais pas j'ai des animations bizarres) " du coup à  la fin de l'animation ça "saute" en (0,0) avant de re-sauter en (xFinal, yFinal)  :'(
  • schlumschlum Membre
    avril 2009 modifié #23
    dans 1239050991:

    Moi j'ai fait des NSBezierPath avec un curveToPoint et j'aimerai bien qu'on voit l'arc se dessiner quand on en ajoute un. Un petit effet rapide mais sympa.


    Je me demande si mes calculs ne pourraient pas servir pour le coup  :)
    On y est presque, à  un temps "t" (entre 0 et 1), on a le point et le vecteur tangente (vitesse) ; de là  à  trouver le contrôle point pour une sous-partie du path, il n'y a probablement pas loin.

    Peut être -V/3... (enfin assez empirique comme supputation  :P, mais en tout cas, c'est -V/qqch, qui peut être constant ou variable... mais le problème, c'est que le premier contrôle point subit peut-être une homothétie aussi...)
Connectez-vous ou Inscrivez-vous pour répondre.