TRIANGULATION DE DELAUNAY

Projet de C - Licence d'informatique 2001

Réalisé par Nicolas DUMOULIN et Michaël ORTEGA


Rappel du contexte théorique

retour en haut de la page

 

Triangulation : qu'est-ce que c'est ?

        La triangulation consiste à mailler un semis de points, avec des triangles ayant pour sommets les points du semis. Nous nous limiterons à un espace à deux dimension, qui est le cas d'école. En effet, le même problème peut se poser en un nombre de dimensions supérieur, notamment celui en 3 dimensions, qui est très utilisé pour la modélisation des objets (réalité virtuelle).
   Ce maillage doit répondre à certaine propriétés de la triangulation, à savoir que l'intersection de deux triangles est soit :

    Le problème consiste à choisir une méthode pour construire cette triangulation. Nous allons nous intéresser à celle de Delaunay qui repose sur le diagramme de Voronoï (ces deux représentation sont en fait duales).

La méthode Delaunay

    Cette méthode s'appuie principalement sur le critère suivant :

Soit T un triangle du maillage, alors aucun point du semis (sauf ceux de T), n'est contenu dans le cercle cercle circonscrit de T.

    Nous allons utiliser un algorithme incrémental pour construire le diagramme de Delaunay (il en existe d'autres qui utilisent des méthodes globales, comme le célèbre "Diviser pour Construire" ou "divide and conquer").

Principe: 

    On insère les points un par un. A chaque point inséré, on recherche dans quel triangle il se trouve. On supprime alors ce triangle pour en créer trois nouveaux ayant pour sommet ce point et pour côté opposé les arêtes du triangle englobant. On vérifie ensuite le critère, c'est à dire que le point inséré ne se trouve pas dans le cercle circonscrit d'un des triangles voisins. Si c'est le cas, on fait pivoter l'arête commune entre les deux triangles, et on vérifie le critère avec les voisins des nouveaux triangles créés.... 

Pour ce faire il faut initialiser le maillage, c'est à dire qu'il faut au moins un triangle de départ qui contient tous les points à insérer. A la fin, une fois tous les points insérés, on retire ce triangle du maillage et on corrige éventuellement en rajoutant des triangles sur le bord du maillage de façon à former une enveloppe convexe. 




Structures de données utilisées

retour en haut de la page


On utilise une liste doublement chaînée pour stocker les points. Ces points sont à coordonnées réelles et seront représentés par un enregistrement contenant 2 champs, un pour l'abscisse et un pour l'ordonnée.

On utilise une deuxième liste doublement chaînée LT pour le stockage des triangles du maillage. Chaque élément de la liste est un enregistrement contenant un champ du type triangle, et deux pointeurs pour l'accès au précédent et au suivant de la liste. On fera en sorte que la liste soit triée par rapport à l'orthocentre du triangle de chaque élément (tri par abscisse, puis par ordonnée si collision).

typedef struct triangle{
Elt *s1,*s2,*s3;            
EltTriangle *tv1,*tv2,*tv3; 
Point H;                             
} Triangle;

typedef struct eltTriangle{
Triangle t;                     
struct eltTriangle *prec; 
struct eltTriangle *suiv;  
} EltTriangle;
typedef struct tliste{
int nbT;          
EltTriangle *first; 
EltTriangle *last; 
} Tliste;

Le type triangle est un enregistrement contenant :

  • trois pointeurs sur des éléments de la liste de points qui sont les trois sommets du triangle

  • trois pointeurs sur des éléments de LT référençant les voisins du triangle

  • un champ H contenant un point correspondant aux coordonnées de l'orthocentre du triangle

 

 

Voici un schéma regroupant les différentes déclarations et leurs liens :

Liste de points

 

Liste de triangles

 

Autres structures de données utilisées :

 

 


Description de l'algorithme

retour en haut de la page

  1. Outils géométriques : geometrie.c et geometrie.h

  2. Opérations sur le type Point : points.c et points.h

  3. Manipulation d'une liste de Points : listePoint.c et listePoint.h

  4. Opérations sur le type Triangle et gestion d'une liste de triangles : listeTriangle.c et listeTriangle.h

  5. Fonctions et procédures propres à l'algorithme : delaunay.c et delaunay.h


Algorithme principal :

  1. Chargement des points en mémoire, dans la structure prévue, à partir du fichier d'entrée. Ce fichier d'entrée sera conforme au format suivant : le nombre de points contenu dans le fichier, suivi (ligne par ligne) des coordonnées des points comprises entre 0 et 100, écrites sur deux caractères avec 2 espaces entre chaque coordonnée, exemple : entree.dat.

  2. Initialisation de la boite englobante  : l'algorithme de Delaunay reposant sur l'insertion de points dans un triangle, on doit avoir un triangle de départ. Pour résoudre cette contrainte, on crée une boite englobante autour du semis de points : c'est à dire un rectangle ( mieux adapté au problème qu'un triangle) que l'on divise en deux triangles.  

  3. Insertion des points un à un, avec vérification du critère du cercle circonscrit.

  4. Suppression de la boite englobante.

  5. Écriture dans un fichier des triangles résultant de la triangulation, au format suivant : liste des triangles affichés ligne par ligne.

 

