précédent suivant haut Contents Index

ANNEXE : DOCUMENTATION DE LA BIBLIOTHEQUE GRAPHIQUE


G2D Librairie graphique de base en C

Préliminaire

Cette bibliothèque permet de dessiner sur tout écran graphique, et ce sur tout matériel, moyennant peu de modifications. Cette bibliothèque a été écrite de manière à être le plus facilement portable que possible. On peut utiliser au maximum le C standard (ANSI), les fonctions de base faisant des appels au BIOS (passer en mode graphique, allumer un point). Mais pour accélérer les affichages, on utilise les fonctions de l'unité GRAPH de Turbo C, les parties programmées de manière plus standard restant dans le source de la bibliothèque, en commentaires. Pour l'utilisateur, il n'y a pas d'autre différence que la rapidité, les fonctions disponibles dans les deux cas sont les mêmes.

Il faut avant tout définir, dans votre programme, l'ensemble des fonctions que vous allez utiliser. Ceci se fait par un fichier inclus, en C #include "G2D.H" (entre doubles quotes pour chercher le fichier dans le répertoire actuel). De plus, il faudra lier la bibliothèque à votre programme lors de l'édition de liens : LINK MONPROG.OBJ+G2D.OBJ MONPROG.EXE pour l'éditeur de liens MS-DOS. Sous TURBO-C il faut créer un projet (Project -> New Project) puis en y insérant tous les modules nécessaires (Project -> Add Item, insérer G2D.C, VOTREPROG.C, ainsi que les autres bibliothèques nécessaires).

Toutes les fonctions de cette bibliothèque commencent par la lettre G, afin de les identifier plus facilement.

Passage en mode graphique

Tout dessin doit débuter par un passage en mode graphique par la fonction void ginit(gtypecr type_écran). GINIT efface l'écran. Dans le cas d'un PC, type_écran peut valoir :

0 : mode texte. On est limité à 25 lignes de 80 caractères, sans graphique possible.

1 : CGA couleur (320x200 en 4 couleurs)
2 : CGA mono (640x200)
3 : écran Olivetti (640x400 mono)
4 : EGA (640x350 16 couleurs)
5 : MDA (320x200 256 couleurs)
6 : VGA (640x480 16 couleurs)
7 : SVGA 640x480 256 couleurs
8 : SVGA 800x600 16 couleurs
9 : Hercules 720x348 monochrome

GINIT crée la fenêtre 0 (réserve tout l'écran au graphique). 0n peut utiliser la fonction gtypecr gtyp_ecr_par_def(void) qui rend une valeur par défaut dépendant de votre matériel (en général 6 ou 2). De plus la valeur rendue par cette fonction peut être forcée sous MS DOS lors de l'appel de votre programme compilé par des options /CGA, /EGA, /VGA , /SVGA, /HER ou /OLI. Dans le cas d'une version utilisant les spécificités de TURBO C, il vous faudra fournir le fichier .BGI correspondant à votre écran soit dans le répertoire actuel, soit dans un répertoire défini par SET BGI=répertoire (par exemple, mettez dans AUTOEXEC.BAT la commande SET BGI=C:\TC\BGI).

On quitte le mode graphique et retourne en mode texte par la fonction void gfin(void). Il ne faut jamais ré-appeler GINIT sans être passé par GFIN (si ce n'était que pour effacer l'écran il vaut mieux utiliser gefface dans la fenêtre 0).

Les fenêtres

Une fois en mode graphique, on peut définir des fenêtres. Ceci n'est pas obligatoire, on sera sans cela dans la fenêtre 0 (totalité de l'écran). On crée une fenêtre par :

void gcree_fenetre(float xgauche, float xdroit, float ybas, float yhaut, int num_fen). On y définit les limites de la fenêtre par rapport à l'écran complet, par des valeurs entre 0 (à gauche en X et en bas en Y) et 1 (à droite en X, en bas en Y). Num_fen est le numéro que l'on désire attribuer à la fenêtre, il doit être un entier strictement positif, mais on n'est pas obligé de les faire se suivre. Une fenêtre est une partie de l'écran, pour laquelle on s'est défini une échelle, une couleur de tracés, une taille de caractères... Mais cette fenêtre n'est qu'une limite logique (on ne dépassera pas ses limites), sa création ne changeant rien à l'écran (on peut utiliser GEFFACE et GCADRE). On peut se faire superposer des fenêtres avec des échelles différentes, les tracés se superposeront. On appellera une telle fenêtre : "fenêtre écran", ou "fenêtre papier" sur table traçante.

Si l'on a défini plusieurs fenêtres, on passe de l'une à l'autre par void gchoix_fenetre(int num_fen). On dessine toujours dans la dernière fenêtre choisie. GCREE_FENETRE nous met directement dans la nouvelle fenêtre créée. Dans chaque fenêtre sont mémorisés : les échelles (2D et 3D le cas échéant), les couleurs, le type de trait et les informations sur les écritures (taille, direction, position).

On supprime une fenêtre par void gferme_fenetre(int num_fen). La fermeture d'une fenêtre ne change rien à l'écran, elle ne fait qu'oublier les définitions dans cette fenêtre. Il vaut mieux ne pas être dans la fenêtre à fermer, on se retrouvera dans ce cas dans la fenêtre 0.

Tout dessin sera limité aux limites de la fenêtre actuelle. Des algorithmes ont été mis en place pour accélérer le traitement des dépassements de la fenêtre (clipping / clôture). Vous pouvez donc sans soucis tracer l'ensemble de votre dessin, même si seule une partie entre dans la fenêtre, la perte de temps restera assez faible.

On efface la fenêtre actuelle par void gefface(void) (du moins on remplit la fenêtre par la couleur du fond). On encadre la fenêtre actuelle par void gcadre(void). Pour effacer la totalité de l'écran, utiliser GEFFACE après avoir choisi la fenêtre 0.

la fonction int gexiste_fenetre(int num_fen) permet de déterminer si une fenêtre est encore ouverte (1) ou non (0).

Les échelles

Vous travaillez toujours à votre échelle, avec des coordonnées de type gcoord (actuellement float). On appelle "fenêtre utilisateur" la partie de l'espace (dans votre système de coordonnées) que vous désirez représenter dans la "fenêtre écran". On définit l'échelle ("coordonnées utilisateur") par la fonction void gechelle(gcoord xgauche, gcoord xdroite, gcoord ybas, gcoord yhaut). Vous définissez la coordonnée en X que vous désirez donner au bord gauche de la fenêtre écran, puis le bord droit, puis vous définissez les bord haut et bas. Les valeurs n'ont pas besoin d'être croissantes en X ou en Y, ni de commencer à 0, ni d'être du même ordre de grandeur en X et Y (vous pouvez représenter en X des jours (entre 0 et 31), et des kilomètres de saucisse en Y (entre 0 et 0.1). Dans ce cas, la fonction GCERCLE vous dessinera une ellipse à l'écran.

Si vous désirez une unité représentée par la même distance en X et en Y, utilisez void gechelleort(gcoord xgauche, gcoord xdroite, gcoord ybas, gcoord yhaut). Quelles que soient les proportions de la fenêtre écran actuelle et de la fenêtre utilisateur désirée, cette fonction choisira une échelle représentant la fenêtre utilisateur la plus grande possible, à l'intérieur de la fenêtre écran, tout en gardant un repère orthonormé. Le clipping se fera sur la fenêtre écran, vous pourrez donc dessiner un partie hors de la fenêtre utilisateur : si la fenêtre écran est deux fois plus longue que haute, gechelleort(0, 100, 0, 100) permettra de dessiner de 0 à 100 en Y, mais de -50 à 150 en X. GCERCLE dessinera un véritable cercle. La fonction void glimites(gcoord *xgauche, gcoord *xdroite, gcoord *ybas, gcoord *yhaut) permet de récupérer les vraies limites de la fenêtre (dans votre échelle utilisateur).

