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.
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é.
Rien que cinq fonctions nous suffisent pour passer en mode vga et de tracer des droites dans ce mode :
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 :
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 :
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; }