2d Chapitre 2 - Géométrie de base
CHAPITRE 2 - Géométrie de base
Ce cours porte sur des notions fondamentales: les figures géométriques de base. Tout particulièrement, il traite des lignes et des cercles. Il existe plusieurs algorithmes différents pour résoudre ces deux problèmes. Je vais présenter un des plus populaire et efficace qui soit: L'algorithme du mathématicien Bresenham. À la fin de ce cours, nous aurons ajouter à notre librairie de fonctions graphiques la capacité de dessiner plusieurs primitives tels les lignes diagonales, les droites horizontales et verticales, les cercles, les rectangles et les polygones convexes.
LES DROITES HORIZONTALES ET VERTICALES
Commençons tout d’abord par les cas les plus simple, c’est à dire les lignes horizontales et verticales. Définissons (x1,y1) comme le point de départ, et (x2,y2) comme le point d’arrivé. Comme nous avons vu au chapitre 1, la fonction memset permet de spécifier la valeur que prendra une certaine quantité de mémoire, et ce à partir d’un point donné. Dans notre cas, le point de départ sera le premier pixel de la ligne. Pour calculer sa position, on applique la formule (y*320)+x. La ligne horizontale est très simple à dessiner : comme la mémoire est linéaire, il suffit tout simplement de mettre autant de pixels que son intervalle (x2-x1) :
void hline(int x1, int x2, int y, unsigned char coul)
{
memset(ecran+x1+(y*320),coul,(x2-x1));
}
La version verticale requiert un peu plus de calculs. Nous devons augmenter notre offset de 320 à chaque itérations pour descendre verticalement. C’est donc nécessairement un peu plus lent que la version horizontale :
void vline(int x, int y1, int y2, unsigned char coul)
{
unsigned int offset = (y*320)+x
for(int i=y1;i<y2;i++)
{
ecran[offset] = coul;
offset += 320;
}
}
MÉTHODE MATHÉMATIQUE DE RÉGRESSION LINÉAIRE
La formule de régression linéaire la plus connue est sans aucun doute y=mx+b. Cette fonction permet de dessiner une droite en trouvant les points se situant sur la pente formée entre un point d’origine et un point d’arrivé. Les deltas se calculent avec la formule x2-x1 / y2-y1. Cette formule n’est cependant pas utilisé en programmation graphique :
void LineYMXB(int x1, int y1, int x2, int y2, char coul)
{
int dx,dy;
int x,y;
float m;
if(x1>x2)
{
x=x1; x1=x2; x2=x;
}
dx=x2-x1;
dy=y2-y1;
if(!dx) return;
m=(float)dy/dx;
for(x=0; x<dx; x++)
{
y=m*x + y1;
ecran[y*320+x+x1]=coul;
}
}
ALGORITHME DE BRESENHAM
Pour comprendre l'algorithme de Bresenham, il faut comprendre qu'une division n'est en fait qu'une série de soustractions. Si on soustrait un nombre d'un autre, tant que le résultat est plus grand que le nombre que nous soustrayons, nous avons divisé le premier nombre par le deuxième. Le nombre de divisions requises est le quotient de la division, et le résultat restant est le reste de la division. Par exemple, on peut soustraire 2 de 11 cinq fois, avec un reste de 1 - qui est plus petit que 2. Donc 11/2 est 5, avec un reste de 1. De la même façon, si on additionne a répétition un nombre à lui même jusqu'à ce qu'il soit plus grand qu'un second, le nombre d'addition est le quotient du premier nombre divisé par le second, plus 1. Si on soustrait le second nombre du premier, on obtient le reste. Par exemple, 11/2 -> 2+2+2+2+2+2=12 donc plus grand. 6 = quotient (5) + 1. Résultat de l'addition 12-premier nombre (11)= 1, soit le reste de la division.
Ce procédé de division répétitive est le coeur de cet algorithme. Premièrement on calcul le changement des coordonnés x et y sur la droite (bref, on soustrait x2-x1 et y2-y1, et on garde la valeur absolue). On appelle ces variables xdiff et ydiff. Si la pente est moins que 1 -bref si xdiff est plus grand que ydiff- on augmente la coordonnée X de 1 après chaque pixel. Pour déterminer quand on va augmenter la coordonnée Y, on crée un variable nommée déviation, qui est initialisée a 0. Elle nous dit de combien notre ligne de pixel dévie d'une droite géométrique. Après avoir dessiné un pixel, on additionne ydiff à déviation et on vérifie si cette nouvelle valeur excède xdiff. Si non, on laisse la coordonnée ainsi. Si oui, notre coordonnée a dévié d'au moins 1 pixel. Donc, on incrémente la coordonnée Y et on soustrait xdiff de déviation.
Exemple:
xdiff est 42.
ydiff est 20
La pente de notre droite serait donc 20/42, soit 10/21. Nous aurions besoin d'incrementer la coordonnée Y 10 fois pour chaque fois que nous incrémentons la coordonnée X 21 fois. La déviation nous aide a effectuer cela. En ajoutant ydiff a la déviation initiale nous donne 20. On compare cela a xdiff pour voir si elle est supérieure, on constate que non, donc nous n'incrémentons pas Y. La prochaine itération nous ajoutons ydiff a la déviation, le résultat est 40, qui est encore inférieur à xdiff(42), donc on ne touche toujours pas à la coordonnée Y. Mais la troisième fois, la déviation est de 60, donc nous incrémentons la coordonné Y. Ce qui signifie que les trois premier pixels sont dessinés à la même coordonnée Y, mais le quatrième avance de 1:
123
***4
*
Nous soustrayons ensuite xdiff de la déviation, qui nous la ramène a 18. Puisque la déviation est plus grande, nous pourrons seulement incrementer X 2 fois avant que Y ne soit incrementé à nouveau:
123
***45
**6
*
... ainsi de suite pour les 19 autres pixels.
Si ydiff est plus grand que xdiff, on procède tout simplement par l'inverse: on augmente Y de 1 pixel en ajoutant xdiff à déviation, jusqu'à ce que la ligne soit dessiné au complet. Assez de théorie mathématique! Maintenant, voici le code C pour réaliser cette algorithme:
void line(int x1, int y1, int x2, int y2, unsigned char coul)
{
int x_chan, x_chan; // Pour le changement dans x et y
int offset = (y1*320)+x1 // Calcule l'offset dans la RAM
int ydiff = y2-y1; // Calcule la différence entre y2 et y1
int deviation = 0; // Initialise la déviation a 0;
if (ydiff < 0) // Si la ligne va dans un direction Y-
{
xdiff = -ydiff;
y_chang = 320;
}
int xdiff = x2-x1; // Calcule la différence entre x2 et x1
if (xdiff < 0) // Si la ligne va dans un direction X-
{
ydiff = -xdiff;
x_chang = 320;
}
else x_chan = 1;
if (xdiff > ydiff) // si la différence est + grande
{ // sur l'axe X
int longueur = xdiff+1;
for(int i = 0; i < longueur; i++)
{
ecran[offset] = coul;
offset+=x_chan;
deviation+=ydiff;
if (deviation>xdiff) // Est-ce le temps de changer Y?
{
deviation-=xdiff;
offset+=y_chan;
}
}
else // Différence + grande sur Y
{
int longueur = ydiff+1;
for(int i = 0; i < longueur; i++)
{
ecran[offset] = coul;
offset+=y_chan;
deviation+=xdiff;
if (deviation>0) // Est-ce le temps de changer X?
{
deviation-=ydiff;
offset+=x_chan;
}
}
}
}
LES LIGNES SINUSOÏDALES
Avant de dessiner des cercles, voyons ensemble comment dessiner une ligne courbe. Naturellement, la fonction mathématique SIN nous est très utile dans ce cas. Une ligne sinusoïdales comporte 2 paramètres : la hauteur et la fréquence. La hauteur représente la hauteur de la ligne et la fréquence représente la proximité des courbes. Donc, pour déterminer où mettre notre pixel sur l'écran, on se sert de la fréquence multiplier par la hauteur.
SIN (fréquence) * hauteur
En se servant de cette fonction, l'origine serait (0,0). Pour descendre notre ligne sur l'axe des ordonnées, nous devons ajouter à notre formule y. En mettant dans un tableau les résultat de ces calculs, nous coupons le temps de calcul subséquent sur cette même ligne courbe. Donc, voici le code nécessaire:
void sinline(int y, int hauteur, float freq, unsigned char coul)
{
float courbe = 0;
int point;
for (int i=0; i<319; i++)
{
point = ((sin(courbe)*hauteur)+y);
courbe += freq;
ecran[(point*320) + i] = coul;
}
}
CERCLES
De la même façon, la fonction cosinus nous permettrais de dessiner des lignes courbes verticales. En combinant les deux, on obtient la base de l’effet de plasma en temps-réel. Une fois ceci dit, dessiner un cercle n'est pas beaucoup plus compliqué. L’équation du cercle est :
Rayon * sin (theta) + OrigineX
Rayon * cos (theta) + OrigineY
Un ligne sinusoïdale est une des composantes d'un cercle, donc il n'est pas surprenant que la formule pour dessiner un cercle soit presque identique à celle d'une ligne sinusoïdale. Encore une fois, cette formule est très mathématiquement correcte :
void circle(int x, int y, int hauteur, float freq, unsigned char coul)
{
float courbe = 0;
int i = 0;
int point1;
int point2;
for (i=0; i<319; i++)
{
point1 = (sin(courbe)*hauteur);
point2 = (cos(courbe)*hauteur);
courbe += freq;
ecran[((point1+y)*320)+point2+x] = coul;
}
}
Cependant, encore une fois Bresenham nous offre une solution plus rapide et efficace pour dessiner un cercle. Je n’expliquerai pas en détails cet algorithme, comme ce tuteur commence à être beaucoup trop long. Cependant, cet algorithme est le plus rapide pour dessiner un cercle donc c’est lui que nous utiliserons :
void cercle(int cx, int cy, int r, char coul)
{
int x,y;
for(x=-r; x<r; x++)
{
y=sqrt(r*r - x*x);
ecran[(cy+y)*320+x+cx]=coul;
ecran[(cy-y)*320+x+cx]=coul;
}
}
On peut ajouter également quelques primitives très simples, les rectangles vides et les rectangles pleins. Il s’agit simplement de combiner les fonctions de lignes horizontales et verticales. Pour dessiner un rectangle plein, nous devons tout simplement remplir les pixels situés entre (x1,y1) et (x2,y2) :
void rectangle(int x1, int y1, int x2, int y2, unsigned char coul)
{
for(short x=x1;i<x2;i++)
for(short y=y1;j<y2;j++)
ecran[(y*320)+x]=coul;
}
Dans le cas d’une simple bordure rectangulaire, nous utiliserons les fonctions de droite horizontales et verticales pour dessiner les lignes formant la boîte :
void boite(int x1, int y1, int x2, int y2, unsigned char coul)
{
vline(x1,y1,y2,coul);
hline(x1,x2,y1,coul);
vline(x2,y1,y2,coul);
hline(x1,x2,y2,coul);
}
POLYGONES REMPLIS
Dans le cas de polygones pleins, il faut procéder autrement. On utilise le « polygon scan conversion ». Cette technique consiste à découper un polygone quelconque en une série de lignes horizontales. En effet, si on connaît les extrémités gauche et droite de chaque lignes d'un polygone, on est en mesure de le dessiner à partir d'une série de lignes horizontales. Regardez le schéma suivant:
Pour se faire, il va falloir procéder par régression linéaire. Calculer la pente d'un des côté du polygone, suivre cette pente pour chaque Y du polygone, vérifier si coordonnée courante est plus petite que MinX ou plus grand que MaxY, et mettre à jour notre structure de scanline. Voici, étape par étape, ce processus.
1. Nous avons besoins d'une structure comme celle-ci pour contenir les informations sur nos extrémités gauche et droite du polygone. Il faudra prévoir autant de lignes que la résolution verticale le permet:
// Structure pour le remplissage de polygones
typedef struct TScan
{
long gauche;
long droite;
};
Tscan Scanline[200];
2. On trouve tout d'abord la hauteur du polygone, c'est à dire son Ymax - Ymin. Cela nous donne le nombre de lignes que nous devrons parcourir ultérieurement.
3. Initialisation de la structure TScan avec des valeurs limites, afin de s'assurer que les résultats soient les bons.
4. On parcours tous les côtés du polygones, selon le nombre de côté qu’il possède.
5. On détermine la pente, et tout en s'assurant que l'on se dirige dans la bonne direction, on tiens à jour la variable Tscan.
Nous avons besoin en tout premier lieu d’une fonction de régression linéaire qui va remplir graduellement notre structure Tscan avec les données qu’elle retourne. Cette fonction s’assure tout d’abord que nous allons dans le bon sens, et inverse les coordonnées y1 et y2 au besoin. Ensuite, on calcule la pente, qui sera notre incrémenteur dans la boucle principale (un double car sinon la valeur pourrait être trop petite et on se retrouverais alors dans une boucle infinie). La variable Xinc représente la pente, et de combien on doit incrémenter x pour progresser sur la ligne. Les variables miny et maxy jouent un peu le même rôle que les scanlines horizontales, mais leurs utilités est de savoir le haut et le bas du polygone. On doit sauter par dessus le premier x, et ensuite nous comparons la valeur du x avec nos valeurs limites, et on mets à jour notre structure Scanline.
void scan(float x1, float y1, float x2, float y2)
{
if (y1==y2) return; // Check pour la div/0
if (y2<y1) {Swap (y1,y2); Swap (x1,x2);} // Dans le bon sens...
double Xinc = (x2-x1) / (y2-y1); // Regression lineaire
double x = x1 += Xinc; // pente m = (dx/dy)
// on saute par dessus le premier pixel
if(y1<miny) miny=y1; // on mets a jour le haut et le bas
if(y2>maxy) maxy=y2; // du polyhone
for (int y=y1;y<y2;y++) // On scan la ligne de haut en bas
{
if (x < scanline[y].gauche) scanline[y].gauche = x;
if (x > scanline[y].droite) scanline[y].droite = x;
x+=Xinc;
}
}
La fonction qui dessinera le polygone devra connaître le nombre d’arêtes qu’il possède, ainsi que les coordonnées 2D de ces arrêtes. Pour stocker les informations sur un polygone on peut imaginer une structure qui ressemblerais à ceci :
typedef struct _2D // Pour contenir les informations sur un
{ // sommet d'un polygone
int x,y;
};
La fonction dessinepoly utilisera également miny et maxy, variables globales au programme, pour déterminer l’étendu du polygone sur l’axe Y. On utilise une liste chaînées des sommets du polygone que l’on parcours avec la fonction scan :
void dessinepoly(_2D *listesommet, int nbcotes, unsigned char coul)
{
// On declare deux pointeurs sur des sommets. Ils seront utilises
// pour progresser dans la liste des sommets (ptr courant et suivant)
_2D *ptrcour, *ptrsuiv;
// Initialisation de la liste chainee
ptrcour = listesommet;
ptrsuiv = listesommet+1;
// Reinisialisation des valeurs extremes
miny=200; maxy=0; // Étendu Y du polygone
for (int i=0;i<200;i++)
{
scanline[i].gauche = 32000;
scanline[i].droite = -32000;
}
// On parcours la liste des polygones et on trouve les extremites
for (i = 1; i < nbcotes; i++)
{
scan(ptrcour->x, ptrcour->y, ptrsuiv->x, ptrsuiv->y);
ptrcour++;
ptrsuiv++;
}
// Il ne faut pas oublier de fermer le polygone
ptrsuiv = listesommet;
scan(ptrcour->x, ptrcour->y, ptrsuiv->x, ptrsuiv->y);
// on parcours le tableau de scanline et on dessine nos lignes horizontales
for (int y=miny;y<maxy;y++)
hline (scanline[y].gauche,scanline[y].droite,y,coul);
}
À la fin de la boucle principale, nous aurons rempli la structure scanline, qui contient, pour chaque Y contenu entre miny et maxy, l’extrémité gauche et droite de cette ligne. Il suffit tout simplement de faire une boucle entre miny et maxy, et d’y dessiner sur chacune une ligne horizontale entre scanline.gauche et scanline.droite.
Vous avez maintenant une bonne ébauche pour mettre sur pied une petite librairie graphique. Dans le code source, vous trouverez toute la matière de ce cours. J’ai décidé d’inclure dans le code source les fonctions de lignes et de cercles de Bresenham, mais libre à vous d’utiliser les autres contenues dans ce chapitre. En résumé, nous avons vu :
- Les algorithmes de droites horizontales et verticales
- La ligne et le cercle de Bresenham
- Les rectangles (remplis et vides)
- La conversion de polygones convexes (scanline algorihtm)
- Le remplissage de polygone
2dchap2.cpp
//----------------------------------------------------------------------//
// FICHIER : 2DCHAP2.CPP //
// AUTEUR : Shaun Dore //
// DESCRIPTION : Figures geometriques de base //
// DATE DE MODIFICATION : 25-10-97 //
// COMPILATEUR : Borland Turbo C++ Real Mode 16-bit compiler //
// NOTES : Compiler avec modele memoire Compact //
//----------------------------------------------------------------------//
//----------------------------------------------------------------------//
// Fichiers include //
//----------------------------------------------------------------------//
#include <mem.h>
#include <math.h>
#include <time.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
//----------------------------------------------------------------------//
// Types personalises //
//----------------------------------------------------------------------//
typedef struct _2D // Pour contenir les informations sur un
{ // sommet d'un polygone
int x,y;
};
typedef struct TScan // Structure pour le remplissage de polygones
{
long gauche,droite;
};
//----------------------------------------------------------------------//
// Variables globales //
//----------------------------------------------------------------------//
int miny,maxy; // Hauteur des polygones
TScan scanline[200]; // Largeur des lignes des polys
char *ecran = (char *) (0xA0000000L); // Pointeur sur RAM video
//----------------------------------------------------------------------//
// setmode - Appelle le mode passer en parametre //
//----------------------------------------------------------------------//
void setmode(unsigned int mode)
{
asm {
MOV AX, [mode]
INT 0x10
}
}
//----------------------------------------------------------------------//
// cls - vide l'ecran //
//----------------------------------------------------------------------//
void cls()
{
memset(ecran,0,64000L);
}
//----------------------------------------------------------------------//
// putpixel - Affiche un pixel directement dans la memoire //
//----------------------------------------------------------------------//
void putpixel (int x, int y, unsigned char coul)
{
ecran[(y*320)+x] = coul;
}
//----------------------------------------------------------------------//
// hline - Dessine une ligne horizontale //
//----------------------------------------------------------------------//
void hline(int x1, int x2, int y, unsigned char coul)
{
memset(ecran+x1+(y*320),coul,(x2-x1));
}
//----------------------------------------------------------------------//
// Line - Dessine une ligne selon l'algorithme de Bresenham //
//----------------------------------------------------------------------//
void line(int x1, int y1, int x2, int y2, unsigned char coul)
{
int x_chan, y_chan; // Pour le changement dans x et y
int offset = (y1<<8)+(y1<<6) + x1; // Calcule l'offset dans la RAM
int ydiff = y2-y1; // Calcule la difference entre y2 et y1
int deviation = 0; // Initialise la deviation a 0;
if (ydiff < 0) // Si la ligne va dans un direction -
{
ydiff = -ydiff;
y_chan = -320;
}
else y_chan = 320;
int xdiff = x2-x1; // Calcule la difference entre x2 et x1
if (xdiff < 0) // Si la ligne va dans un direction +
{
xdiff = -xdiff;
x_chan = -1;
}
else x_chan = 1;
if (xdiff > ydiff) // si la difference est + grande
{ // sur l'axe X
int longueur = xdiff+1;
for(int i = 0; i < longueur; i++)
{
ecran[offset] = coul;
offset+=x_chan;
deviation+=ydiff;
if (deviation>xdiff) // Est-ce le temps de changer Y?
{
deviation-=xdiff;
offset+=y_chan;
}
}
}
else // Difference + grande sur Y
{
int longueur = ydiff+1;
for(int i = 0; i < longueur; i++)
{
ecran[offset] = coul;
offset+=y_chan;
deviation+=xdiff;
if (deviation>0) // Est-ce le temps de changer X?
{
deviation-=ydiff;
offset+=x_chan;
}
}
}
}
//----------------------------------------------------------------------//
// sinline - Affiche des lignes sinuosidales //
//----------------------------------------------------------------------//
void sinline(int y, int hauteur, float freq, unsigned char coul)
{
float courbe = 0;
int point;
for (int i=0; i<319; i++)
{
point = ((sin(courbe)*hauteur)+y);
courbe += freq;
ecran[(point*320)+i]=coul;
}
}
//----------------------------------------------------------------------//
// circle() - Dessine un cercle avec l'algorithme de Bresenham //
//----------------------------------------------------------------------//
void circle(int cx, int cy, int r, unsigned char coul)
{
int x,y;
for(x=-r; x<r; x++)
{
y=sqrt(r*r - x*x);
ecran[(cy+y)*320+x+cx]=coul;
ecran[(cy-y)*320+x+cx]=coul;
}
}
//----------------------------------------------------------------------//
// Swap - Effectue l'echange entre 2 variables float //
//----------------------------------------------------------------------//
void Swap(float &x,float &y)
{
float temp = x;
x = y;
y = temp;
}
//----------------------------------------------------------------------//
// Scan - Trouve le minX et maxX d'un cote d'un polygone //
//----------------------------------------------------------------------//
void scan(float x1, float y1, float x2, float y2)
{
if (y1==y2) return; // Check pour la div/0
if (y2<y1) {Swap (y1,y2); Swap (x1,x2);} // Dans le bon sens...
double Xinc = (x2-x1) / (y2-y1); // Regression lineaire
double x = x1 += Xinc; // pente m = (dx/dy)
// on saute par dessus le premier
if(y1<miny) miny=y1; // pixel
if(y2>maxy) maxy=y2;
for (int y=y1;y<y2;y++) // On scan la ligne de haut en bas
{
if (x < scanline[y].gauche) scanline[y].gauche = x;
if (x > scanline[y].droite) scanline[y].droite = x;
x+=Xinc;
}
}
//----------------------------------------------------------------------//
// dessinepoly - Dessine un polygone avec liste de points(listesommet) //
//----------------------------------------------------------------------//
void dessinepoly(_2D *listesommet, int nbcotes, unsigned char coul)
{
// On declare deux pointeurs sur des sommets. Ils seront utilises
// pour progresser dans la liste des sommets.
_2D *ptrcour, *ptrsuiv;
// Initialisation de la liste chainee
ptrcour = listesommet;
ptrsuiv = listesommet+1;
// Reinisialisation des valeurs extremes
miny=200; maxy=0;
for (int i=0;i<200;i++)
{
scanline[i].gauche = 32000;
scanline[i].droite = -32000;
}
// On parcours la liste des polygones et on trouve les extremites
for (i = 1; i < nbcotes; i++)
{
scan(ptrcour->x, ptrcour->y, ptrsuiv->x, ptrsuiv->y);
ptrcour++;
ptrsuiv++;
}
// Il ne faut pas oublier de fermer le polygone
ptrsuiv = listesommet;
scan(ptrcour->x, ptrcour->y, ptrsuiv->x, ptrsuiv->y);
// on parcours le tableau de scanline et on dessine nos lignes horizontales
for (int y=miny;y<maxy;y++)
hline (scanline[y].gauche,scanline[y].droite,y,coul);
}
//----------------------------------------------------------------------//
// testlignes() - Affiche des lignes de longueurs et couleurs aleatoires//
//----------------------------------------------------------------------//
void testligne()
{
int x1,y1,x2,y2;
unsigned char coul;
printf("TEST DE L'ALGORITHME DE LIGNE BRESENHAM");
do
{
x1 = random(320);
x2 = random(320);
y1 = random(190)+10;
y2 = random(190)+10;
coul = random(256);
line(x1,y1,x2,y2,coul);
} while (!kbhit());
}
//----------------------------------------------------------------------//
// testsinus() - Affiche des lignes sinus de hauteur differentes //
//----------------------------------------------------------------------//
void testsinus()
{
short wave = 1;
short hauteur = 30;
cls();
gotoxy(8,1);printf("TEST DE LIGNES SINUOSIDALES");
do
{
for (unsigned int ralenti=0;ralenti<65500;ralenti++) {}
line(0,100,319,100,190);
sinline(100,hauteur,0.03,0);
if (hauteur == 60) wave =- 1;
if (hauteur == -60) wave =+ 1;
hauteur += wave;
sinline(100,hauteur,0.03,50);
} while (!kbhit());
}
//----------------------------------------------------------------------//
// testcercle() - Affiche des cercles de rayons differents //
//----------------------------------------------------------------------//
void testcercle()
{
int x,y,rayon;
unsigned char coul;
cls();
gotoxy(1,1);printf("TEST DE L'ALGORITHME DE CERCLE BRESENHAM");
do
{
x = random(320);
y = random(100)+60;
rayon = random(40);
coul = random(256);
circle(x,y,rayon,coul);
} while(!kbhit());
}
//----------------------------------------------------------------------//
// testpoly() - Dessine des polygones convexes (triangle et rectangle) //
//----------------------------------------------------------------------//
void testpoly()
{
unsigned char coul;
unsigned long tri, tempdeb, tempfin;
cls();
gotoxy(4,1);printf("TEST DE L'ALGORITHME DE POLYGONES");
_2D triangle[3];
_2D rectangle[4];
// Definition d'un triangle
triangle[0].x = 20; triangle[0].y = 20;
triangle[1].x = 100; triangle[1].y = 70;
triangle[2].x = 20; triangle[2].y = 70;
// Definition d'un rectangle
rectangle[0].x = 180; rectangle[0].y = 40;
rectangle[1].x = 300; rectangle[1].y = 50;
rectangle[2].x = 180; rectangle[2].y = 170;
rectangle[3].x = 120; rectangle[3].y = 180;
do
{
dessinepoly(triangle,3,40); // Dessine un triangle
dessinepoly(rectangle,4,50); // Dessine un rectangle
} while(!kbhit());
//-------- TEST DE VITESSE ---------//
getch(); cls();
tri=0; tempdeb = clock(); // clock() retourne le temps de debut
do
{
for (int s=0;s<3;s++)
{
triangle[s].x = random(320);
triangle[s].y = random(200);
coul = random(256);
dessinepoly(triangle,3,coul);
tri++; // incremente le compteur de triangle
}
} while(!kbhit());
tempfin = clock(); // clock() pour le temps de fin
setmode(0x03);
printf("Triangles par seconde: %.2f\n", (tri / ((tempfin - tempdeb) / CLK_TCK)));
printf("\nShaun Dore\ndores@videotron.ca\n http://pages.infinit.net/shaun/ ");
}
//----------------------------------------------------------------------//
// Fonction MAIN //
//----------------------------------------------------------------------//
void main()
{
randomize();
setmode(0x13);
testligne(); getch();
testsinus(); getch();
testcercle(); getch();
testpoly();
}