Aller au contenu

Programmation C/Courbe de Bézier

Un livre de Wikilivres.

Ce code permet de tracer une courbe de Bézier définie par 4 points de contrôle. C'est donc une courbe cubique. Cet algorithme est une implémentation de l'algorithme de Casteljau.

Pour adapter ce code C à votre système, il vous suffit de remplacer la procédure de tracé de segment (ici en OpenGL).

La structure Global_Bezier contient les 4 points de contrôle de la courbe de Bézier à tracer. level contient le nombre d'appel récursif.

#include <GL/glu.h>

typedef struct
{
    float x, y;
}
point;

typedef struct
{
    point P[4];
}
Bezier;

/* Variables globales */
Bezier Global_Bezier;
int level=1;

// Draw a line with color (r,v,b)
void DrawLine(int x1, int y1, int x2, int y2,float r, float v, float b)
{
    glColor3f(r,v,b);
    glBegin(GL_LINES);
    glVertex2i(x1,y1);
    glVertex2i(x2,y2);
    glEnd();
    glFlush();
}

void DrawBezierBase(Bezier p,float r,float v,float b)
{
    DrawLine(p.P[0].x,p.P[0].y,p.P[1].x,p.P[1].y,r,v,b);
    DrawLine(p.P[1].x,p.P[1].y,p.P[2].x,p.P[2].y,r,v,b);
    DrawLine(p.P[2].x,p.P[2].y,p.P[3].x,p.P[3].y,r,v,b);
}

void DrawBezierRecursive (Bezier b, int level) 
{
    if (level <= 0)
        /* draw a line segment */
        DrawLine((int) (b.P[0].x + 0.5), (int) (b.P[0].y + 0.5),
                 (int) (b.P[3].x + 0.5), (int) (b.P[3].y + 0.5),1,1,1);
    else
    {
        Bezier left, right;                 
        /* subdivide into 2 Bezier segments */
        left.P[0].x = b.P[0].x;
        left.P[0].y = b.P[0].y;
        left.P[1].x = (b.P[0].x + b.P[1].x) / 2;
        left.P[1].y = (b.P[0].y + b.P[1].y) / 2;
        left.P[2].x = (b.P[0].x + 2*b.P[1].x + b.P[2].x) / 4;
        left.P[2].y = (b.P[0].y + 2*b.P[1].y + b.P[2].y) / 4;
        left.P[3].x = (b.P[0].x + 3*b.P[1].x + 3*b.P[2].x + b.P[3].x) / 8;
        left.P[3].y = (b.P[0].y + 3*b.P[1].y + 3*b.P[2].y + b.P[3].y) / 8;
        DrawBezierBase(left,0,1,0);
        right.P[0].x = left.P[3].x;
        right.P[0].y = left.P[3].y;
        right.P[1].x = (b.P[1].x + 2*b.P[2].x + b.P[3].x) / 4;
        right.P[1].y = (b.P[1].y + 2*b.P[2].y + b.P[3].y) / 4;
        right.P[2].x = (b.P[2].x + b.P[3].x) / 2;
        right.P[2].y = (b.P[2].y + b.P[3].y) / 2;
        right.P[3].x = b.P[3].x;
        right.P[3].y = b.P[3].y;
        DrawBezierBase(right,0,0,1);
        /* draw the 2 segments recursively */
        DrawBezierRecursive (left, level -1);
        DrawBezierRecursive (right, level -1);
    }
}

void DrawBezier()
{
    DrawBezierBase(Global_Bezier,1,0,0);
    DrawBezierRecursive(Global_Bezier,level);
}