Ce document résulte du projet réalisé début 2002 par Emmanuel DUCHAINE et Jorn VAN DER STAP, étudiants en DESS TSI-MA à l'IPST - ULP. Professeur : Patrick TRAU.

PROJET

INFORMATIQUE

UTILISATION DES LIBRAIRIES VGA.h,VGAGL.h,VGAMOUSE.h en C

Introduction :

Le but de ce projet est d'expliquer simplement l'utilisation des bibliothèques vga.h, vgagl.h et vgamouse.h, dans un programme en c (sous Linux). Nous avons donc décidé de réaliser un programme simple utilisant les fonctions graphiques principales des bibliothèques citées précédemment. Celui-ci permet de tracer une droite de la forme y=ax+b, d'une manière directe en donnant a et b, et par interpolation en donnant un nuage de points entré au clavier ou directement à l'écran, à la souris. Nous tâcherons d'expliquer dans un premier temps les fonctions utiles au programme et dans un second le programme dans son intégralité.

La bibliothèque vga.h :

Rien que cinq fonctions nous suffisent pour passer en mode vga et de tracer des droites dans ce mode :

La bibliothèque vgagl.h :

Nous nous sommes servis de 10 fonctions de cette bibliothèque, nous permettant de configurer la géométrie et le mouvement de la souris, la typographie et la couleur en mode vga :

La bibliothèque vgamouse.h :

Enfin nous avons utilisé 8 fonctions de la bibliothèque vgamouse.h afin de configurer la souris et d'obtenir une interactivité de celle-ci au niveau du mouvement et des boutons :

Programme exemple :

Voici le programme dans son intégralité, accompagné de notes explicatives en commentaire. Il faut compiler ce programme avec la ligne suivante :
gcc -o3 -o executable programme.c -lvgagl -lvga (toujours lvgagl avant lvga !)

De plus, l'executable doit être lancé sous "root" (le super utilisateur) pour avoir le droit d'accéder directement à l'écran (ou le déclarer SUID par chmod u+s).

 

#include <stdio.h>
#include <stdlib.h>
#include <vga.h>
#include <vgagl.h>
#include <vgamouse.h>
#include <math.h>
#include <unistd.h>

#define FONT_HEIGHT  8            /* taille des lettres en vga*/
#define FONT_WIDTH   8

char box[11 * 19 * 8];            /*rectangle pour la souris*/

void move_cursor(int x, int y, int ox, int oy);
void draw_cursor(int x, int y);

void prepare_font(int color ) /* http://www.svgalib.org/jay/font_tutorial/fonts.html */
         {
           void *font = malloc(256 * FONT_WIDTH * FONT_HEIGHT * BYTESPERPIXEL);
           gl_expandfont(FONT_WIDTH, FONT_HEIGHT, color, gl_font8x8, font);
           gl_setfont(FONT_WIDTH, FONT_HEIGHT, font);
         }

void cross(int x,int y)                       /*fonction de traçage de croix*/
    {
      vga_setcolor(4);
      vga_drawline(x-3, y, x+3, y);
      vga_drawline(x, y-3, x, y+3);
    }

void move_cursor(int x, int y, int ox, int oy)     /*fonction de déplacement de la souris*/
  {
   gl_putbox(ox, oy, 11, 19, box);
   gl_getbox(x, y, 11, 19, box);
   draw_cursor(x, y);
  }