Attributs de tracé

On peut définir, dans chaque fenêtre, une couleur de tracé par la fonction void gcouleur(int trait). Les tracés qui suivront se feront dans la couleur définie. La couleur peut être choisie entre 0 (couleur du fond, en général le noir) et la variable entière gcoul_max (qui dépend de votre type d'écran). Si trait est supérieur à gcoul_max, c'est gcoul_max qui sera choisi, ce qui signifie que si vous effectuez, sur un écran monochrome ou une imprimante, un dessin initialement prévu en couleur, tout ce qui était prévu dans une autre couleur que celle du fond (0) sera dessiné (couleur 1).

On peut également définir une couleur spécifique pour les remplissages par void gcouleur_remplissage(int rempli), ainsi que la couleur du fond par void gcouleur_fond(int fond). void gcouleur_tot(int trait, int rempli, int fond) permet de définir en une fois les trois couleurs (utilisé par la bibliothèque de remplissage).

Sur un écran couleur le permettant, vous pouvez redéfinir les couleurs de base, par la fonction void gpalette(int num_coul, float rouge, float vert, float bleu). Rouge, vert, bleu sont des réels entre 0 et 1 définissant l'intensité de chaque couleur de base (0 éteint, 1 intensité maximale). void gpalette_progressive(void) crée une palette de couleurs progressives de 1 à gcoul_max-1, du bleu au rouge, avec 0 (couleur du fond) en noir et gcoul_max en blanc (pour les tracés). On retourne à la palette par défaut du système par void gpalette_initiale(void) (sur PC, ne pas l'oublier avant le GFIN, sinon vos couleurs sous DOS peuvent être modifiées).

