Programmer une courbe spline

Le problème exposé dans ce sujet a été résolu.

Salut !

Je voudrais afficher à l’écran une courbe spline ayant trois points de contrôle : un situé à sa première extrémité, un autre vers le milieu, et le dernier à son autre extrémité. Pour ce faire, j’ai recours à cette définition :

$\forall t \in [0 ; 1], C(t) = \sum\limits_{i=1}^{k}F_i(t)P_i$

Avec :

  1. "t" l’abscisse du point à construire

  2. "C" la fonction définissant soit l’abscisse, soit l’ordonnée du point à construire en fonction de "t"

  3. "k" le nombre de points de contrôle

  4. "F_i" une fonction de déformation de la courbe

  5. "P_i" soit l’abscisse, soit l’ordonnée du point de contrôle de la courbe

Autrement dit, chaque point de la courbe a pour abscisse : la somme des produits "image d’une fonction de déformation en ’t’ multipliée par l’abscisse du point de contrôle". Même raisonnement pour l’ordonnée de chaque point de la courbe.

Question

J’ai lu ça dans mon cours et j’ai voulu tester avec :

  1. $t \in [0 ; 19]

  2. $k = 3$

  3. $F_i = 2 || 1 || 0.5$

  4. $P_i$ étant soit au début de la courbe, soit à peu près à son milieu en abscisse mais très haut en ordonnée, soit à son autre extrémité.

Voici le résultat graphique et le problème qui semble apparaître :

Image utilisateur

Comment se fait-il que le point de contrôle du milieu ne force pas la courbe à monter du point de contrôle du début jusqu’au milieu, puis à descendre du point de contrôle du milieu jusqu’à la fin ?

Le code (HTML, JS, CSS)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<html style="background : black;">
</html>

<script>
var pc_0_x = 0, pc_0_y = 0;
var pc_1_x = 19, pc_1_y = 19;
var pc_2_x = 9, pc_2_y = 0;

var new_p_x = 0, new_p_y = 0
for(i = 0; i < 20; i++) {

        new_p_x = 2*i*pc_0_x + 1*i*pc_2_x + 0.5*i*pc_1_x;
        new_p_y = 2*i*pc_0_y + 1*i*pc_2_y + 0.5*i*pc_1_y;

        document.body.innerHTML += "<div style = 'display : inline-block; background : white; padding : 1px; position : absolute; left : " + new_p_x + "; top : " + new_p_y + ";'></div>";
i
}
</script>

Merci d’avance ! ^^

+0 -0

Salut,

Ce que tu as codé n’as pas grand chose à voir avec la définition que tu as donnée, tu as un *i qui traîne partout et qui est responsable de ton résultat étrange. La définition de $C$ que tu donnes est pas super claire par ailleurs, si $t$ est l’abscisse des points à produire, tu n’as pas besoin de calculer les abscisses en question puisque tu connais déjà leur valeur…

+0 -0

La définition de CC que tu donnes est pas super claire par ailleurs, si tt est l’abscisse des points à produire, tu n’as pas besoin de calculer les abscisses en question puisque tu connais déjà leur valeur…

Oui, effectivement j’ai pensé à ça hier, c’est bizarre. Sauf que si je ne recalcule pas l’abscisse, les points de contrôle modifieront ma courbe qu’en ordonnée, c’est problématique.

Le produit par $$i$$ correspond à l'antécédent des fonctions $$F_i$$.

Les points de ta courbe sont calculés en multipliant $i$ par des constantes. C’est une fonction affine en $i$, aucune chance que tu obtiennes un polynôme par morceaux.

thulemalta

Oui mais est-ce le seul problème ? J’ai l’impression d’avoir mal compris la définition en fait, ça me stresse o_O

Je pense envoyer un mail à la prof

Oui, effectivement j’ai pensé à ça hier, c’est bizarre. Sauf que si je ne recalcule pas l’abscisse, les points de contrôle modifieront ma courbe qu’en ordonnée, c’est problématique.