void draw_cursor(int x, int y)                         /*fonction  de dessin de la souris*/
{
   gl_getbox(x, y, 11, 19, box);
   gl_setpixel(x, y, 254);                                                  /* line 1 */
   gl_hline(x, (y + 1), (x + 1), 254);                                      /* line 2 */
   gl_setpixel(x, (y + 2), 254);                                            /* line 3 */
   gl_setpixel((x + 1), (y + 2), 255);
   gl_setpixel((x + 2), (y + 2), 254);
   gl_setpixel(x, (y + 3), 254);                                            /* line 4 */
   gl_hline((x + 1), (y + 3), (x + 2), 255);
   gl_setpixel((x + 3), (y + 3), 254);
   gl_setpixel(x, (y + 4), 254);                                            /* line 5 */
   gl_hline((x + 1), (y + 4), (x + 3), 255);
   gl_setpixel((x + 4), (y + 4), 254);
   gl_setpixel(x, (y + 5), 254);                                            /* line 6 */
   gl_hline((x + 1), (y + 5), (x + 4), 255);
   gl_setpixel((x + 5), (y + 5), 254);
   gl_setpixel(x, (y + 6), 254);                                            /* line 7 */
   gl_hline((x + 1), (y + 6), (x + 5), 255);
   gl_setpixel((x + 6), (y + 6), 254);
   gl_setpixel(x, (y + 7), 254);                                            /* line 8 */
   gl_hline((x + 1), (y + 7), (x + 6), 255);
   gl_setpixel((x + 7), (y + 7), 254);
   gl_setpixel(x, (y + 8), 254);                                            /* line 9 */
   gl_hline((x + 1), (y + 8), (x + 7), 255);
   gl_setpixel((x + 8), (y + 8), 254);
   gl_setpixel(x, (y + 9), 254);                                            /* line 10 */
   gl_hline((x + 1), (y + 9), (x + 8), 255);
   gl_setpixel((x + 9), (y + 9), 254);
   gl_setpixel(x, (y + 10), 254);                                           /* line 11 */
   gl_hline((x + 1), (y + 10), (x + 5), 255);
   gl_hline((x + 6), (y + 10), (x + 10), 254);
   gl_setpixel(x, (y + 11), 254);                                           /* line 12 */
   gl_hline((x + 1), (y + 11), (x + 2), 255);
   gl_setpixel((x + 3), (y + 11), 254);
   gl_hline((x + 4), (y + 11), (x + 5), 255);
   gl_setpixel((x + 6), (y + 11), 254);
   gl_setpixel(x, (y + 12), 254);                                           /* line 13 */
   gl_setpixel((x + 1), (y + 12), 255);
   gl_setpixel((x + 2), (y + 12), 254);
   gl_setpixel((x + 4), (y + 12), 254);
   gl_hline((x + 5), (y + 12), (x + 6), 255);
   gl_setpixel((x + 7), (y + 12), 254);
   gl_hline(x, (y + 13), (x + 1), 254);                                     /* line 14 */
   gl_setpixel((x + 4), (y + 13), 254);
   gl_hline((x + 5), (y + 13), (x + 6), 255);
   gl_setpixel((x + 7), (y + 13), 254);
   gl_setpixel(x, (y + 14), 254);                                           /* line 15 */
   gl_setpixel((x + 5), (y + 14), 254);
   gl_hline((x + 6), (y + 14), (x + 7), 255);
   gl_setpixel((x + 8), (y + 14), 254);
   gl_setpixel((x + 5), (y + 15), 254);                                     /* line 16 */
   gl_hline((x + 6), (y + 15), (x + 7), 255);
   gl_setpixel((x + 8), (y + 15), 254);
   gl_setpixel((x + 6), (y + 16), 254);                                     /* line 17 */
   gl_hline((x + 7), (y + 16), (x + 8), 255);
   gl_setpixel((x + 9), (y + 16), 254);
   gl_setpixel((x + 6), (y + 17), 254);                                     /* line 18 */
   gl_hline((x + 7), (y + 17), (x + 8), 255);
   gl_setpixel((x + 9), (y + 17), 254);
   gl_hline((x + 7), (y + 18), (x + 8), 254);                               /* line 19 */
}
int main(void)
{
 long int Xmin,Xmax,Ymin,Ymax,nb_pxgrad,nb_pygrad,pos_YY,pos_XX,i,x,y,x1,y1,
   maxX,maxY,nbpX,nbpY,ord,r1,r2,key,mousetype,xx, yy, oxx, oyy,button,nb_point;
 float pente,ord_orig,N,M,U,V,W,Z;
 char text[] = "%d";
 char  nom_X[8] ;
 char  unit_X[8] ;
 char  nom_Y[8] ;
 char  unit_Y[8] ;
 int choix1,choix2;
 float points[100][2];

 nb_point=0;
 printf("\n\nnom de X\n ");
 scanf("%s",&nom_X);
 printf("unité de X\n ");
 scanf("%s",&unit_X);
 printf("entrez Xmin\n ");
 scanf("%d",&Xmin);                   /*demande du nom et des unité des axes*/
 do
  {printf("entrez Xmax\n");
   scanf("%d",&Xmax);
  }while (Xmax<Xmin);
 printf("nom de Y\n ");
 scanf("%s",&nom_Y);                          /*et des valeurs mini et maxi */
 printf("unité de Y\n ");
 scanf("%s",&unit_Y);
 printf("entrez Ymin\n");
 scanf("%d",&Ymin);
 do
  {
   printf("entrez Ymax\n");
   scanf("%d",&Ymax);
  }
 while (Ymax<Ymin);

 nbpX=1 ;
 maxX=abs(Xmax-Xmin);
 if ((Xmax-Xmin)>20)
   {
     while (maxX>20)
     {
      nbpX=nbpX*10;
      maxX=maxX/10;
     }
   }
                                   /*calcul de l'unité nbpX(ouY) 1 ou 10 ou 100 ....*/
 nbpY=1 ;                          /*calcul du nbre de graduations surX (maxX) et sur Y*/
 maxY=abs(Ymax-Ymin);
 if ((Ymax-Ymin)>20)
  {
    while (maxY>20)
     {
      nbpY=nbpY*10;
      maxY=maxY/10;
     }
  }

 nb_pxgrad=760/((abs(Xmax-Xmin))/nbpX);    /*nbre de pixels correspondant à une graduation*/
 nb_pygrad=740/((abs(Ymax-Ymin))/nbpY);

 if (Xmin<0)
  {
   ord=abs(Xmin)/nbpX ;
    if (Xmax<0)
      pos_YY=nb_pxgrad*abs(Xmax-Xmin)/nbpX;                                     /*position*/
    else
      pos_YY=nb_pxgrad*abs(Xmin)/nbpX;
  }
 else
  {                                                                            /*des*/
   pos_YY=0;  ord=-Xmin/nbpX;
  }

 r1=0; r2=0;
 if (Ymax>0)
  {
   if (Ymin<0)
     pos_XX=nb_pygrad*abs(Ymax)/nbpY;                                             /*axes*/
   else
     {
      pos_XX=nb_pygrad*abs(Ymax-Ymin)/nbpY;  r1=Ymin*nb_pygrad/nbpY;
     }
  }
 else
  {
    pos_XX=0;  r2=Ymax*nb_pygrad/nbpY;
  }
                          /* détermination du type de tracé par interpolation ou direct*/
 printf("\n choisir une interpolation(1) ou tracer une droite de type ax+b(2)\n");
 scanf("%d",&choix1);
 if (choix1==1)
   {
     do
      {
       printf(" entrez le nombre de points (>2):\n");
       scanf("%d",&nb_point);
      }
     while(nb_point<2);
     printf("entrer les points à la souris (1) ou au clavier (2):\n");
     scanf("%d",&choix2);
     if (choix2==2)
      {
      for (i=0;i<nb_point;i++)
       {
        printf("X%d: ",i+1);
        scanf("%f" ,&points[i][0]);
        printf("Y%d: ",i+1);
        scanf("%f",&points[i][1]);
       }
      choix2=2;
      }                                          /*mémorisation des choix effectués*/
     choix1=1;
   }
 else
   {
    printf("\n Tracé de A*X+B\n");
    printf(" entrez A\n");
    scanf("%f",&pente);
    printf(" entrez B\n");
    scanf("%f",&ord_orig);
   }
 getchar();

 vga_init();                                        /*initialisation de l'écran en vga */
 vga_setmode(12);
 gl_setcontextvga(12);
 mousetype=mouse_init("/dev/psaux",5,400);                                 /* de la souris*/
 mouse_setxrange( 0, 760);
 mouse_setyrange( 0,  766);
 vga_setmousesupport(mousetype);
 mouse_setscale(30);

 gl_setrgbpalette();                                               /*changement de couleur */
 gl_setpalettecolor(253, 223, 223, 223);                                    /* gris */
 gl_setpalettecolor(254, 0, 0, 0);                                          /* noir */
 gl_setpalettecolor(255, 255, 255, 255);                                    /* blanc */
 gl_setpalettecolor(2, 0, 63, 0);                                           /* vert */
 gl_setpalettecolor(3, 50, 50, 63);                                         /* bleu */
 gl_setpalettecolor(4, 63,0, 0);                                            /* rouge */
 gl_setpalettecolor(5, 50,50,40);
 gl_setpalettecolor(10, 63,63,0);
 gl_setpalettecolor(11, 63,20,20);

 prepare_font(10);                          /*écriture des unités sur le graph */
 if (Xmax>0) {
    gl_printf(780,pos_XX+2,nom_X);
    gl_printf(780,pos_XX+10,"(%s)",unit_X); }
 else {gl_printf(0,pos_XX+10,nom_X);
       gl_printf(0,pos_XX+20,"(%s)",unit_X);}
 if (Ymax>0){
    gl_printf(pos_YY+10,2,nom_Y);
    gl_printf(pos_YY+10,10,"(%s)",unit_Y);}
 else {gl_printf(pos_YY+10,757,nom_Y);
       gl_printf(pos_YY+10,767,"(%s)",unit_Y);  }

 vga_setcolor(2);
 vga_drawline(0, pos_XX, 760, pos_XX);                       /*traçage des axes*/
 vga_drawline(pos_YY, 0,pos_YY, 744);

 vga_setcolor(2);
 for (i=0;i<maxX+1;i++)
    {
       vga_drawline(nb_pxgrad*i,pos_XX-3,nb_pxgrad*i,pos_XX+3);
       prepare_font(2);
       gl_printf(nb_pxgrad*i+2,pos_XX+5, text,Xmin+nbpX*i);
    }
                                                                     /* des graduations */
 for (i=0;i<maxY+1;i++)
    {
        vga_drawline(pos_YY-3,nb_pygrad*i,pos_YY+3,nb_pygrad*i);
        prepare_font(2);
        if (nb_pygrad*i-8>0)
           gl_printf(pos_YY+5,nb_pygrad*i-8, text,Ymax-nbpY*i);
    }

 vga_setcolor(254);
 vga_drawline(1023,0,1023,767);
 vga_drawline(1022,0,1022,767);
 vga_drawline(1021,0,1021,767);
 vga_drawline(0,767,1023,767);
 vga_drawline(0,766,1023,766);
 vga_drawline(0,765,1023,765);

 prepare_font(5);
 gl_printf(890,20,"entrez vos\n%d points",nb_point);            /*petit texte pour l'utilisateur*/

 if (choix1==1 )               /* on veut une interpolation */
   {
    if (choix2==1 )            /* on voulait donner les points à la souris */
     {
      while (((key = vga_getkey()) != 27) && (key != 81)
              && (key != 113) && (nb_point!=0))
        {
         mouse_update();
         xx = mouse_getx();
         yy = mouse_gety();
         button = mouse_getbutton();

         if ((xx != oxx) || (yy != oyy))
          {
           move_cursor(xx, yy, oxx, oyy);
           oxx = xx;                                       /* boucle de mouvement de la souris */
           oyy = yy;
          }
         prepare_font(10);
         N=((xx)*nbpX*1.0)/nb_pxgrad+Xmin;
         M=((-(yy))*nbpY*1.0)/nb_pygrad+Ymax;
         gl_printf(890,50, "x= %f        ",N);
         gl_printf(890,60, "y= %f        ",M);
         usleep(5000);
         if (button!=0) if (button!=1)
          {
           cross(xx-1,yy-1);usleep(150000); button=0;
           points[nb_point-1][0]=N;
           points[nb_point-1][1]=M;              /*entrée des points à la souris dans un tableau*/
           nb_point=nb_point-1;
          }
         if (nb_point==0) gl_putbox(xx,yy, 11, 19, box);
        }
     }
    else                          /* on voulait entrer les pts au clavier */
     {
      for (i=0;i<nb_point;i++)
       {
        xx=pos_YY+(((int)(points[i][0]))*nb_pxgrad)/nbpX;
        yy=pos_XX+((-(int)(points[i][1]))*nb_pygrad)/nbpY;
        cross(xx,yy);
       }
     }
    U=0;
    for (i=0;i<nb_point;i++)  U=U+points[i][0];
    V=0;                                            /*calcul pour l'interpolation*/
    for (i=0;i<nb_point;i++)  V=V+points[i][1];
    W=0;
    for (i=0;i<nb_point;i++)  W=W+(points[i][0]*points[i][0]);
    Z=0;
    for (i=0;i<nb_point;i++)  Z=Z+(points[i][0]*points[i][1]);

    pente=(Z-(U*V)/nb_point)/(W-(U*U)/nb_point);      /* calcul des param de la droite */
    ord_orig=(V-U*pente)/(nb_point);
   }
 vga_setcolor(3);
 x=y=x1=y1=0;

 for (i=0;i<1023;i++)                                /* traçage de droite*/
  {
     y=((pos_XX+(nbpX*(pente*ord*nb_pygrad-pente*nb_pygrad*i/nb_pxgrad))/nbpY)
                                -((int)(ord_orig*nb_pygrad)/(nbpY)))+r1+r2;
     x=i;
     y1=((pos_XX+(nbpX*(pente*ord*nb_pygrad-pente*nb_pygrad*(i+1)/nb_pxgrad))/nbpY)
                    -((int)(ord_orig*nb_pygrad)/(nbpY)))+r1+r2;
     x1=i+1;
  }
     if (x>-1) if (y>-1) if (x<760) if (y<768)
     if (x1>-1) if (y1>-1) if (x1<760) if (y1<768)
     vga_drawline(x,y,x1,y1);}

     gl_getbox(xx, yy, 11, 19, box);

     prepare_font(5);
     gl_printf(890,20,"pour sortir\ncliquez bouton\ndroit"); /*petit texte affiché pour l'utilisateur*/
     prepare_font(11);
     gl_printf(890,100, "pente\n= %f        ",pente);
     gl_printf(890,130, "ordonnee a\nl'origine\n= %f        ",ord_orig);

     while (((key = vga_getkey()) != 27) && (key != 81)
             && (key != 113)&& (button!=1))
      {
       mouse_update();
                                                      /*réapparition de la souris */
       xx = mouse_getx();
       yy = mouse_gety();
       button = mouse_getbutton();
       if ((xx != oxx) || (yy != oyy))
        {
         move_cursor(xx, yy, oxx, oyy);
         oxx = xx;
         oyy = yy;
        }
       prepare_font(10);
       N=((xx)*nbpX*1.0)/nb_pxgrad+Xmin;
       M=((-(yy))*nbpY*1.0)/nb_pygrad+Ymax;
       gl_printf(890,50, "x= %f        ",N);
       gl_printf(890,60, "y= %f        ",M);
       usleep(5000);
      }
  }
 gl_clearscreen(0);
 vga_setmode(0);                                    /*fermeture de l'écran vga*/
 exit(0);
 return 0;
}