Certaines versions de G2D permettent de définir le type de trait par void gtypetrait(int typ) (0 trait continu, 1 interrompu, 2 mixte, la taille est définie par gtaillecar (voir documentation GECR). De même void geptrait(int ep) permet de définir l'épaisseur du trait. Le test de ces options ralentissant beaucoup le tracé, ils n'ont pas été implantés dans toutes les versions.

Tracés de base

Tous les tracés se font dans la couleur définie par le dernier GCOULEUR appelé dans cette fenêtre. On peut effacer un objet en le dessinant en couleur 0. Toutes les coordonnées seront de type gcoord (réel) dans votre système de coordonnées (coordonnées utilisateur), défini par le dernier GECHELLE appelé dans cette fenêtre.

La fonction void gpoint(gcoord x, gcoord y) allume le pixel le plus proche du point réel désiré, la fonction int gtestpoint(gcoord x, gcoord y) donne la couleur actuelle d'un point, la fonction void gcarpoint(gcoord x, gcoord y, int typ) trace en un point un signe (0=point, 1=X, 2=carré, 3=*, 4=losange, 5=+). Cette fonction est utile pour les tracés de courbes.La taille est définie par GTAILLECAR (voir documentation GECR).

La fonction void gligne(gcoord x1, gcoord y1, gcoord x2, gcoord y2) trace une ligne du point 1 au point 2, void gfleche(gcoord x0, gcoord y0, gcoord x1, gcoord y1) trace une flèche (signe flèche sur le point 2). void grectangle(gcoord xg, gcoord yb, gcoord xd, gcoord yh) trace un rectangle parallèle aux axes.

La fonction void garcellipse(gcoord xcentre, gcoord ycentre, gcoord rayonx, gcoord rayony,gcoord angledeb, gcoord anglefin) trace un arc d'ellipse défini par son centre, ses rayons en X et Y, l'angle de début et l'angle de fin (sens trigonométrique, en degrés). On peut également utiliser les fonctions void garc(float xcentre, float ycentre, float rayonx, float angledeb, float anglefin), void gcercle(float xcentre, float ycentre, float rayon) et void gellipse(float xcentre, float ycentre, float rayonx, float rayony).

Table traçante

On peut faire tous les tracés sur table traçante ou imprimante graphique, en même temps que l'on dessine sur l'écran. Tous les dessins se feront à la précision de la table traçante, même si celle-ci est différente de la définition de l'écran (en général elle est meilleure). Le tracé débutera à l'appel de void gdebut_table(gtypecr n, char *nomfic,float xgauche, float xdroite, float ybas, float yhaut). Typ représente le type de table (1 et 2 table Houston DMP 40 A4 et A3, 3 et 4 imprimante graphique matricielle type EPSON LX en mode paysage ou portrait, nécessitant beaucoup de mémoire, 5 et 6 EPSON LX utilisant peu de mémoire mais des accès disques nombreux, ce qui rend l'impression très lente), 7 et 8 table traçante HPGL (HP7470 par ex), en mode paysage ou portrait. Nomfic représente le nom du fichier ASCII comportant les commandes pour la table, qu'il faudra imprimer par la suite (sous MS DOS, on peut choisir PRN ou COM1 pour un envoi immédiat), mais il vaut mieux utiliser COPY /B NOMFIC PRN (copie en format binaire). Xgauche, Xdroite, Ybas, Yhaut sont des réels entre 0 et 1 qui définiront la portion de la feuille sur laquelle on "collera" la totalité de l'écran graphique (ceci permet de réduire le dessin, voire de le retourner). A partir de ce moment, il va falloir définir toutes les fenêtres et échelles, puis dessiner. Les effacements ne fonctionneront pas (sauf sur imprimante matricielle). Ce n'est qu'en appelant la fonction void gfin_table(void) que le fichier sera correctement fermé et que l'impression pourra débuter. On pourra ensuite soit continuer à dessiner sur l'écran, soit quitter le graphique par GFIN. Pour un résultat similaire sur l'écran et sur la table traçante choisissez un mode paysage.

Autres bibliothèques

Des fonctions supplémentaires ont été regroupées dans des bibliothèques différentes de G2D, afin de ne charger que celles utiles pour votre programme (voir détails plus bas) :
GECR : écritures graphiques
GPOLY : traçage, hachurage, remplissage de polygones
GREMPL : remplissage d'une surface déjà dessinée à l'écran
G3D : bibliothèque tridimensionnelle (ainsi que G3POLY et G3ECR)
SOURIS : prise en compte de la souris, directement dans votre échelle utilisateur
MENUG : menus graphiques
etc...

Exemple :

#include <conio.h>
#include <stdlib.h>
#include "g2d.h"
#define alea ((float)rand()/RAND_MAX)

void main(void)
{
 int i;

 ginit(gtyp_ecr_par_def());
 gefface();
 gcadre();
 gcree_fenetre(0,0.2,0.2,0.5,20);
 gcadre();
 gechelle(0,1,0,1);
 for (i=0;i<1000;i++)
  {
   gcouleur(rand()%16);
   gpoint(alea,alea);
  }
 gcree_fenetre(0.2,0.4,0.2,0.5,21);
 gcadre();
 gechelle(0,1,0,1);
 gcercle(0.5,0.5,0.5);
 gtaillecar(0.1,0.1);
 for (i=0;i<19;i++)
  {
   gcouleur(rand()%16);
   gcarpoint(alea,alea,rand()%6);
  }
 gcree_fenetre(0,0.2,0.5,0.8,22);
 gcadre();
 gechelle(0,1,0,1);
 for (i=0;i<100;i++)
  {
   gcouleur(rand()%16);
   gligne(alea,alea,alea,alea);
  }
 gcree_fenetre(0.2,0.4,0.5,0.8,24);
 gcadre();
 gechelle(0,1,0,1);
 for (i=0;i<20;i++)
  {
   gcouleur(rand()%16);
   grectangle(alea,alea,alea,alea);
  }
 gcree_fenetre(0.5,0.9,0.1,0.9,23);
 gcadre();
 gechelleort(0,1,0,1);
 g
taillecar(0.05,0.05);
 for (i=0;i<30;i++)
  {
   gcouleur(rand()%16);
   gfleche(alea,alea,alea,alea);
  }
 getch();
 gfin();
}

bibliothèque GECR

Cette bibliothèque, associée à G2D, permet d'afficher du texte en graphique. Son intérêt sur écran est moindre (on pouvait utiliser printf), bien que l'on puisse définir la position du texte de manière précise, à n'importe quelle taille et dans n'importe quelle direction. Mais les caractères obtenus sont moins beaux et moins lisibles que par printf. Mais par contre ils permettent d'écrire sur n'importe quel organe de sortie, à condition de savoir initialiser cet organe et y tracer une droite (table traçante, voire fraiseuse). Les caractères ne sont vraiment lisibles que pour une taille supérieure à 6 pixels. Certaines fonctions de traitement de chaînes de caractères, ainsi que le type chaine sont définis dans la petite bibliothèque CHAINES.

Avant tout, il faut déclarer dans votre programme les fonctions de la bibliothèque (#include "G2D.H" #include "GECR.H"). Il faut ensuite initialiser le graphique, définir vos fenêtres (avec leur échelle respective). Puis vous pouvez utiliser :

void gecrit(gcoord x, gcoord y, chaine gtexte) : écrit votre chaine de caractères en commençant en x,y,

void gecrite(gcoord x, gcoord y, int i) : idem pour un entier,.

void gecritr(gcoord x, gcoord y, float r) : idem pour un réel

void gtaillecar(gcoord x, gcoord y) : définit la taille des caractères, dans votre échelle, en X et Y. Si vous choisissez une échelle en Y de haut en bas (pour simuler des numéros de ligne d'écran tels qu'ils sont couramment définis), il faut donner une taille de caractères négative en Y pour ne pas écrire à l'envers.

void gdircar(float d) : pour donner la direction d'écriture, en degrés.

Si vous ne vous souvenez pas de votre échelle réelle (gechelleort ou g3d), vous pouvez utiliser void gtaillecarpc(float pcx, float pcy). pcx et pcy sont des réels entre 0 et 1, et définissent la taille des caractères en proportion de la taille de la fenêtre.

Remarque : gtaillecar et gtaillecarpc servant également à définir la taille des carpoint et gfleche, ils sont définis dans G2D.

Les fonctions gcoord gcurseurx(void) et gcoord gcurseury(void) rendent la position du "curseur", c'est à dire la position où il aurait écrit le prochain caractère. Ceci permet de mettre côte à côte des chaînes, entiers et réels.

Les écritures se SUPERPOSENT au dessin déjà présent à l'écran, pour effacer une ligne de texte avant d'en réécrire une autre, on peut : soit réécrire l'ancienne chaîne en couleur de fond, soit appeler void gecrit_blanc(gcoord x, gcoord y, int nbcar), définie dans la bibliothèque GPOLY, qui remplit en couleur de fond un rectangle en X,Y, de longueur nbcar caractères et de hauteur 1 caractère (prend en compte votre taillecar et dircar).

Cette bibliothèque est assez lente, et prend pas mal de place en mémoire. Elle est définie dans GECR_STD.C, qu'il faudra lier à votre projet (ou LINKer). En cas d'une utilisation exclusivement limitée à l'écran, la bibliothèque définie dans GECR_ECR.C permet, par appel aux fonction spécifiques du compilateur, une écriture plus rapide. Les fonctions ayant le même nom, il est inutile de changer l'inclusion de GECR.H dans votre source. Cependant les caractères seront dessinés à taille constante (8 pixels sous TurboC) et direction constante. Par contre, chaque caractère d'une chaîne sera dessiné à la même position qu'avec la bibliothèque standard (donc en fonction gtaillecar et gdircar). De plus cette version rapide ne sait pas écrire sur les tables traçantes (et imprimantes).

EXEMPLE GECR : il est intéressant de linker ce test avec GECR_STD en premier, puis avec GECR_ECR pour comparer.


#include <conio.h>
#include "g2d.h"
#include "gecr.h"

void main(void)
 {
  int i,j;
  ginit(gtyp_ecr_par_def());
  gefface();
  gcadre();

/*essai de différentes tailles*/
  gechelle(0,639,0,479);
  gdircar(0);
  gcouleur(1);
  j=2;
  gtaillecar(j,j);
  gecrit(0,475,"\n");
  for (i=1;i<=17;i++)
   {
    j+=2;
    gtaillecar(j,j);
    gecrit(10,gcurseury(),"taille ");
    gecrite(gcurseurx(),gcurseury(),j);
    gecrit(gcurseurx(),gcurseury(),"\n");
   }

/*essai de directions et rapport X/Y différent*/
  gechelle(0,1,0,1);
  gtaillecar(0.02,0.03);
  gcouleur(10);
  gecrit(0.1,0.5,"salut");
  gtaillecar(0.02,0.18);
  gcouleur(2);
  gecrit(0.7,0.13,"HAUT");
  gtaillecar(0.2,0.05);
  gcouleur(3);
  gecrit(0.05,0.05,"LARGE");
  gtaillecar(0.03,0.04);
  gdircar(15);
  gcouleur(4);
  gecrit(0.5,0.34,"ça monte !");
  gdircar(90);
  gcouleur(5);
  gecrit(0.9,0.15,"ça grimpe.");

/*fin de la démo*/
  getch();
  gfin();
 }

remplissage - hachurage de polygones (GPOLY)

la bibliothèque GPOLY permet de faire des remplissages ou hachurages indépendamment de ce qui se trouve déjà à l'écran. La frontière n'est pas dessinée lors d'un remplissage, c'est à vous d'appeler gpolygone pour la tracer si nécessaire. Le polygone à tracer est défini par ses N sommets, définis par deux tableaux de type gtableau_polygone (un pour chaque coordonnée). Ce sont des tableaux de réels limités à une taille de GMAXPOLY = 10 éléments. Par contre, vous pouvez redéfinir GMAXPOLY par un #define avant l'inclusion de GPOLY.H. Ceci vous permet de déclarer des variables de type gtableau_polygone à la dimension désirée. Mais il vous est aussi possible de déclarer directement des tableaux de gcoord (réels) et les transmettre en arguments aux fonctions de GPOLY. En effet, les fonctions ne font qu'utiliser votre tableau, sans en créer d'autre (ou alors par création par malloc).

void gpolygone(gtableau_polygone x, gtableau_polygone y, int nombre) : trace un polygone en reliant les points (x,y tableaux de reels, nombre : nombre de sommets du polygone). Cette fonction ne tracant que des segments de droites, les polygones peuvent être quelconques (mais fermés).

void gremplit_polygone(gtableau_polygone x, gtableau_polygone y, int nb) remplit le polygone dans la couleur de remplissage donnée (définie par la fonction gcouleur_remplissage de G2D). Dans la version standard (mais plus lente et encore plus gourmande en mémoire) GPOLY_STD, si votre écran est monochrome (variable gcoul_max de G2D valant 1), vous obtiendrez des niveaux de gris par répartition aléatoire de points. Cette fonction ne fonctionne bien que sur écran, utilisez le hachurage sur table traçante (avec interhachures de l'épaisseur du trait au minimum).

void ghachure_polygone(gtableau_polygone x, gtableau_polygone y, int nb, float angle,float interligne) : Cette fonction permet de hachurer un polygone, en donnant l'angle des hachures et la valeur de l'interligne La couleur des hachures est celle des remplissages (définie par gcouleur_remplissage).

Remarque : on trouve également dans cette unité la fonction gecritblanc(gcoord x, gcoord y, int nbcar), qui remplit un rectangle en couleur du fond, ce qui permet d'effacer un texte écrit par GECR (tient compte de la taille et direction d'écriture)

Exemple : (avec ghachure_polygone, on peut essayer gremplit_polygone)

#include <conio.h>
#include "g2d.h"
#include "gpoly.h"
#include "gecr.h"

void main(void)
 {
  gtableau_polygone x,y;
  int i;
  ginit(gtyp_ecr_par_def());
  gcree_fenetre(0,1,0.5,1,1);
  gcouleur(14);
  gcadre();
  gechelle(0,4,0,4);
  gecrit (0.1,0.1,"polygones convexe");
  x[0]=1;y[0]=1;
  x[1]=1;y[1]=2;
  x[2]=1.6;y[2]=3.8;
  x[3]=2.4;y[3]=3.8;
  x[4]=3;y[4]=2;
  x[5]=3;y[5]=1;
  for (i=0;i<=12;i++)
   {
    gcouleur_remplissage(i+1);
    ghachure_polygone(x,y,6,(3.14/15)*i,0.1);
   }
  gpolygone(x,y,6);

  gcree_fenetre(0,0.5,0,0.5,2);
  gcadre();
  gechelle(0,4,0,4);
  gecrit (0.1,0.1,"polygone NON convexe");
  x[0]=1;y[0]=1;
  x[1]=2;y[1]=3.5;
  x[2]=3;y[2]=1;
  x[3]=2;y[3]=2.5;
  for (i=0;i<=12 ;i++)
   {
    gcouleur_remplissage(i+1);
    ghachure_polygone(x,y,4,(3.14/15)*i,0.1);
   }
  gpolygone(x,y,4);

  gcree_fenetre(0.5,1,0,0.5,3);
  gcadre();
  gechelle(0,4,0,4);
  gecrit (0.1,0.1,"faux polygone");
  x[0]=1;y[0]=1;
  x[1]=2;y[1]=3;
  x[2]=3;y[2]=1;
  x[3]=1;y[3]=2.4;
  x[4]=3;y[4]=2.4;
  for (i=0;i<=12;i++)
   {
    gcouleur_remplissage(i+1);
    ghachure_polygone(x,y,5,(3.14/15)*i,0.1);
   }
  gpolygone(x,y,5);
  getch();
  gfin();
 }

remplissage suivant l'écran (GREMPL)

On peut également utiliser la bibliothèque GREMPL qui permet de remplir (d'une couleur de remplissage donnée) une frontière déjà dessinée à l'écran. Il suffit de donner un point de départ par ses coordonnées X et Y, la fonction void gremplir( gcoord x, gcoord y) remplira autour de ce point jusqu'à trouver des points déjà allumés. Il est évidement impossible de recouvir de cette manière des objets déjà dessinés. La frontière doit être dessinée auparavant, mais peut avoir n'importe quelle forme (voir plus bas l'exemple d'une spirale). Si la frontière n'est pas fermée, on remplira jusqu'aux limites de la fenêtre (même si le cadre n'a pas été tracé). Si le point de départ correspond à un point déjà allumé (par exemple sur une frontière), rien n'est rempli. En version spécifique Turbo, ne s'arrête que sur la couleur actuelle de tracé, en version standard s'arrête sur toute couleur différente du fond.

exemple :

#include <stdio.h>
#include <conio.h>
#include <math.h>

#include "g2d.h"
#include "gecr.h"
#include "grempl.h"

void figure1(void)
 {
  gligne(90,10,600,10);
  gligne(90,10,90,350);
  gligne(90,350,250,200);
  gligne(250,200,600,350);
  gligne(600,350,600,10);
 }

void figure3(void)
 {
  int a;
  for (a=1;a<=15;a++)
   {
    gcouleur(a);
    gligne(a*40,70,(a+1)*35,70);
   }
  grectangle(100,100,300,300);
  gcadre();
 }

void figure2(void)
 {
  int r, x1, y1, x2, y2,xlimite,ylimite;
  float o;
  xlimite=640;ylimite=480;
  o= 0;
  x1= xlimite / 2;
  y1= ylimite / 2;
  for (r=0;r<=200;r++)
     {
	 x2= (int)(sin(o)*r*(xlimite/640.0))+xlimite / 2;
	 y2= (int)(cos(o)*r*(ylimite/480.0))+ylimite / 2;
	 gligne(x1,y1,x2,y2);
	 o= o+PI/18.0;
	 x1= x2;
	 y1= y2;
     }
  gligne(x1, y1, x1, y1+ylimite/10);
 }

void figure4(void)
 {
  grectangle(40,40,600,440);
  gtaillecar(55,200);
  gecrit(60,100,"C'est Fini");
 }

void main(void)
 {
   ginit(gtyp_ecr_par_def());
   gcree_fenetre(0,0.5,0,0.5,1);
   gechelle(0,640,380,-20);
   gcadre();
   gcouleur(13);
   figure1();
   gcouleur_remplissage(3);
   gremplir(100,300);

   gcree_fenetre(0.5,1,0,0.5,2);
   gechelle(0,640,0,480);
   gcouleur(14);
   gcadre();
   figure2();
   gcouleur_remplissage(2);
   gremplir(300,300);

   gcree_fenetre(0,0.5,0.5,1,3);
   gechelle(0,640,0,480);
   figure3();
   gcouleur_remplissage(1);
   gremplir(400,300);

   gcree_fenetre(0.5,1,0.5,1,4);
   gcadre();
   gechelle(0,640,0,480);
   gcouleur(13);
   figure4();
   gcouleur_remplissage(4);
   gremplir(300,300);

   puts("c'est fini");
   getch();
   gfin();
}

bibliothèque GPLUS

Cette bibliothèque contient quelques petites fonctions qui peuvent être utiles :

void gix(gcoord x, gcoord y) dessine une petite croix (taille 4 pixels) autour du point X,Y en inversant la couleur des pixels, ce qui fait qu'un second appel remet l'écran tel qu'il se trouvait auparavant. Cette fonction est utilisée par MENUG pour représenter le curseur graphique lorsque la souris est absente.

void greticule(gcoord x, gcoord y) : idem GIX mais dessine une croix de la taille de la fenêtre. C'est évidement plus lent, mais plus visible.

void gcadre_ombre(int coul_fond) trace un fond de fenêtre avec effet de relief (comme les boutons windows)

bibliothèque tridimensionnelle

G3D

Cette bibliothèque, associée à G2D, permet de tracer des primitives tridimensionnelles, à votre échelle. Vous donnez tous vos points par leur 3 coordonnées. Cette bibliothèque vous fera vos projections, avec perspective. Mais cette bibliothèque n'est qu'une aide au tracé de traits, et ne sait pas en retrouver une définition de volume. Elle ne pourra donc pas éliminer des faces cachées, puisqu'elle ne connaît pas les faces. Toutes les fonctions de cette bibliothèque commencent par G3, afin de les identifier facilement.

Avant tout, il faut déclarer dans votre programme les fonctions de la bibliothèque (inclure entre autres G2D.H et G3D.H). Il faut ensuite initialiser le graphique, définir vos fenêtres, les couleurs... Toutes les fonctions 2D seront encore utilisables, la bibliothèque G3D ne faisant que des projections 3D-2D, puis utilise les fonctions de G2D pour tracer.

Dans une fenêtre que vous destinez au 3D, vous devez définir votre projection, c'est à dire la position de l'oeil O de l'observateur (ou sa caméra), ainsi que le point que vous visez V, par la fonction void g3origine(gcoord gxo, gcoord gyo, gcoord gzo, gcoord gxv, gcoord gyv, gcoord gzv, int propose_axe, int type_3d). Si propose_axe est faux (0), l'ordinateur cherchera à mettre l'axe Z vertical sur l'écran, sinon il posera la question. type_3d peut valoir G3PARAL, G3PERSP ou G34VUES, permettant une projection parallèle, en perspective ou en mode 4 vues (voir plus loin).

Puis vous pouvez définir votre "parallélépipède limite utilisateur" en donnant les minis-maxis que vous désirez faire entrer dans votre fenêtre, dans les 3 directions. Ceci définit votre échelle utilisateur. Pour cela appelez la fonction void g3echelle(gcoord xmin, gcoord ymin, gcoord zmin, gcoord xmax, gcoord ymax, gcoord zmax), mais toujours APRES avoir appelé G3ORIGINE. Si vous désirez changer d'origine pour une même échelle, il faudra appeler à nouveau g3echelle après votre g3origine, ou appeler void g3change_origine(gcoord gxo, gcoord gyo, gcoord gzo, gcoord gxv, gcoord gyv, gcoord gzv). qui recalcule l'échelle (comme dans l'exemple ci-après, même en éloignant l'oeil l'objet restera dessiné en pleine fenêtre).

On peut ensuite effectuer les tracés par les fonctions :

void g3point(gcoord xm, gcoord ym, gcoord zm) affichage d'un point,

void g3ligne(gcoord xm, gcoord ym, gcoord zm, gcoord xn, gcoord yn, gcoord zn) : tracé d'un segment,

void g3fleche(gcoord xm, gcoord ym, gcoord zm, gcoord xn, gcoord yn, gcoord zn) : tracé d'une flèche (dirigée de M vers N),

void g3cercle(gcoord xcentre, gcoord ycentre, gcoord zcentre, gcoord x1, gcoord y1, gcoord z1, gcoord x2, gcoord y2, gcoord z2) : cercle. on donne le centre et 2 points de passage (le 1er donne le rayon, le 2è définit uniquement le plan contenant le cercle). Il ne faut pas que ces 3 points soient allignés (infinité de solutions). Ce cercle sera représenté par une ellipse, sauf dans le cas de projections particulières.

void g3arc(gcoord xcentre, gcoord ycentre, gcoord zcentre, gcoord x1, gcoord y1, gcoord z1, gcoord x2, gcoord y2, gcoord z2, gcoord xpas, gcoord ypas, gcoord zpas) : on donne le centre, les 2 extrémités et un point de passage

On quitte le 3D soit en refermant la fenêtre, soit en y définissant une nouvelle échelle 2D, soit en quittant complètement le graphique par GFIN.

précisions sur le mode G34VUES

En définissant par g3origine une fenêtre de type G34VUES, il y a création automatique de 4 sous fenêtres de la fenêtre actuelle. Leur numéros seront définis automatiquementde numfen+ à numfen+4 (numfen étant le ndeg. de la fenêtre actuelle). Ces numéros de fenêtres ne doivent pas correspondre à des fenêtres déjà ouvertes, sous peîne d'erreur. La fenêtre est divisée en 4 parties égales, trois fenêtres en projection parallèle suivant les 3 axes, la quatrième étant une perspective définie par votre g3origine. En appelant une fonction de dessin G3D dans la fenêtre de base, on génèrera automatiquement un tracé dans les 4 sous fenêtres.. Par contre le dessin limité à une seule des sous fenêtres reste possible par un gchoix_fenêtre.

Pour fermer la fenêtre de base, il faut d'abord (en étant dans cette fenêtre) appeler void g3ferme_sous_fenetres(void) pour supprimer les 4 sous fenêtres puis faire un gferme_fenetre de la fenêtre de base. Pour changer l'origine, appeler g3change_origine qui contrairement à g3origine ne recréera pas de sous fenêtres.

Ce mode G34VUES n'est pas encore définitif, il devrait encore être amélioré.

G3ECR

On peut aussi écrire des textes, (avec la bibliothèque G3ECR, utilisant GECR), mais on ne donne en 3D que le point de départ, l'écriture se faisant toujours dans le plan de l'écran. Fonctions déclarées dans G3ECR.H : void g3ecrit(gcoord ggx, gcoord ggy, gcoord ggz, chaine gtexte), void g3ecrite(gcoord ggx, gcoord ggy, gcoord ggz, int ent), void g3ecritr(gcoord ggx,gcoord ggy,gcoord ggz,gcoord r). De plus on trouve dans cette bibliothèque la fonction void g3axes(gcoord xm, gcoord ym, gcoord zm) qui trace les 3 axes X,Y,Z. Il faut donner les longueurs des axes à cette fonction.

Pour utiliser ces fonctions il faut inclure GECR.H et G3ECR.H.

G3POLY

En incluant G3POLY.H, on peut accéder aux versions 3D de GPOLY. Les polygones doivent être plans (ou presque) :

void g3polygone(gtableau_polygone x, gtableau_polygone y, gtableau_polygone z, int nombre) : trace un polygone en reliant les points (x,y,z tableaux de reels),

void g3remplit_polygone(gtableau_polygone x, gtableau_polygone y, gtableau_polygone z, int nombre) : remplit le polygone dans la couleur de remplissage donnée, si l'écran est monochrome, met des niveaux de gris par répartition aléatoire de points.

void g3hachure_polygone(gtableau_polygone x, gtableau_polygone y, gtableau_polygone z, int nombre, float angle, float interligne) hachure le polygone.

void g3ecritblanc(gcoord x, gcoord y, gcoord z, int nbcar) efface un texte en remplissant un polygone, suivant dircar

Vecteurs

Cette bibliothèque, utilisée par G3D et donc de toute façon nécessaire à votre programme peut vous être utile. Elle contient la définition de la constante PI, et les fonctions suivantes :

float gscalaire(float x1, float y1, float z1, float x2, float y2, float z2) : rend le produit scalaire de deux vecteurs, float gnorme(float x, float y, float z) rend la norme du vecteur, void gnormer(float *x, float *y, float *z) modifie les coordonnées du vecteur pour le rendre de norme 1, mais toujours dans la même direction, void gvectoriel(float x1, float y1, float z1, float x2, float y2, float z2, float *x3, float *y3, float *z3) rend le produit vectoriel des deux premiers vecteurs, float gangle(float x1, float y1, float z1, float x2, float y2, float z2); retourne l'angle entre les 2 vecteurs (en les supposant sur le même point origine), entre 0 et pi.

OBJets à lier à votre EXEcutable

Pour utiliser G3D, il faut inclure à votre projet : G2D.C, G3D.C, VECTEURS.C. Il faudra également, en cas d'écritures, lier G3ECR.C et GECR (GECR_STD.C ou GECR_ECR.C). Pour utiliser les polygones, on devra lier GPOLY.C et G3POLY.C.

EXEMPLE G3D

#include <stdio.h>
#include <conio.h>
#include "g2d.h"
#include "g3d.h"
#include "g3ecr.h"

void cube(void)
 {
  gcouleur(14);
  g3ligne(0,0,0,0,1,0);
  g3ligne(0,1,0,0,1,1);
  g3ligne(0,1,1,0,0,1);
  g3ligne(0,0,1,0,0,0);
  gcouleur(13);
  g3ligne(1,0,0,1,1,0);
  g3ligne(1,1,0,1,1,1);
  g3ligne(1,1,1,1,0,1);
  g3ligne(1,0,1,1,0,0);
  gcouleur(12);
  g3ligne(0,0,0,1,0,0);
  g3ligne(0,1,0,1,1,0);
  g3ligne(0,1,1,1,1,1);
  g3ligne(0,0,1,1,0,1);
  gcouleur(11);
 }

void main(void)
 {
  float xo,yo,zo,xv,yv,zv;
  char c;
  float pas;
  ginit(gtyp_ecr_par_def());
  xo=10;yo=2;zo=1;
  xv=0;yv=0;zv=0;
  pas=0.5;
  puts("A,Z,E augmenter coord X,YouZ du pt visé, Q,S,D diminuer,
idem oeil en minuscule");
  puts("ESC: fin ");
  gcouleur(8);
  gcadre();
  gcree_fenetre(0,1,0,0.92,1);
  do
   {
    gotoxy(10,2);
    printf(" XO:%6.2f YO:%6.2f ZO:%6.2f XV:%6.2f YV:%6.2f
ZV:%6.2f",xo,yo,zo,xv,yv,zv);
    g3origine(xo,yo,zo,xv,yv,zv,0,G3PERSP);
    g3echelle(-0.1,1.1,-0.1,1.1,-0.1,1.1);
    gefface();
    gcouleur(8);
    gcadre();
    gcouleur(10);
    g3axes(1.1,1.1,1.1);
    gcouleur(9);
    g3ecrit(xo,yo,zo,".Oeil");
    gcouleur(15);
    g3ecrit(xv,yv,zv,".Visé");
    cube();
pas_la_peine_de_redessiner:
    c=getch();
    switch (c)
     {
      case 'a':xo=xo+pas;break;
      case 'q':xo=xo-pas;break;
      case 'z':yo=yo+pas;break;
      case 's':yo=yo-pas;break;
      case 'e':zo=zo+pas;break;
      case 'd':zo=zo-pas;break;
      case 'A':xv=xv+pas;break;
      case 'Q':xv=xv-pas;break;
      case 'Z':yv=yv+pas;break;
      case 'S':yv=yv-pas;break;
      case 'E':zv=zv+pas;break;
      case 'D':zv=zv-pas;break;
      case 27:break;
      default: goto pas_la_peine_de_redessiner;
     }
   }
  while (c!=27);
  gfin();
 }

SOURIS : utilisation de la souris sous G2D

Cette bibliothèque permet d'utiliser plus facilement une souris, en utilisant G2D en mode graphique ou texte (GINIT(0)). Toutes les fonctions de cette bibliothèque commencent par S. on trouvera des fonctions de bas niveau (pour gérer directement les informations de la souris) dans l'échelle de la souris, qui commenceront par SB.

types utilisés

Ce paragraphe décrit les types prédéclarés qui seront utilisés pour passer les arguments aux fonctions de la bibliothèque :

#define SNB_BOUTONS 3
typedef int st_boutons[SNB_BOUTONS]
	( dans l'ordre : bouton gauche,droite,centre)
/* définition des numéros de boutons */
#define SGAUCHE 0
#define SDROITE 1
#define SMILLIEU 2
Ces déclarations, ainsi que les fonctions décrites plus loin, seront connues de votre programme par la déclaration #define "SOURIS.H" et le lien avec SOURIS.C.

fonctions d'usage courant

Les coordonnées, si elles sont utilisées par la fonction, correspondent à vos coordonnées utilisateur, dans la fenêtre active (définie dans G2D, par Gcree_fenetre et Gechelle). On pourra assez facilement retrouver (ou recréer) ces fonctions sur tout matériel, utilisez les donc de préférence.

void sinit(int * nb_bts) : initialise la souris, retourne le nombre de boutons de la souris (0 si non installée (hard ou soft), 2 ou 3 en général). Le type de curseur est initialisé à un rectangle en mode texte, une flèche en mode graphique. Le curseur est caché, mais est positionné au milieu de l'écran.

void smontre_curs(void) : le curseur est affiché et suivra les déplacements de la souris. Il ne faut utiliser cette fonction que quand le curseur est caché.

void scache_curs(void) : cache le curseur. A utiliser par exemple pour sauver un écran graphique (sans le curseur de la souris), effacer l'écran, ou déplacer la souris par soft. Il ne faut utiliser cette fonction que quand le curseur est visible.

void sread(st_boutons b, gcoord *x, gcoord *y) : lit l'état de la souris : quels boutons sont appuyés et la position actuelle de la souris, dans l'échelle de la fenêtre graphique actuellement active, même si vous cliquez à l'extérieur de cette fenêtre (si vous n'avez pas empêché la souris de sortir de votre fenêtre). Cette fonction n'attend aucun appui de bouton, il faut pour celà utiliser un "do ... while (!b[i])" par exemple.

void sattend(st_boutons b, gcoord *x, gcoord *y) : idem SREAD mais attend que l'on appuie sur un des boutons de la souris, puis qu'on le relâche. Il rend l'état et les coordonnées mesurées lors de l'appui, mais ne retourne à la fonction appelante que lors du relâchement.

void sposit_curs(gcoord x, gcoord y) : positionne le curseur souris en x,y dans la fenêtre graphique active. On a intérêt à cacher le curseur avant, pour le remontrer après.

void sbornes(gcoord minx, gcoord maxx, gcoord miny, gcoord maxy) : limite (en X et Y) le déplacement de la souris. Il vaut mieux positionner auparavant le curseur de la souris à l'intérieur des bornes désirées. En général il vaut mieux associer une fenêtre G2D à la zonz limite et appeler :

void sbornes_fenetre(void) : limite la souris à votre fenêtre G2D actuelle.

Attention, pour ces deux dernières fonctions, le changement de fenêtre G2D ne change pas les bornes, il faut réappeler cette fonction.

forme du curseur

On peut modifier la forme du curseur (par défaut, un rectangle en inverse vidéo en mode texte, une flèche en mode graphique). Excepté SCROIX, ces fonctions utilisent des arguments trop proches du hard pour être facilement transportable sur un autre matériel. Ne les utilisez que si vous êtes sur de ne jamais avoir besoin de changer de matériel (ni Macintosh, ni station de travail Unix,...)

void scroix(void) : définit le curseur graphique sous forme d'une croix (au lieu de la flèche par défaut).

void scurs_graph(struct st_curseur *c) : fixe le type de curseur en graphique (voir la déclaration du type t_curseur dans SOURIS.C).

void scurs_text_ligne(int deb, int fin) : fixe le type de curseur en mode texte, sous forme d'une ligne dont on donne l'épaisseur par deb et fin (entre 0 et 7; 7,7 curseur MS DOS). Ce curseur sera déplacé par un gotoxy, contrairement au curseur graphique et au curseur texte/caractère. Il n'affecte PAS WhereX et WhereY (c'est à dire qu'un printf déplace le curseur, mais si on déplace le curseur par la souris, le prochain printf se fera quand même ligne suivante). Pour qu'un printf ne change pas la position du curseur, il faut cacher le curseur, faire le printf puis montrer le curseur, qui sera remis à l'endroit où il avait été caché. Attention, ces remarques ne sont vraies que pour le curseur text_ligne.

void scurs_text_char(int fond, int curs) : c'est le mode de curseur par défaut en mode texte. Cette fonction fixe le type de curseur en mode texte, en changeant les couleurs des caractères déjà sur l'écran. Ce curseur ne sera pas déplacé par un gotoxy et ne changera pas wherex/y. Le curseur texte/ligne reste derrière le dernier caractère écrit (ou gotoxy).

 FOND contient :
	1 bit si clignotant
	3 bits couleur de fond (0/7)
	4 bits couleur caractère (0/15)
	8 bits code ASCII du caractère
seuls points restant du caractère sous le curseur : ceux appartenant à ce caractère et au caractère du fond (AND). CURS contient la même chose, mais les points restants sont ceux qui n'appartiennent qu'a soit au reste de l'application du fond, soit au caractère du curseur (XOR).

exemple : $77FF,$7700 échangent la couleur du caractère (valeur à l'initialisation).

fonctions de bas niveau

Les coordonnées données par la souris sont, dans la plupart des modes graphiques d'un PC, dans les plages 0-639 et 0-199. Elles sont arrondies à l'inférieur si nécessaire : en 320/200 les X sont toujours pairs, en texte 80 col on n'a que des multiples de 8. Par contre en mode 640x480 les coordonnées souris sont les mêmes que les coordonnées écran. Toutes les fonctions dans cette échelle de base commencent par SB, les Y vont de haut en bas. Il est bien évident qu'il ne faut pas utiliser ces fonctions dépendant trop du matériel (y compris du driver de souris) sauf raison particulière.

void sbread(st_boutons b, gpixel *x, gpixel *y) : lit l'état des boutons et la position : x entre 0 et 639, y entre 0 et 199, 0,0 étant le coin supérieur gauche

void sbbornes(gpixel xmin, gpixel xmax, gpixel ymin, gpixel ymax) : impose les bornes de déplacement du curseur de la souris.

void sbposit_curs(gpixel x, gpixel y) : positionne le curseur en X,Y

exemple

#include "g2d.h"
#include "souris.h"
#include <stdio.h>
#include <conio.h>

void main(void)
 {
  st_boutons b;
  int a,i,nb;
  float x,y,m,n;

  ginit(gtyp_ecr_par_def());
  gechelle(0,1,0,1);
  sinit(&nb);
  sbornes_fenetre();
  scroix();
  gotoxy(2,2);printf("vous possedez %d boutons (mais pas sur la
figure)\n",nb);
  gotoxy(1,21); /* gotoxy n'est pas une fonction standard */
  puts(" bouton gauche : repositionner curseur");
  puts("        droit  : définir une fenêtre");
  puts(" fin par CTRL BREAK ou bouton milieu");
  smontre_curs();
  gcadre();
  gcree_fenetre(0,1,0,1,1);
  gechelle(-100,100,-100,100);
  do
   {
    sread(b,&x,&y);
    gotoxy(60,1);
    printf("x:%7.2f y:%7.2f\n",x,y);
    if (b[SGAUCHE])
     {
      clreol();
      printf("nouvelle position curseur (au clavier) : x? ");
      scanf("%f",&x);
      printf(" y? ");
      scanf("%f",&y);
      scache_curs();
      sposit_curs(x,y);
      smontre_curs();
     }
    else if (b[SDROITE])
     {
      clreol();
      gchoix_fenetre(0);
      sbornes_fenetre();
      printf("cliquez votre coin inf gauche ?");
      sattend(b,&x,&y);
      clreol();printf("coin sup droit ?");
      sattend(b,&m,&n);
      scache_curs();
      gcree_fenetre(x,m,y,n,1);
      gechelle(-100,100,-100,100);
      gcadre();
      sbornes_fenetre();
      smontre_curs();
     }
   }
  while (!b[SMILLIEU]);
  gfin();
 }

Bibliothèque MENUG

Descriptif général

Cet utilitaire regroupe des utilitaires permettant de gérer toute application graphique interactive en C (ou Pascal). Il décompose l'écran en deux fenêtres : l'une graphique, de forme carrée, utilisant la partie gauche de l'écran, la partie de droite étant réservée au texte. Cette bibliothèque utilise les fonctions de G2D, GECR,...

menuG

La fenêtre graphique utilise 71% de la largeur de l'écran, ce qui fait un carré sur un écran classique. La fenêtre de menus fait 23 lignes de 21 caractères, son "scrolling" est indépendant des autres fenêtres

Toutes les fonctions graphiques seront limitées à la fenêtre graphique. Tous les écritures se feront automatiquement dans la fenêtre texte, arrivé en 23è ligne seule la fenêtre texte sera remontée (scrollée) d'une ligne.

Une gestion de menus (demander à l'utilisateur un choix entre plusieurs options) est prévue. L'option peut être choisie :

- en donnant la 1ère lettre,
- en sélectionnant une option à l'aide des flèches puis RETURN,
- en sélectionnant la dernière option par ESCAPE,
- en pointant une option à l'aide de la souris.

Le bouton gauche de la souris correspondra à un RETURN, le droit à ESCAPE.

De plus la fonction read_coord permet de lire des coordonnées :
- en entrant la valeur X et Y au clavier,
- en déplaçant le curseur graphique, dans la fenêtre graphique, à l'aide des flèches, puis validation par RETURN, ESCAPE ou une touche de fonction (CTRL PGUP et PGDN permettent alors de modifier le pas de déplacement),
- en pointant le point dans la fenêtre graphique à l'aide de la souris.

la touche INS (ou bouton milieu de souris) permet d'afficher un réticule.

Description détaillée

Détails pratiques

Il est impératif d'inclure au sommet de votre fichier, #include "G2D.H" #include "MENUG.H" (plus les autres utilitaires si nécessaire). Mais il faudra lier G2D, MENUG, GECR, GPLUS

Pour initialiser le mode MENUG, appelez void minit(gtypecr typ, gcoord minx, gcoord maxx, gcoord miny, gcoord maxy), qui efface l'écran et prépare la fenêtre graphique ainsi que la fenêtre de texte. Les variables réelles minx, maxx, miny, maxy doivent correspondre aux limites des coordonnées du dessin que vous désirez afficher. Typ correspond au type d'écran désiré (par exemple gtyp_ecr_par_def(), voir G2D).

Les textes seront écrits dans la fenêtre texte par mprint. Les mgotoxy considèrent la colonne 0 comme étant la première de la fenêtre texte (21 colonnes utilisables). Pour changer l'échelle, il faut changer les bornes MINX, MAXX, MINY, MAXY et appeler mregen

Si l'on désire écrire à l'extérieur de la fenêtre texte, on peut utiliser GECRIT, ou alors on peut définir la fenêtre graphique comme une fenêtre texte par la fonction fen_text_gauche(). Ne pas oublier de revenir à une fenêtre texte normale à droite.

La fenêtre graphique de gauche, à votre échelle, porte le ndeg. 1 dans G2D. la fenêtre texte est la ndeg. 2, l'affichage des coordonnées la 3, la 4 étant limitée à la fenêtre gauche, mais à une échelle permettant un affichage 59 caractères sur 25 lignes. Par défaut, menug se place et reste dans la fenêtre 2.

On quittera le mode menus par mfin().

Menus

La fonction int menu(tmenu tab, int ent, int nb, int defaut) permet de gérer les menus. tab est du type prédéfini tmenu (tableau de 23 lignes de 21 caractères). Il contient les commentaires à afficher: lignes d'entête, options de choix. Ent est le nombre de lignes d'entête, Nb est le nombre d'options, Defaut est le ndeg. d'option proposée par défaut. La fonction rend le ndeg. de l'option choisie (entre 0 et NB-1)

Rq: on a toujours intérêt à mettre en dernier les options de type FIN, QUITTER, etc car la touche ESCAPE envoie toujours sur la dernière option.

Menu efface toujours l'écran texte lors de son appel, mais pas en sortie.

lectures (clavier ou souris)

void readst(char *nom) est une fonction permettant de lire une chaîne. Il ne pose pas de question (à vous de faire le mprint). Mais il accepte le CTRL C. De plus le RETURN peut être fait par un bouton de la souris. Un RETURN seul rend une chaîne vide (strlen(nom)=0).

void readi(int *i) lit un entier. Il repose la question si on entre autre chose. Il accepte le CRTL C et la souris. Un RETURN laisse I à la même valeur qu'à l'appel de la fonction. void readr(float *r) fait de même sur un réel.

La fonction void read_coord(gcoord *x, gcoord *y, int *fonc_fin, int nb_valeurs) permet de lire X et Y. La valeur X et Y à l'appel détermine la valeur par défaut, le curseur s'y place dans la fenêtre graphique. On peut valider directement cette position, ou déplacer le curseur par les flèches ou la souris, ou donner les 2 valeurs directement au clavier. L'appui sur INS (2 fois) ou bouton milieu souris affiche un réticule qui permet de vérifier un alignement avec d'autres points. CTRL PgUp et PgDn augmente ou baisse le pas de déplacement par les flèches. La position du curseur est constamment indiquée en bas à droite (lignes 24 et 25, sous les menus, dans la fenêtre ndeg. 3). La variable de sortie FIN indique comment la position a été validée:

FIN

= 1..10 si fin par touche F1..F10

= 1 si CR ou bouton gauche souris

= 2 si ESC ou bouton droit souris

=-1 si on a donné 2 valeurs au clavier
Dernier utilitaire proposé, la fonction ERR qui affiche le message "demande rejetée", et attend CR (ou bouton souris) pour continuer, CRTL C pour arrêter

référence

Constante prédéfinie

nbcolmenu=21 : nombre de caractères d'une ligne de menu

Variable globale prédéfinie

int nbligmenu: nombre de lignes de menu affichables (23 normalement)

Types prédéfinis

char tstring[255] : chaîne par defaut
char tstring21[nbcolmenu] : chaîne pour les menus, nbcolmenu=21 actuellement
tstring21 tmenu[nbligmenu] : tableau comportant les lignes de menu à gérer

Les fonctions avec des arguments de type tstring ou tstring21 peuvent être appelées en donnant n'importe quel char* ou char[]. De même, si un tmenu est demandé, tout tableau ou pointeur de tstring21 sera accepté.

Gestion du mode MENU

void minit(gtypecr typ, gcoord minx, gcoord maxx, gcoord miny, gcoord maxy) : initialisation mode MENU, passage en mode graphique, effacement de l'écran et tracé des cadres. Ne pas réappeler cette fonction avant d'avoir fait un mfin(). On se trouve par défaut dans la fenêtre ndeg. 2, curseur de souris caché.

void mregen(gcoord minx, gcoord maxx, gcoord miny, gcoord maxy) : réinitialisation du mode MENU / effacer fenêtre / sur écran multifenêtre (station Unix) relecture des limites de fenêtre et recalcul des échelles.

void mfin(void) : fin du mode menu et du mode graphique.

Fonctions principales

int menu(tmenu tab, int ent, int nb, int defaut) : retourne le numéro d'option choisie. On donne le schéma d'affichage tab, le nombre de lignes d'entête ENT, le nombre d'options possibles NB, l'option par défaut DEFAUT. La fonction efface la fenêtre menu au début et en sortie. On valide par CR, on choisit par les flèches Haut, Bas, Home,End ou la première lettre. Si une souris est présente, on teste la souris ET les touches.

void read_coord(gcoord *x, gcoord *y, int *fonc_fin, int nb_valeurs) : affiche et déplace un réticule en X,Y par les flèches, fin par CR (fonc_fin=1) ou ESC (2). Si on tape une valeur, elle est prise en compte, fonc_fin=-1. Si nb_valeurs=1 : la valeur est dans X, nb=2 : dans X et Y. CTRL PgUp et PgDn augmentent ou baissent le pas de déplacement. INS affiche un réticule plein écran, jusqu'au prochain ins. Marche également avec la souris (bouton gauche=CR, droit=ESC, milieu=INS).

void affcoord(gcoord x, gcoord y, int fen_de_depart) : affiche la coordonnée dans la fenêtre de coord (ndeg. 3) puis retourne dans la fenêtre fen_de_depart. Cette fonction est appelée par read_coord, vous n'avez donc pas besoin de vous en servir

Ecritures dans la fenêtre menu

void mgotoxy(int x, int y) :uniquement dans la fenêtre menu, déplace le curseur (l'endroit où débutera la prochaine écriture). x entre 0 et nbcolmenu-1, y entre 0 (en haut) et nbligmenu-1.

void mscroll(void) : scroller la fenêtre menu de quelques lignes vers le haut. Les fonctions d'écriture appelant si nécessaire cette fonction, vous n'avez normalement pas besoin d'utiliser cette fonction.

void mprintc(char c) : affiche UN caractère dans la fenêtre menu, en position actuelle du curseur. Si l'on se trouve en fin de ligne, passe à la ligne suivante, si l'on se trouve en dernière ligne "scrolle" les textes vers le haut.

void mprint(tstring21 s) : écrit la chaîne de caractères la fenêtre menu, le curseur reste derrière le dernier caractère écrit.

void mprintln(tstring21 s) : écrit la chaîne de caractères la fenêtre menu, le curseur passe au début de la ligne suivante.

void mclrscr(void) : efface uniquement le texte (fenêtre menu)

Lectures (clavier ou souris)

void readst(char * nom) : lecture clavier d'une chaîne de caractères, rend nom initial par défaut, c'est à dire en cas d'appui de CR ou bouton gauche de la souris.

void readr(float *r) : lecture d'un réel avec test d'erreur, valeur initiale par défaut

void readi(int *i) : lecture d'un entier avec test erreur.

Les deux fonctions suivantes, utilisées par ces fonctions de lecture, peuvent également vous servir :

void err(tstring21 mess) : affiche le message d'erreur puis attend un appui de touche ou de bouton de souris.

void err_read(void) : demande si continuer ou abandonner

Ecrire dans la fenetre de gauche (58 caractères, 25 lignes)

void fen_gauche(void) : passer à la fenêtre gauche, mais à l'échelle 1..58, 1..25 (fenêtre ndeg. 4 G2D)

void efface_fen_gauche(void) : passer à la fenêtre gauche et l'effacer

void fen_droite(void) : revient à la fenêtre de menu (obligatoire avant tout appel de fonction pour le menu). ce n'est qu'un gchoix_fenêtre(2), il peut aussi être utilisé après un dessin dans la fenêtre gauche.

void mggotoxy(int x, int y), void mgprint(tstring21 txt) et void mgprintln(tstring21 txt) permettent les écritures dans la fenêtre de gauche, à condition d'avoir fait auparavant un fen_gauche().

Exemple MENUG

#include <stdio.h>
#include <conio.h>
#include <string.h>

#include "g2d.h"
#include "menug.h"

void main(void)
 {
  tstring21 m[]={"entête ligne 1",
                 "",
                 "faites votre choix",
                 "",
                 "Ecrire à droite",
                 "Ecrire à gauche",
                 "Dessin",
                 "Fin du programme"};
  int i,j;
  tstring s;
  float x0,y0,x1,y1;

  for (i=1;i<100;i++) printf("écran encore normal  ");
  printf("\n\nappuyez une touche pour continuer");
  getch();
  minit(4,0,10,0,10);
/* si l'on n'avait pas initialisé m, on aurait pu le charger ainsi
:
  strcpy(m[0],"entête ligne 1");
  *m[1]=0;
  strcpy(m[2],"faites votre choix");
  *m[3]=0;
  strcpy(m[4],"Ecrire à droite");
  strcpy(m[5],"Ecrire à gauche");
  strcpy(m[6],"Dessin");
  strcpy(m[7],"Fin du programme");
*/
  do
   {
    j=menu(m,4,4,2);  /* position 2= le 3ème */
    switch (j)
     {
      case 0: mclrscr();
              for (i=1;i<30;i++)
               {
                mprint("txt droite ");
                sprintf(s,"%d",i);
                mprintln(s);
               }
              break;
      case 1: efface_fen_gauche();
              for (i=1;i<100;i++) mgprint("texte à gauche
");
              fen_droite();
              break;
      case 2: mclrscr();
              mprintln("choisissez un point");
              read_coord(&x1,&y1,&i,2);
              mprintln("choisissez d'autres");
              mprintln("points jusqu'à finir");
              mprintln("par ESC ou bouton ");
              mprintln("droit de la souris");
              do
               {
                x0=x1;y0=y1;
                read_coord(&x1,&y1,&i,2);
                gchoix_fenetre(1);
                gligne(x0,y0,x1,y1);
                gchoix_fenetre(2);
               }
              while (i!=2);
              break;
     }
   }
  while (j!=3);
  mfin();
 }


précédent suivant haut Contents Index