En quoi est-ce problématique ? Si $t$ est l’abscisse, tu peux bien voir le spline comme une fonction de $t$ et tu as juste besoin de savoir calculer l’ordonnée qui correspond à une abscisse quelconque. Cette ordonnée sera bien sûr à calculer en fonction des points à interpoler.

Le produit par $i$ correspond à l′antécédent des fonctions $F_i$.

Là j’ai beau me creuser la tête, je pige pas du tout ce que tu essayes de dire. $i$ est juste l’indice des points présent, il ne fait partie ni de l’ensemble de départ ni de celui d’arrivé des fonctions. Sa valeur n’a aucune raison d’intervenir dans le calcul de $C$.

+0 -0

Alors en fait, dans la formule :

  1. $$t$$ correspond à une sorte d’identificateur du point de la courbe qu’on souhaite placer donc oui "l’indice des points présents" comme tu le dis

  2. Le résultat des fonctions $$F_i$$ est un coefficient qui, multiplié aux coordonnées x et y du point de contrôle correspondant, permet de déterminer si le point que l’on souhaite placer est plus ou moins près du point de contrôle.

Donc au final c’est assez simple !

La prof a validé ça, et j’ai écrit ce code (non divulgué à la prof mais il marche, j’ai testé - juste que les polynômes sont mal choisis donc les points de contrôle sont un peu WTF et la courbe n’est pas très belle). Si on bouge les points de contrôle, on bouge bien tout ou partie de la courbe, bref ça marche ! :D

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<html style="background : black;">
</html>

<script src="jquery-ui/jq.js"></script>
<script src="jquery-ui/jquery-ui.min.js"></script>

<script>

function p1(t) {
    return 2*Math.pow(t, 3) - 3*Math.pow(t, 2) + 1;
}

function p2(t) {
    return -2*Math.pow(t, 3) + 3*Math.pow(t, 2);
}

function p3(t) {
    return Math.pow(t, 3) + 3*Math.pow(t, 2);
}

var pcs = new Array([0, 0], [13, 13], [40, 40]);

var new_p_x = 0, new_p_y = 0

/* Draws curve's points and control points */
function draw() {
document.body.innerHTML = "";
var result_p = 0;
for(i = 0; i <= 1; i+=0.01) { // Draws the curve according to mathematics
    new_p_x = 0;
    new_p_y = 0;

    for(b = 0; b < pcs.length; b++) {

    switch(b) {

        case 0 :
        result_p = p1(i);
        break;

        case 1 :
        result_p = p2(i);
        break;

        case 2 :
        result_p = p3(i);
        break;

    }

        new_p_x += result_p*pcs[b][0];
    new_p_y += result_p*pcs[b][1];

    }

    document.body.innerHTML += "<div style = 'display : inline-block; background : white; padding : 1px; position : absolute; left : " + new_p_x + "; top : " + new_p_y + ";'></div>";
}

for(b = 0; b < pcs.length; b++) { // Draws the control points
document.body.innerHTML += "<div class='pc' id='" + b + "' draggable='true' style = 'cursor : hand; display : inline-block; background : red; padding : 5px; position : absolute; left : " + pcs[b][0] + "; top : " + pcs[b][1] + ";'></div>";


};

    $('.pc').draggable({'drag' : function(event, ui) { movePC(event.target.id, event.pageX, event.pageY); } });

}

/* We update the coordinates of the control points and re-draw the graph (curve's points and control points are re-drawn)  */
function movePC(indice, cursor_x, cursor_y) {

    pcs[indice][0] = cursor_x;
    pcs[indice][1] = cursor_y;

    draw();
}

draw(); // We draw the graph when the user visits this Web page
</script>

Alors en fait, dans la formule :

$t$ correspond à une sorte d’identificateur du point de la courbe qu’on souhaite placer donc oui "l’indice des points présents" comme tu le dis

Je parlais de $i$ (l’indice entier des points de contrôles), pas de $t$ (qui est d’après ce que tu dis et ton code, un paramètre variant le long du spline, pas un indice).

D’ailleurs, dans ton code, tu as appelé $t$ i, et tu as hardcodé les valeurs de $i$ (qui sont les entiers 1, 2 et 3).

Bref, l’important c’est que ça fonctionne et que tu ais compris.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte