Je cherche un algorithme très simple pour calculer l'intersection/le découpage des polygones . C'est-à-dire, étant donné les polygones P
, Q
, je souhaite trouver le polygone T
qui est contenu dans P
et dans Q
et que je souhaite que T
soit maximal parmi tous les polygones possibles.
Le temps d'exécution ne me dérange pas (j'ai quelques très petits polygones), je peux aussi me permettre d'obtenir une approximation de l'intersection des polygones (c'est-à-dire, un polygone avec moins de points, mais qui est toujours contenu dans l'intersection des polygones ).
Mais il est vraiment important pour moi que l’algorithme soit simple (tests moins coûteux) et de préférence court (moins de code).
edit: s'il vous plaît noter, je souhaite obtenir un polygone qui représente l'intersection. Je n'ai pas besoin que d'une réponse booléenne à la question de savoir si les deux polygones se croisent.
Je comprends que l’affiche originale cherchait une solution simple, mais malheureusement, il n’existe pas de solution simple.
Néanmoins, j'ai récemment créé une bibliothèque de coupures de logiciels libres open-source (écrites en Delphi, C++ et C #) qui permet de clipser toutes sortes de polygones (y compris ceux qui se croisent automatiquement). Cette bibliothèque est assez simple à utiliser: http://sourceforge.net/projects/polyclipping/ .
Vous pouvez utiliser un algorithme Polygon Clipping pour rechercher l'intersection de deux polygones. Cependant, ces algorithmes ont tendance à être compliqués lorsque tous les cas Edge sont pris en compte.
Une implémentation de la coupure de polygone que vous pouvez utiliser avec votre moteur de recherche préféré est Weiler-Atherton. Article de wikipedia sur Weiler-Atherton
Alan Murta dispose d'une implémentation complète d'un clipper de polygones GPC .
Modifier:
Une autre approche consiste à diviser d’abord chaque polygone en un ensemble de triangles, plus faciles à gérer. Le théorème Deux-oreilles de Gary H. Meisters fait l'affaire. Cette page à McGill explique très bien la subdivision en triangle.
Si vous utilisez C++ et que vous ne voulez pas créer l'algorithme vous-même, vous pouvez utiliser Boost.Geometry . Il utilise une version adaptée de l'algorithme de Weiler-Atherton mentionné ci-dessus.
Vous ne nous avez pas donné votre représentation d'un polygone. Donc, je choisis (plutôt de suggérer) un pour vous :)
Représentez chaque polygone comme un grand polygone convexe et une liste de polygones convexes plus petits qui doivent être «soustraits» de ce grand polygone convexe.
Maintenant, étant donné deux polygones dans cette représentation, vous pouvez calculer l'intersection comme suit:
Calculez l'intersection des grands polygones convexes pour former le grand polygone de l'intersection. Puis «soustrayez» les intersections de toutes les plus petites des deux pour obtenir une liste des polygones sous-traités.
Vous obtenez un nouveau polygone suivant la même représentation.
Étant donné que l'intersection de polygones convexes est facile, cette recherche d'intersection devrait l'être également.
Cela semble fonctionner, mais je n’y ai pas réfléchi plus en profondeur en ce qui concerne la complexité correct/temps/espace.
Voici une approche basée sur la triangulation qui est assez simple à mettre en œuvre et peut être exécutée en mode O (N).2).
BTW, O (N2) est optimale pour ce problème. Imaginez deux polygones en forme de lames de fourche se coupant à angle droit. Chacun a un nombre de segments proportionnel au nombre de dents; le nombre de polygones dans l'intersection est proportionnel au carré du nombre de dents.
D'abord, triangulez chaque polygone.
Comparez tous les triangles de P par paire avec tous les triangles de Q pour détecter les intersections. Toute paire de triangles qui se croisent peut être divisée en triangles plus petits, chacun d'eux étant en P, en Q ou à l'intersection. (Ce que vous avez utilisé à l'étape 1 peut être réutilisé pour vous aider.) Ne conservez que les triangles qui se trouvent à l'intersection.
Calculez les voisins de chaque triangle en les comparant par paires et construisez un graphique de contiguïté. Ce graphique contiendra un sous-graphe connecté pour chaque polygone dans l'intersection de P et de Q.
Pour chacun de ces sous-graphes, choisissez un triangle, dirigez-vous vers Edge, puis contournez-le en produisant les segments délimitant le polygone de sortie correspondant.
Voici une approche simple et stupide: en entrée, discrétisez vos polygones en bitmap. Pour se croiser, ET les bitmaps ensemble. Pour produire des polygones en sortie, tracez les bords irréguliers du bitmap et lissez-les à l'aide d'un algorithme d'approximation de polygone . (Je ne me souviens pas si ce lien fournit les algorithmes les plus appropriés, il ne s'agit que du premier hit de Google. Vous pouvez essayer l'un des outils permettant de convertir des images bitmap en représentations vectorielles. Vous pourriez peut-être y faire appel sans réimplémenter l'algorithme. ?)
La partie la plus complexe serait traçant les frontières }, je pense.
Au début des années 90, je rencontrais d'ailleurs un problème de ce type au travail. Je l'ai étouffé: j'ai mis au point un algorithme (complètement différent) qui fonctionnerait avec les coordonnées d'un nombre réel, mais qui semblait se heurter à une pléthore de cas dégénérés complètement irréversible face aux réalités de la virgule flottante . Peut-être qu'avec l'aide d'Internet, j'aurais mieux fait!
La façon dont j'ai travaillé sur le même problème
IntervalTrees
ou LineSweepAlgo
GrahamScanAlgo
pour trouver un chemin fermé avec des sommets adjacentsDinicAlgo
pour les dissoudrenote: mon scénario était différent étant donné que les polygones avaient un sommet commun. Mais espérons que cela peut aider
Je n'ai pas de solution très simple, mais voici les principales étapes pour l'algorithme real:
std::list
ne suffira pas, car vous devez permuter vous-même les pointeurs/décaleurs précédents et précédents .__ pour une opération spéciale sur les nœuds C’est le seul moyen d’avoir un code simple et cela donnera de bonnes performances.Ensuite, vous avez le résultat brut de l'algorithme de résolution d'intersection de polygones. Normalement, vous souhaiterez sélectionner une région en fonction du nombre d'enroulement de chaque région. Recherchez numéro de polygone pour une explication à ce sujet.
Si vous souhaitez créer un algorithme O (N · logN) à partir de celui-ci, vous devez faire exactement la même chose, sauf que vous le faites dans un algorithme de balayage de ligne. Cherchez algorithme de Bentley Ottman. L'algorithme interne sera le même, avec la seule différence que vous aurez un nombre réduit d'arêtes à comparer, à l'intérieur de la boucle.