Tracer des lignes [djgpp]

Soyez le premier à donner votre avis sur cette source.

Vue 24 338 fois - Téléchargée 429 fois

Description

voila une fonction que j'ai créer pour tracer des lignes. A l'origine elle est faite pour un kit pour faire des jeux videos en VGA 13h que je suis en train de faire, mais j'ai deja mis la fonction ici. Elle peut etre utilisee pour n'importe quelle mode graphique (ou meme texte) car elle utilise une reference de fonction.

Source / Exemple :


#include <stdio.h>		/* pour printf et getch */
#include <conio.h>		/* pour gotoxy */

/*
   Pour une meilleure comprehension voici la formule,
   le code en est tres different car il utilise plein
   d'astuces pour avoir moins de calcul a faire, mais 
   en gros c'est ça :

   soit deux point A(a,b) et B(c,d)

   m=(d-b)/(c-a);

   tout point M(x,y) appartenant a [AB]
   verifie donc l'equation :

   y=mx-ma+b  
   x=(ma-b+y)/m

  • /
/* firstx => position X du premier point de la ligne firsty => position Y du premier point de la ligne lastx => position X du dernier point de la ligne lasty => position Y du dernier point de la ligne void (&func)(int,int) => reference de la fonction a appeler
  • /
void glbDrawLine(int firstx,int firsty,int lastx,int lasty,void (&func)(int,int)) { int x1; /* debut de la ligne => milieu de la ligne */ int y1; /* debut de la ligne => milieu de la ligne */ int x2; /* fin de la ligne => milieu de la ligne */ int y2; /* fin de la ligne => milieu de la ligne */ int dx; /* longueur X de la droite */ int dy; /* longueur Y de la droite */ int sub; /* utilise pour des soustractions */ int remain; /* nombre de pixel restant */ int error; /* erreur du trace, doit etre corrige si positif */ int inc1; /* pour des incrementations/decrementations */ int inc2; /* pour des incrementations/decrementations */ /* x1 = premier point X x2 = dernier point X y1 = premier point Y y2 = dernier point Y si firstx > lastx les premiers et les derniers sont inverses
  • /
if (firstx>lastx) { x1=lastx; x2=firstx; y1=lasty; y2=firsty; } else { x1=firstx; x2=lastx; y1=firsty; y2=lasty; } dx=x2-x1; /* longueur X de la droite */ dy=y2-y1; /* longueur Y de la droite */ if ((!dx)&&(!dy)) return; /* quitte si aucun trace a effectuer */ /* si dy negatif, inverse dy et initialise les incrementation selon le signe de dy (afin que les droites aillent dans le bon sens
  • /
if (dy<0) { dy=-dy; inc1=-1; inc2=1; } else { inc1=1; inc2=1; } /* pour augmenter la rapidite du code vous pouvez rajoutez ici des algos pour les droites horizontales (dy==0), verticales (dx==0) et diagonale (dx==dy) car ces droites ne necessitent pas d'algorythme complique, mais la taille du code en souffrira
  • /
/* pour aller plus vite on dessine la droite des deux cotes a la fois, en meme temps a partir du premier point et du dernier
  • /
/* si la droite est plutot horizontale */ if (dx>dy) { sub=dx-dy; error=dy-(dx>>1); remain=(dx+1)>>1; /* dx+1 est le nombre de points a tracer, diviser par deux car on dessine des deux cotes a la fois
  • /
/* pour mieux comprendre sachez que la position x doit augmenter de 1 a chaque tour et y de dy/dx a chaque tour (car sur la longueur dx y doit en tout augmenter de dy).
  • /
do { func(x1,y1); /* appelle la fonction de dessin avec en parametre */ func(x2,y2); /* les positions des points a dessiner */ x1+=inc2; /* la position x1 augmente */ x2-=inc2; /* et la position x2 diminue (on va vers le centre) */ if (error>=0) /* si l'erreur est assez grande pour etre corrigee */ { y1+=inc1; /* la position y1 augmente */ y2-=inc1; /* et la position y2 diminue (on va vers le centre) */ error-=sub; /* diminue l'erreur */ } else error+=dy; /* sinon augmente l'erreur */ } while (--remain>0); /* diminue remain et recommence s'il reste des points a tracer */ if (!(dx&1)) func(x1,y1); /* si dx etait pair l'algo n'a pas pu tracer le point du milieu car il a fait une division entiere par deux sur dx pour connaitre le nombre de points a tracer et a ainsi perdu le 1
  • /
return; /* fin de la fonction */ } else { sub=dy-dx; error=dx-(dy>>1); remain=(dy+1)>>1; /* dy+1 est le nombre de points a tracer, diviser par deux car on dessine des deux cotes a la fois
  • /
/* pour mieux comprendre sachez que la position y doit augmenter de 1 a chaque tour et x de dx/dy a chaque tour (car sur la longueur dy x doit en tout augmenter de dx).
  • /
do { func(x1,y1); /* appelle la fonction de dessin avec en parametre */ func(x2,y2); /* les positions des points a dessiner */ y1+=inc2; /* la position y1 augmente */ y2-=inc2; /* et la position y2 diminue (on va vers le centre) */ if (error>=0) /* si l'erreur est assez grande pour etre corrigee */ { x1+=inc2; /* la position x1 augmente */ x2-=inc2; /* et la position x2 diminue (on va vers le centre) */ error-=sub; /* diminue l'erreur */ } else error+=dx; /* sinon augmente l'erreur */ } while (--remain>0); /* diminue remain et recommence s'il reste des points a tracer */ if (!(dy&1)) func(x1,y1); /* si dy etait pair l'algo n'a pas pu tracer le point du milieu car il a fait une division entiere par deux sur dy pour connaitre le nombre de points a tracer et a ainsi perdu le 1
  • /
return; /* fin de la fonction */ } } /* Fonction qui dessine le caractere 0xDB (un carre) a la position xy. Vous pouvez creer n'importe quelle autre fonction pour afficher vos points, aussi bien en mode texte qu'en mode graphique, mais la fonction ne doit rien renvoyer et accepter deux parametres de type int pour les positions du point.
  • /
void putcara(int x,int y) { gotoxy(x,y); printf("\xDB"); } /* Et enfin la fonction principale qui trace une ligne...
  • /
int main() { glbDrawLine(1,1,79,25,putcara); /* dessine une ligne de 1-1 a 79-25 avec la fonction putcara(int x,int y) */ getch(); /* attend une pression de touche */ return 0; /* fini ! */ }

