Programmation C/Courbe de Bézier

Un livre de Wikilivres.
Sauter à la navigation Sauter à la recherche

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);
  }