L'exécutable : BSplines.exe

B-Splines-01-01.png (2833 octets) B-Splines-01-02.png (2931 octets)

B-Splines de Bezier

B-Splines-01-03.png (2671 octets) B-Splines-01-04.png (2698 octets)

B-Splines non rationnelles uniformes et de Catmull-Rom

B-Splines-02-01.png (4567 octets) B-Splines-02-02.png (4408 octets)

B-Splines de Catmull-Rom et B-Splines non rationnelles uniformes
La méthode fonctionne.

B-Splines-02-03.png (5569 octets)

B-Splines de Bézier
La méthode ne fonctionne pas.

Fichier source : BSplines.cpp

/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Novembre 2007                                */
/* Trace de B-Splines                           */

#include <stdio.h>
#include <stdlib.h>

#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>

/* Variables et constantes globales             */

static int solution = 0;
static int disc = 25;
static int mode = 0;
static int el = 0;
static int mat = 2;

/* Variables globales de gestion                */
/* de l'interactivite clavier et souris         */

static int clic = 0;
static int mx;
static int my;
static float rx = 0.0F;
static float ry = 0.0F;

/* Type de stockage d'une position              */

typedef struct position {
  double x;
  double y;
  double z;
  double t; } position;

/* Type de stockage d'une matrice de base       */

typedef double matriceDeBase[4][4];

/* Type de stockage d'une ligne polygonale      */

typedef struct lignePolygonale {
  int n;
  position *pts; } lignePolygonale;

/* Donnees statiques constantes                 */

static const float blanc[]   = { 1.0F,1.0F,1.0F,1.0F };
static const float rouge[]   = { 1.0F,0.0F,0.0F,1.0F };
static const float vert[]    = { 0.0F,1.0F,0.0F,1.0F };
static const float bleu[]    = { 0.0F,0.0F,1.0F,1.0F };
static const float jaune[]   = { 1.0F,1.0F,0.0F,1.0F };
static const float cyan[]    = { 0.0F,1.0F,1.0F,1.0F };
static const float magenta[] = { 1.0F,0.0F,1.0F,1.0F };
static const float c1[]      = { 0.3F,0.5F,0.7F,1.0F };
static const float c2[]      = { 0.5F,0.7F,0.3F,1.0F };
static const float c3[]      = { 0.7F,0.3F,1.5F,1.0F };
static const float *couleurs[10] = { rouge,vert,
                                     bleu,cyan,
                                     jaune,c3,
                                     magenta,c1,
                                     c2,blanc };
/* Donnees statiques                            */

static matriceDeBase mBNRU = 
  { { -0.1666666F, 0.5F,      -0.5F,      0.1666666F },
    {  0.5F      ,-1.0F,       0.5F,      0.0F       },
    { -0.5F      , 0.0F,       0.5F,      0.0F       },
    {  0.1666666F, 0.6666666F, 0.1666666F,0.0F       } };
static matriceDeBase  mBCR =
  { { -0.5F, 1.5F,-1.5F, 0.5F },
    {  1.0F,-2.5F, 2.0F,-0.5F },
    { -0.5F, 0.0F, 0.5F, 0.0F },
    {  0.0F, 1.0F, 0.0F, 0.0F } };
static matriceDeBase  mBB =
  { { -1.0F, 3.0F,-3.0F, 1.0F },
    {  3.0F,-6.0F, 3.0F, 0.0F },
    { -3.0F, 3.0F, 0.0F, 0.0F },
    {  1.0F, 0.0F, 0.0F, 0.0F } };
static matriceDeBase *mb = &mBB;
static position p1[10] =
  { { -6.0,-1.0, 5.0, 1.0 },
    { -1.0,-6.0,-4.0, 1.0 },
    {  3.0,-4.0, 1.0, 1.0 },
    {  6.0,-1.0, 0.0, 1.0 },
    {  5.0, 3.0,-2.0, 1.0 },
    {  1.0, 6.0, 4.0, 1.0 },
    { -1.0, 2.0, 1.0, 1.0 },
    { -4.0, 2.0, 2.0, 1.0 },
    { -5.0, 6.0,-3.0, 1.0 },
    { -2.0, 5.0,-6.0, 1.0 } };
static lignePolygonale lp = { 10,p1 };

/* Fonction de calcul du tableau de positions   */
/* d'evaluation d'une B-Spline cree             */
/* entre quatre positions                       */

position *calculBSpline(matriceDeBase m,position *pts,int n) {
  position *p =(position *) calloc(n,sizeof(position));
  for ( int i = 0 ; i < n ; i++ ) {
    double t =(double) i/(n-1);
    double tt[4] = { t*t*t,t*t,t,1.0 };
    double tn[4] = { 0.0,0.0,0.0,0.0 };
    int j;
    for ( j = 0 ; j < 4 ; j++ )
      for ( int k = 0 ; k < 4 ; k++ )
        tn[j] += tt[k]*m[k][j];
    for ( j = 0 ; j < 4 ; j++ ) {
      p[i].x += tn[j]*pts[j].x;
      p[i].y += tn[j]*pts[j].y;
      p[i].z += tn[j]*pts[j].z; }
    p[i].t = 1.0; }
  return(p);
}