Prototypes des fonctions utilisées pour la réalisation de l'algorithme :

 

  1. Outils géométriques : geometrie.c et geometrie.h

  2. Opérations sur le type Point : points.c et points.h

  3. Manipulation d'une liste de Points : listePoint.c et listePoint.h

  4. Opérations sur le type Triangle et gestion d'une liste de triangles : listeTriangle.c et listeTriangle.h

  5. Fonctions et procédures propres à l'algorithme : delaunay.c et delaunay.h

Programme principal :

    Il suffit d'appeler la procédure fichier_de_points avec le nom de fichier saisie à l'appel du programme pour charger les points en mémoire. Ensuite on appelle init_All pour créer la boite englobante. On parcourt la liste de points et on les insère un par un dans le maillage à l'aide de la procédure ajoute_point_dans_Graphe. A la sortie on obtient la liste des triangles du maillage. On supprime alors la boite englobante. Il ne reste plus qu'à écrire dans un fichier ( sortie.dat ) les triangles, identifiés par leurs sommets.

 

 


Remarques et conclusion

retour en haut de la page


Optimisation et résultats du programme :

    On pourrait améliorer la structure de données, en modifiant les champs sommets et triangles voisins, en remplaçant dans les deux cas les trois champs par un tableau de trois pointeurs.

    Le programme ne fonctionnement pas dans tous les cas. Pour l'insertion de points, tout se passe comme prévu, mais lors de la vérification du critère, à partir du deuxième appel ( récursif ) des triangles ne sont pas supprimés. En effet, après vérification, on pouvait obtenir quatre triangles pour quatre points. On en conclut, que le pivotement d'arête a lieu, mais que l'actualisation de la liste n'est pas correcte : 

LA VERITE EST AILLEURS....

Du point de vue de la suppression de la boite englobante, nous avons vérifié que l'on obtenait bien les points du contours. Tout se passe correctement, mis à part la suppression, de la mémoire, de la liste de triangles temporaire que l'on crée. En effet, la liste ne ressort pas indemne de la boucle qui consiste à vérifier la convexité du système. Mais, nous n'arrivons pas à comprendre pourquoi, puisque on ne fait pas appel à la liste dans cette boucle. Encore une fois : Mystère.

Bénéfice du projet :

    En dehors du plaisir incommensurable de débugger un programme en C, nous avons pu prendre conscience que la notion de pointeurs n'était pas si évidente à manipuler. Nous avons également, mais trop tard, adopté des méthodes un peu plus rigoureuses pour programmer.

Quelques liens intéressants :

Algorithme de Delaunay

Triangulation de Delaunay

Triangulation de Delaunay

Ces quelques sites nous ont bien inspirés au niveau de la réalisation de l'algorithme, et le troisième nous a plus particulièrement soufflé la structure de donnée pour le type triangle (le fait que chaque triangle point sur ses voisins).