Conclusion :


Voila. Pour informations, c'est l'algorythme de Bresenham (ou Bresenhau ?).
Pour mieux comprendre le code, allez faire un tour sur http://www.vije.net/~opecheux/abcp, dans la section divers il y a un article tres complet et bien fait pour tracer des lignes et qui m'a beaucoup aide.
J'ai mis niveau 2 parce que le code est complique, mais bon sinon c'est que du math il ne faut pas beaucoup de connaissances en C++. Désolé je n'ai pas commenté la source.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

cs_sim38
Messages postés
9
Date d'inscription
samedi 4 novembre 2006
Statut
Membre
Dernière intervention
20 novembre 2008
-
Je n'arrive pas à lancer le code... la fonction gotoxy n'est pas dans le fichier conio.h... comment dois-je faire ? est-il possible de changer la résolution de la ligne ?
merci
cs_sim38
Messages postés
9
Date d'inscription
samedi 4 novembre 2006
Statut
Membre
Dernière intervention
20 novembre 2008
-
Je n'arrive pas à lancer le code... la fonction gotoxy n'est pas dans le fichier conio.h... comment dois-je faire ? est-il possible de changer la résolution de la ligne ?
merci
cs_fisherman
Messages postés
1
Date d'inscription
mardi 25 mai 2004
Statut
Membre
Dernière intervention
27 mai 2004
-
Super ton code
Y a juste un petit bug dans la partie pour tracer les lignes plutot verticales
A la place de :
y1+=inc2;
y2-=inc2;
Il faut écrire :
y1+=inc1;
y2-=inc1;

Petite inatention sans doute sinon c'est OK.
cs_gorgonzola
Messages postés
37
Date d'inscription
samedi 16 mars 2002
Statut
Membre
Dernière intervention
21 février 2015
-
voila j'ai un peu plus commente

ah oui pour ceux qui ne le sauraient pas >>1 est egal a /2 et <<1 a *2 mais c'est plus rapide
> >>x /(2^x) et <<x = *(2^x)
cs_GoldenEye
Messages postés
527
Date d'inscription
vendredi 14 septembre 2001
Statut
Membre
Dernière intervention
6 octobre 2008
2 -
1/ commente un peu plus. La personne qui ne connait pas Bresenham, elle ne comprendra rien
2/ Petite astuce d'optimisation: a%2 est équivalent à a&1, la seconde solution étant autrement plus rapide
3/ Il y a trop de portions de code qui se ressemble, tu dois pouvoir synthétiser ça un beaucoup mieux à mon avis (en collant dx,dy, inc1,inc2 et x1,x2 dans un tableau par exemple

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.