École de technologie supérieure Génie de la production automatisée GPA665 Structures de données et algorithmes Laboratoire 3 Décomposition d’un polygone concave en polygones convexes Responsable du cours : Rédaction du laboratoire : Révision et barème de correction : Temps alloué pour ce laboratoire : Mohamed Cheriet, ing., Ph. D. Jean-Christophe Demers Yan Levasseur & Mathieu Binette 4 périodes de laboratoire Résumé En trois comme en deux dimensions, la gestion de formes à géométrie complexes nécessite beaucoup de manipulations mathématiques. Souvent, ces manipulations seront simplifiées par la décomposition d’une forme concave en plusieurs formes convexes, pour lesquelles les algorithmes d’optimisation sont rapides et efficaces. Le graphisme et la planification de trajectoire d’un robot mobile sont des exemples où la décomposition en formes convexes est très avantageuse. Ce laboratoire vous donnera l’occasion de réaliser un algorithme simple de décomposition en formes convexes. Ce sera l’occasion de mettre en pratique les notions relatives à l’utilisation du TDA arbre. De plus, par ce laboratoire, vous expérimenterez des notions telles que les types structurés, types énumérés, pointeurs, tableaux dynamiques, récursivité, et l’utilisation de structures de données et de fonctions existantes. Il vous incombera donc de développer un algorithme efficace pour résoudre le problème concret de la concavité d’une forme en adoptant une méthode de programmation rigoureuse qui tient compte des concepts fondamentaux de qualité logiciel. Énoncé du problème La description d’une entité par un polygone apporte des solutions à une multitude de problèmes de différentes natures. Ainsi, il est pertinent de développer une panoplie d’outils algorithmiques et géométriques servant à la manipulation de polygones. Or, il existe plusieurs propriétés particulières aux polygones convexes qui permettent le développement d’outils puissants, efficaces et uniques, qui sont très lourds ou simplement irréalisables pour le cas de polygones concaves. Pour cette raison, il est souvent préférable de diviser un polygone concave en plusieurs polygones convexes et ainsi pouvoir utiliser les différentes propriétés de ces polygones particuliers. Malgré tout, la décomposition d’un polygone n’est pas une tâche triviale et demande l’élaboration d’un algorithme d’une certaine complexité. Dans ce laboratoire vous aurez à implanter une solution fonctionnelle à ce problème. Finalement, la nature récursive du problème sera exploitée. Définitions d’un polygone convexe Soit P, un polygone formé de n sommets et n segments. P est convexe s’il répond à la définition suivante (sinon P est concave) : il est impossible de tracer une droite à l’intérieur du polygone qui traverse le contour de ce dernier. Une autre définition utile est : tous les angles intérieurs du polygone sont inférieurs à 180°. 121,5° 121,5° 44,0° 142,1° 121,0° 77,9° 292,2° 77,9° 125,8° 131,6° Polygone convexe 131,6° 52,8° Polygone concave Sommets convexes Sommets concaves Segments défini par deux sommets Figure 1 : Exemples de polygone convexe et de polygone concave GPA665 LABORATOIRE 3 STRUCTURES DE DONNEES ET ALGORITHMES AUTOMNE 2002 2 / 13 Nature récursive du problème et structure de données Intuitivement, il est facile de décomposer un polygone concave en deux sous-polygones dont un est convexe et l’autre indéfini. Développer un tel algorithme de décomposition peut être très pratique puisque la nature récursive du problème apparaît dès le départ. En effet, il suffit d’utiliser simplement ce même algorithme de décomposition sur le sous-polygone indéfini si ce dernier est concave. De cette façon, en appliquant récursivement cet algorithme de décomposition sur tous les sous-polygones indéfinis qui sont concaves, on obtient une décomposition complète du polygone concave initial en plusieurs polygones convexes. Puisque cette approche de décomposition donne pour chaque sous-polygone concave deux sous-polygones pour le décrire, on utilise un arbre binaire permettant de représenter cette structure de données. Dans ce type d’arbre, chacun des noeuds correspond à un polygone. Ainsi, la racine correspond au polygone concave initial qui est décrit par toutes les feuilles de l’arbre (correspondant aux sous-polygones convexes de l’arbre). Il est intéressant de remarquer que l’arbre obtenu n’est aucunement équilibré puisque ce dernier possède pour chaque noeud un enfant avec un seul et unique descendant. Néanmoins, cette représentation d’un polygone concave par des polygones convexes reste performante et très bien adaptée étant donné la nature récursive du problème. La figure 4 montre un exemple du résultat obtenu par une telle approche. Algorithme de décomposition Il existe plusieurs approches pour décomposer un polygone concave en polygones convexes. L’approche présentée ici offre certaines caractéristiques intéressantes. Premièrement elle permet une solution élégante en utilisant l’approche récursive précédemment expliquée. Deuxièmement, elle permet une décomposition du polygone initiale en sous-polygones de n sommets et non pas des polygones triangulaires formés de 3 sommets uniquement (comme plusieurs autres algorithmes le font). De cette façon, le nombre de sous-polygones convexes nécessaires à la représentation du polygone concave peut être beaucoup moindre. Finalement, il est possible d’optimiser l’algorithme de façon à décomposer le polygone concave en un nombre optimal de sous-polygones convexes. Cette optimisation se fait en prenant, pour chaque appel récursif, le sous-polygone convexe qui minimise le nombre de sommets du sous-polygone indéfini. 1 Cette optimisation n’est pas demandée dans le cadre de ce travail . 2 L’algorithme de décomposition d’un polygone concave en sous-polygones convexes est réalisé en 2 étapes principales : 1. On identifie tous les sommets Si correspondant aux concavités Ci du polygone P. 2. On détermine si le polygone est concave par le nombre de sommets correspondant aux concavités (nc). Si nc = 0 alors le polygone est convexe et on arrête le processus, sinon on divise le polygone concave en deux polygones : un polygone convexe et un polygone indéfini. Cette division est la partie la plus délicate du travail à faire et se fait en 4 étapes. i. On identifie un sommet Si pour lequel il existe deux voisins consécutifs, Si+d et Si+2d qui 3 respectent les trois critères suivants : 1 Les étudiants qui trouveront la façon de faire cette optimisation et qui prendront le temps de l’implanter se mériteront une évaluation plus clémente ! 2 L’algorithme qui est décrit ici est la version simplifiée, sans optimisation. GPA665 LABORATOIRE 3 STRUCTURES DE DONNEES ET ALGORITHMES AUTOMNE 2002 3 / 13 a. le sommet Si+d est un sommet convexe (ceci implique que le polygone formé par les trois sommets b. est un polygone convexe); le sommet Si+3d est à l’extérieur (la frontière étant incluse) du polygone formé par les sommets c. S i S i d S i2d S i S i d S i2d ; le segment formé par les sommets Si et Si+2d n’entre pas en collision avec le polygone à scinder. ii. On parcourt les sommets du polygone à partir de Si+jd (j = 2) jusqu’à ce qu’on atteigne un sommet Si+jd qui correspond à l’un des cinq critères suivants : a. b. c. d. e. Si+jd est un sommet correspondant à une concavité; le sommet Si+(j+1)d est à l’intérieur (la frontière étant exclue) du polygone formé par les sommets Si à Si+jd; le segment formé par les sommets Si+(j+1)d et Si entre en collision avec le polygone à scinder; le polygone créé par les sommets Si à Si+(j+1)d est concave; le polygone créé par les sommet Si à Si+(j+1)d entre en collision avec un des sommets restants du polygone à scinder. iii. On scinde le polygone concave P en deux polygones : le polygone convexe Pconvexe formé par les sommets Si à Si+jd et le polygone indéfini Pindéfini formé par les sommets Si+(j+1)d à Si (en respectant la définition circulaire des sommets décrivant les polygones). iv. On recommence récursivement le processus avec Pindéfini Voici un exemple pas à pas de cet algorithme pour le polygone suivant (les nombres indiquent l’ordre dans lequel sont définis les sommets) : 1 3 4 2 10 5 9 11 14 8 6 Sommets convexes Sommets concaves 7 12 13 Segments défini par deux sommets Figure 2 : Polygone concave 3 d est la direction du voisin considéré, c’est-à-dire 1 ou -1. Pour ce laboratoire on simplifie l’algorithme en posant d = 1. GPA665 LABORATOIRE 3 STRUCTURES DE DONNEES ET ALGORITHMES AUTOMNE 2002 4 / 13 Polygone convexe résultat de l’appel récursif précédent Polygone indéfinie résultat de l’appel récursif précédent Description de l’algorithme pour passer de l’appel récursif courant au suivant 1 3 4 2 Polygone initial. 10 1 5 9 nc = 4 Si = 2 j=2 11 14 défini par la contrainte 2c 8 6 7 12 13 12 Ces polygones sont le résultat de l’algorithme appliqué au polygone initial après le premier appel de la fonction de décomposition. 1 13 7 2 2 2 6 8 3 1 11 5 3 4 nc = 4 Si = 1 j=2 défini par la contrainte 2c nc = 4 Si = 1 j=3 défini par la contrainte 2a nc = 4 Si = 3 j=4 défini par la contrainte 2d nc = 3 Si = 3 j=2 défini par la contrainte 2a 9 10 10 12 1 11 5 2 3 6 4 9 3 1 3 2 7 8 7 9 8 4 2 4 3 3 1 1 6 2 10 4 5 5 1 3 5 2 6 1 4 5 7 4 2 3 GPA665 LABORATOIRE 3 STRUCTURES DE DONNEES ET ALGORITHMES AUTOMNE 2002 5 / 13 1 4 6 6 5 3 2 défini par la contrainte 2d nc = 1 Si = 2 j=2 défini par la contrainte 2a nc = 1 Si = 1 j=2 défini par la contrainte 2d 3 1 2 nc = 2 Si = 3 j=2 2 2 1 4 3 7 5 3 1 1 4 3 3 1 8 2 2 3 2 1 1 9 3 nc = 0 polygone convexe fin des appels récursifs 2 Voici le résultat de la décomposition obtenue : Figure 3 : Résultat obtenu après la décomposition du polygone concave Le graphique suivant montre le résultat de l’arbre de décomposition binaire résultant : GPA665 LABORATOIRE 3 STRUCTURES DE DONNEES ET ALGORITHMES AUTOMNE 2002 6 / 13 1 3 4 2 10 5 9 11 14 8 6 7 12 13 12 2 1 13 3 7 1 2 6 8 11 5 3 4 9 10 10 1 12 11 5 2 6 4 9 3 3 1 2 7 8 7 9 8 4 2 3 3 1 1 2 6 10 4 5 5 1 3 2 6 1 7 5 4 4 2 3 4 1 6 5 2 3 3 1 2 2 2 1 4 3 5 3 1 1 4 3 3 1 2 2 3 2 1 1 3 2 Figure 4 : Exemple d'arbre binaire obtenu représentant la décomposition d'un polygone concave GPA665 LABORATOIRE 3 STRUCTURES DE DONNEES ET ALGORITHMES AUTOMNE 2002 7 / 13 On remarque que cette décomposition en polygones convexes ne donne pas un nombre optimal de polygones. Après optimisation, on obtient plutôt cette décomposition qui contient 5 polygones au lieu des 9 polygones obtenus par l’algorithme de base. N’oublier pas que vous ne devez pas implanter la version optimisée de l’algorithme, cette partie n’est ici qu’à titre informatif pour ceux qui désirent aborder le problème. Figure 5 : Décomposition optimal du polygone concave Programme à développer Le programme que vous devez réaliser est évidemment l’implantation de l’algorithme précédemment décrit. Pour ce faire vous devez respecter tous les points suivants. Structure logiciel Votre programme doit être une extension du corps de programme que vous avez utilisé pour le laboratoire 2. De cette façon, vous aurez accès à toutes les fonctions qui avaient été préalablement implantées : gestion de l’interface Windows ; gestion de la boucle des messages de Windows ; gestion de la fenêtre de saisie du nom de fichier d’entrée ; gestion de la fameuse fenêtre « À propos… » ; gestion des menus et de la barre d’outils ; toutes les fonctions graphiques sont déjà incluses. De plus, vous avez à votre portée une bibliothèque de calculs géométriques dédiés à ce laboratoire. Cette bibliothèque vous donne une solution pour chaque sous-problèmes posés par l’algorithme de décomposition (principalement la vérification des différentes contraintes et conditions). Ainsi, il ne vous reste qu’à développer le corps global de l’algorithme en manipulant adéquatement les types de données et en faisant appel aux différentes fonctions fournies en temps opportun. Votre programme doit être en mesure de lire un fichier texte dans lequel se trouve la description d’un polygone. Vous devez en faire une validation de base afin de vous assurer que le fichier respecte le format imposé. Après avoir lancé votre algorithme de décomposition, vous devez afficher les informations suivantes : GPA665 LABORATOIRE 3 tracer tous les polygones convexes résultants de la décomposition (tel que montré à la figure 3), vous devez par contre afficher chaque polygone d’une couleur différente; STRUCTURES DE DONNEES ET ALGORITHMES AUTOMNE 2002 8 / 13 afficher les informations suivantes sur la structure de données : o le nombre de polygones convexes requis pour la description; o le nombre total de sommets et de segments utilisés pour décrire tous les polygones convexes ; o la somme de tous les périmètres des polygones convexes. Structure de données à respecter Tous les types de données sont déjà déclarés dans la bibliothèque de fonctions géométriques disponible sur le site web. Vous devez donc utiliser correctement les types déjà définis pour pouvoir utiliser les fonctions existantes. De plus, puisque vous programmez avec un compilateur C++ nous nous permettons d’utiliser les types booléens (qui ne sont pas portable directement sur un compilateur C). Voici les types qui ont été déclarés et que vous devez utiliser : Un type énuméré IsConvex indiquant si un sommet ou un polygone est convexe, concave ou indéfini. typedef enum {icConcave = 0, icConvex = 1, icUndef = 10} IsConvex; Une structure TVertex contenant les informations pour chaque sommet. typedef struct { int X, Y; IsConvex VertexIsConvex; } TVertex; Une structure TPolygon définissant chaque polygone. Cette structure est celle utilisée pour chaque noeud de l’arbre de représentation binaire. C’est pourquoi on y remarque les deux pointeurs vers les sous-polygones (SubConvexPolygon et SubUndefPolygon). Puisque le nombre de sommets de chaque polygone est connu (mémorisé par la variable NbVertices), un tableau de TVertex contenant la liste des sommets est créé dynamiquement pour chaque nouvel instanciation de polygone via le pointeur Vertices. typedef struct _TPolygon{ int NbVertices; TVertex *Vertices; IsConvex PolygonIsConvex; struct _TPolygon *SubConvexPolygon; struct _TPolygon *SubUndefPolygon; } TPolygon; Le schéma de la page suivante montre un exemple de cette structure. Les nombreuses fonctions de traitement sur les polygones sont incluses dans le fichier présent sur le site web. Vous avez accès directement au code et toute l’information sur ces fonctions se retrouve aux en-têtes de chaque fonction définie dans le fichier PolygonLibrary.c. Principalement vous allez devoir faire appel aux fonctions suivantes : GPA665 LABORATOIRE 3 DefineVerticesConvexity DefinePolygonConvexity PointIsInsideConvexPolygon SegmentIntersectSegment SegmentIntersectPolygon STRUCTURES DE DONNEES ET ALGORITHMES AUTOMNE 2002 9 / 13 NbVertices Vertices PolygonIsConvex SubConvexPolygon SubUndefPolygon NbVertices Vertices PolygonIsConvex SubConvexPolygon SubUndefPolygon X X Y VertexIsConvex X Y VertexIsConvex X Y VertexIsConvex X Y VertexIsConvex X Y VertexIsConvex X Y VertexIsConvex X Y VertexIsConvex X Y VertexIsConvex X Y VertexIsConvex X Y VertexIsConvex X Y VertexIsConvex X Y VertexIsConvex X Y VertexIsConvex X NbVertices Vertices PolygonIsConvex SubConvexPolygon SubUndefPolygon ... X NbVertices Vertices PolygonIsConvex SubConvexPolygon SubUndefPolygon X ... NbVertices Vertices PolygonIsConvex SubConvexPolygon SubUndefPolygon ... X NbVertices Vertices PolygonIsConvex SubConvexPolygon SubUndefPolygon X ... X NbVertices Vertices PolygonIsConvex SubConvexPolygon SubUndefPolygon ... NbVertices Vertices PolygonIsConvex SubConvexPolygon SubUndefPolygon ... X X ... NbVertices Vertices PolygonIsConvex SubConvexPolygon SubUndefPolygon Figure 6 : Exemple de la structure de données Évidemment vous allez devoir réaliser toutes les fonctions nécessaires à la gestion de la structure de données. C’est-à-dire l’instanciation de toute la structure, l’ajout d’un noeud dans l’arbre, la suppression de tous les noeuds, la gestion dynamique de la mémoire, la lecture du fichier d’entrée et toutes les autres fonctions que vous jugerez pertinentes. Fichier d’entrée Le fichier d’entrée est normalisé et doit correspondre au format suivant. On retrouve en en-tête le nombre de noeuds n du polygone. Ensuite, sur n lignes les coordonnées des sommets décrivant le polygone suivant ce format spécifique (X, Y). Voici un polygone ainsi que sa représentation selon ce format : GPA665 LABORATOIRE 3 STRUCTURES DE DONNEES ET ALGORITHMES AUTOMNE 2002 10 / 13 ... X 13 (100,20) (40,40) (40,120) (140,160) (120,140) (160,120) (120,80) (140,120) (60,60) (220,80) (160,160) (260,120) (260,60) Figure 7 : Exemple de fichier d'entrée Lors de la lecture du fichier, vous devez vous assurer que ce dernier et vérifier les 2 points suivants : le nombre de sommets indiqué correspond bien au nombre de sommets inclus dans le fichier; les coordonnées doivent être inclus dans les intervalles suivants y 0,480. x 0,640 et Informations supplémentaires Tous les algorithmes qui ont été décrits ici et toutes les fonctions que vous devez utiliser utilisent une description normalisée du polygone. Ainsi, il est essentiel que tous les polygones traités (soit ceux en entrée ou ceux que vous générez) soient décrits de la façon suivante : les sommets contigus du polygone se retrouvent contigus dans la liste de description (le tableau référencé par la variable Vertices dans la structure TPolygon); la description du polygone se fait toujours dans le sens anti-horaire. Finalement, vous ne devez utiliser aucune variable globale et votre code doit être lisible tout en étant bien documenté. GPA665 LABORATOIRE 3 STRUCTURES DE DONNEES ET ALGORITHMES AUTOMNE 2002 11 / 13 Évaluation L’évaluation de ce laboratoire sera différente des deux laboratoires précédents et permettra à l’évaluateur de faire une évaluation interactive. L’évaluation sera en trois parties : 1. Comme d’habitude, vous devez produire un rapport comprenant un organigramme général du déroulement de votre programme (1 page). Vous devez aussi remplir la grille d’évaluation. Par contre, notez qu’il n’y aura pas de questions à répondre par écrit. 2. Vous aurez à faire une brève présentation orale au chargé de laboratoire. Cette présentation d’une dizaine minutes vous donnera la chance d’expliquer en détail les éléments importants du laboratoire. Par exemple, vous pouvez expliquer votre approche globale, les difficultés que vous avez eues et les solutions que vous avez trouvées. 3. Finalement, vous aurez à répondre aux questions de l’évaluateur (environ 10 minutes également). Ces questions permettront de bien cerner votre niveau de compréhension. L’évaluation se fera pendant la semaine d’examen. La date exacte n’est pas déterminée mais l’évaluation sera pendant la période des examens finaux. Lors des deux dernières périodes de laboratoire, une feuille circulera vous permettant de réserver un bloc horaire. C’est votre responsabilité de vous présenter à cette évaluation. À titre indicatif, voici des exemples de questions qui pourraient vous être posées : Quelle est la pertinence de la structure de données utilisée dans ce laboratoire. En quoi cette structure est-elle mieux adaptée au problème de la division en sous-polygones qu’une autre structure de données ? Donnez les avantages et les inconvénients de la structure de données en arbre pour ce problème. Que seraient les implications de l’imposition d’une forme plus équilibrée de l’arbre ? Est-ce réalisable ? Imaginons le problème de la sélection d’un des sous-polygones affiché à l’écran à l’aide de la souris. Élaborez un moyen par lequel il serait possible d’identifier le sous-polygone sélectionné (avec comme seule information la position X et Y de la souris) sans parcourir toute la structure de données. Quel TDA suggèreriezvous pour cette tâche ? La remise se fait par un fichier ZIP correspondant aux éléments suivants : Le dossier principal de votre projet Visual C++ incluant tous ses dépendants (sauf les librairies principales du C/C++). N’oubliez pas de bien documenter votre code source. Une version exécutable de votre programme. Un PDF de votre rapport. Le fichier doit être nommé : GPA665_LAB3_Polygone_VotreNom.ZIP Le tout doit être remis par courriel au chargé de laboratoire avant la date prescrite. GPA665 LABORATOIRE 3 STRUCTURES DE DONNEES ET ALGORITHMES AUTOMNE 2002 12 / 13 Grille d’évaluation En guise d’autoévaluation, imprimez et remplissez vous-même cette section. Mentionnez une référence (nom de fichier et numéro de ligne) lorsque demandé pour faciliter la vérification par le correcteur. Spécifications techniques 5 Validation du fichier d’entrée 10 Séparation des polygones réussie 10 Affichage des sous-polygones colorés à partir d’un fichier .SDA en animation 5 Affichage des statistiques pour les souspolygones : nombre total de polygones, de segments, somme de tous les périmètres. Spécifications de programmation Oui Non Référence (fichier, ligne) _____________________ _____________________ _____________________ Oui Non 5 Utilisation de la structure de données imposées (arbre binaire) _____________________ 5 Gestion dynamique de la mémoire et libération de l’espace alloué _____________________ (-10) Aucune variable globale Qualité logicielle T.B. Bon Pauvre Référence (fichier, ligne) 5 Modularité : usage généralisé de fonctions et regroupement logique en modules _____________________ 5 Robustesse : Précaution pour éviter les problèmes de données erronées, etc. _____________________ 5 Documentation : Commentaires pertinents qui accélèrent la compréhension du code _____________________ 5 Clarté du code : Code concis et court utilisant les fonctions adaptées _____________________ 60 TOTAL _____________________ _____________________ _____________________ _____________________ Section réservée au correcteur : GPA665 LABORATOIRE 3 / 10 Organigramme / 30 Évaluation orale, réponses aux questions / 60 Respect des spécifications / 100 Total STRUCTURES DE DONNEES ET ALGORITHMES AUTOMNE 2002 13 / 13