/* Fonction d'initialisation des parametres     */
/* OpenGL ne changeant pas au cours de la vie   */
/* du programme                                 */

void init(void) {
  glClearColor(0.0,0.0,0.0,0.0);
}

void dessine(position *p,int n) {
  glPushMatrix();
  glBegin(GL_LINE_STRIP);
  for ( int i = 0 ; i < n ; i++ )
    glVertex3dv((double *) &p[i]);
  glEnd();
  glPopMatrix();
}

void solutionQuestionA(void) {
  switch (mode) {
    case 0 : 
    case 1 : 
    case 2 : position *p = calculBSpline(*mb,&p1[el],disc);
             glColor4fv(vert);
             dessine(p,disc);
             free(p);
             glColor4fv(blanc);
             dessine(&p1[el],4);
             break; }
}

void solutionQuestionB(void) {
  int i;
  switch (mode) {
    case 0 : glColor4fv(blanc);
             dessine(lp.pts,lp.n);
             break;
    case 1 : glColor4fv(blanc);
             dessine(lp.pts,lp.n);
             glColor4fv(vert);
             for ( i = 0 ; i < lp.n-3 ; i++ ) {
               position *p = calculBSpline(*mb,&lp.pts[i],disc);
               dessine(p,disc);
               free(p); }
             break;
    case 2 : glColor4fv(blanc);
             dessine(lp.pts,lp.n);
             for ( i = 0 ; i < lp.n-3 ; i++ ) {
               glColor4fv(couleurs[i]);
               position *p = calculBSpline(*mb,&lp.pts[i],disc);
               dessine(p,disc);
               free(p); }
             break; }
}

/* Scene dessinee                               */

void scene(void) {
  glPushMatrix();
  switch (solution) {
    case 0 : solutionQuestionA();
             break;
    case 1 : solutionQuestionB();
             break; }
  glPopMatrix();
}

/* Fonction executee lors d'un rafraichissement */
/* de la fenetre de dessin                      */

void display(void) {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glPushMatrix();
  glRotatef(rx,1.0F,0.0F,0.0F);
  glRotatef(ry,0.0F,1.0F,0.0F);
  scene();
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
}

/* Fonction executee lors de la frappe          */
/* d'une touche alphanumerique du clavier       */

void key(unsigned char key,int x,int y) {
  switch ( key ) {
    case 43   : disc++;
                glutPostRedisplay();
                break;
    case 45   : disc--;
                if ( disc < 2 )
                  disc = 2;
                glutPostRedisplay();
                break;
    case 'a'  : el = (el+1)%7;
                glutPostRedisplay();
                break;
    case 'm'  : mat =(mat+1)%3;
                switch ( mat ) {
                  case 0 : mb = &mBCR;
                           break;
                  case 1 : mb = &mBNRU;
                           break;
                  case 2 : mb = &mBB;
                           break;}
                glutPostRedisplay();
                break;
    case 0x20 : mode = (mode+1)%3;
                glutPostRedisplay();
                break;
    case 0x0D : solution = (solution+1)%2;
                glutPostRedisplay();
                break;
    case 0x1B : exit(0);
                break; }
}

/* Fonction executee lors d'un clic de souris   */
/* dans la fenetre                              */

void mouse(int bouton,int etat,int x,int y) {
  if ( bouton == GLUT_LEFT_BUTTON ) {
    if ( etat == GLUT_DOWN ) {
      clic = 1;
      mx = x;
      my = y; }
    if ( etat == GLUT_UP ) {
      clic = 0; } }
}

/* Fonction executee lors d'un deplacement      */
/* de la souris sur la fenetre                  */
/* avec un bouton appuye                        */

void motion(int x,int y) {
  if ( clic ) {
    ry += (x-mx);
    rx += (y-my);
    mx = x;
    my = y;
    glutPostRedisplay(); }
}

/* Fonction executee lors d'un changement       */
/* de la taille de la fenetre OpenGL            */

void reshape(int x,int y) {
  glViewport(0,0,x,y); 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(-8.0,8.0,(double) -8.0*y/x,(double) 8.0*y/x,-8.0,8.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
}

/* Fonction principale                          */

int main(int argc,char **argv) {
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
  glutInitWindowSize(300,300); 
  glutInitWindowPosition(50,50); 
  glutCreateWindow("Dessin de B-Splines"); 
  init();
  glutReshapeFunc(reshape);
  glutKeyboardFunc(key);
  glutMotionFunc(motion);
  glutMouseFunc(mouse);
  glutDisplayFunc(display);
  glutMainLoop();
  return(0);
}

RETOUR