Je suis récemment tombé sur un problème où j'avais quatre cercles (points milieu et rayon) et que je devais calculer la surface de l'union de ces cercles.
Exemple d'image:
Pour deux cercles c'est assez facile,
Je peux simplement calculer la fraction de la surface de chaque cercle qui ne se trouve pas dans les triangles, puis calculer la surface des triangles.
Mais y a-t-il un algorithme intelligent que je peux utiliser quand il y a plus de deux cercles?
Recherchez toutes les intersections de cercle sur le périmètre extérieur (par exemple, B, D, F et H sur le diagramme suivant). Connectez-les avec les centres des cercles correspondants pour former un polygone. L'aire de l'union des cercles est l'aire du polygone + l'aire des tranches de cercle définies par des points d'intersection consécutifs et le centre du cercle entre eux. Vous devrez également tenir compte de tous les trous.
Je suis sûr qu'il existe un algorithme intelligent, mais voici un algorithme stupide pour éviter d'avoir à le chercher;
Bien sûr que c'est bête, mais:
Pour une solution différente de la précédente, vous pouvez produire une estimation avec une précision arbitraire en utilisant un arbre à quatre arbres.
Cela fonctionne également pour toute union de forme si vous pouvez dire si un carré est à l'intérieur ou à l'extérieur ou intersecte la forme.
Chaque cellule a l'un des états suivants: vide, complet, partiel
L'algorithme consiste à "dessiner" les cercles du quadtree en commençant par une résolution basse (4 cellules par exemple marquées comme vides). Chaque cellule est soit:
Quand c'est fait, vous pouvez calculer une estimation de l'aire: les cellules pleines donnent la limite inférieure, les cellules vides indiquent la limite supérieure, les cellules partielles donnent l'erreur d'aire maximale.
Si l'erreur est trop importante pour vous, vous affinez les cellules partielles jusqu'à obtenir la bonne précision.
Je pense que ce sera plus facile à mettre en œuvre que la méthode géométrique qui peut nécessiter de traiter beaucoup de cas particuliers.
La réponse de Ants Aasma a donné l’idée de base, mais je voulais la rendre un peu plus concrète. Examinez les cinq cercles ci-dessous et la manière dont ils ont été décomposés.
Identifier ces 3 types de points est facile. Construisons maintenant une structure de données graphique où les nœuds sont les points bleus et les points rouges avec un intérieur blanc. Pour chaque cercle, placez un bord entre le milieu du cercle (point bleu) et chacune de ses intersections (points rouges avec un intérieur blanc) sur sa limite.
Cela décompose l'union du cercle en un ensemble de polygones (ombré en bleu) et de morceaux de camembert circulaires (ombrés en vert) qui sont disjoints deux à deux et recouvrent l'union originale (c'est-à-dire une partition). Comme chaque pièce ici est une chose facile à calculer, vous pouvez calculer la surface de l’union en faisant la somme des zones.
J'aime l'approche du cas de 2 cercles en intersection - voici comment j'utiliserais une légère variation de la même approche pour l'exemple plus complexe.
Cela permettrait peut-être de mieux comprendre la généralisation de l'algorithme pour un plus grand nombre de cercles se chevauchant partiellement.
La différence ici est que je commence par relier les centres (il y a donc un sommet entre le centre des cercles et non entre les endroits où les cercles se croisent). Je pense que cela permet de mieux généraliser.
(dans la pratique, peut-être que la méthode monte-carlo en vaut la peine)
Si vous voulez une réponse discrète (par opposition à une réponse continue), vous pouvez faire quelque chose de similaire à un algorithme de peinture de pixels.
Dessinez les cercles sur une grille, puis colorez chaque cellule de la grille si elle est principalement contenue dans un cercle (c’est-à-dire qu’au moins 50% de sa surface est située dans l’un des cercles). Faites cela pour la grille entière (où la grille couvre toute la zone couverte par les cercles), puis comptez le nombre de cellules colorées dans la grille.
Hmm, problème très intéressant. Mon approche ressemblerait probablement à ce qui suit:
(ceci est vrai pour n'importe quelle forme, que ce soit un cercle ou autre)
area(A∪B) = area(A) + area(B) - area(A∩B)
Où A ∪ B
signifie une union B et A ∩ B
signifie une intersection B (vous pouvez résoudre ce problème dès la première étape.
(C'est la même chose que ci-dessus où A
a été remplacé par A∪B
)
area((A∪B)∪C) = area(A∪B) + area(C) - area((A∪B)∩C)
Où area(A∪B)
nous avons juste travaillé, et area((A∪B)∩C)
peut être trouvé:
area((A∪B)nC) = area((A∩C)∪(B∩C)) = area(A∩C) + area(A∩B) - area((A∩C)∩(B∩C)) = area(A∩C) + area(A∩B) - area(A∩B∩C)
Où encore vous pouvez trouver la région (A∩B∩C) d'en haut.
La dernière chose à faire est la dernière étape - plus il y a de cercles, plus il devient complexe. Je crois qu'il existe une extension pour résoudre le point d'intersection avec une union finie. Sinon, vous pourrez peut-être résoudre le problème de manière récursive.
En ce qui concerne également l'utilisation de Monte-Carlo pour estimer l'aire de la section, je pense qu'il est possible de réduire l'intersection d'un nombre arbitraire de cercles à l'intersection de 4 de ces cercles, ce qui peut être calculé exactement (aucune idée de la manière de procéder). toutefois).
Il y a probablement une meilleure façon de faire cela - la complexité augmente de manière significative (peut-être de façon exponentielle, mais je ne suis pas sûr) pour chaque cercle supplémentaire ajouté.
J'ai travaillé sur un problème de simulation de champs d'étoiles superposés, en essayant d'estimer le nombre réel d'étoiles à partir des zones réelles du disque dans les champs denses, où les grandes étoiles brillantes peuvent masquer les plus faibles. J'espérais moi aussi pouvoir le faire par une analyse formelle rigoureuse, mais je n'ai pas pu trouver d'algorithme pour la tâche. Je l'ai résolu en générant les champs d'étoiles sur un fond bleu sous forme de disques verts, dont le diamètre était déterminé par un algorithme de probabilité. Une simple routine peut les jumeler pour voir s'il y a un chevauchement (en tournant la paire d'étoiles en jaune); ensuite, un nombre de pixels des couleurs génère la zone observée à comparer à la zone théorique. Ceci génère ensuite une courbe de probabilité pour les comptes réels. La force brute peut-être, mais cela semble fonctionner correctement.
http://www.2from.com/images/simulated_star_field.gif
Il existe des solutions efficaces à ce problème en utilisant ce que l’on appelle les diagrammes de puissance. C’est un calcul vraiment lourd et ce n’est pas quelque chose que je voudrais aborder à la volée. Pour une solution "facile", recherchez des algorithmes de balayage de lignes. Le principe de base est que vous divisez la figure en bandes, le calcul de la surface de chaque bande étant relativement facile.
Ainsi, sur la figure contenant tous les cercles n’ayant pas été effacé, tracez une ligne horizontale à chaque position correspondant au haut d’un cercle, au bas d’un cercle ou à l’intersection de 2 cercles. Notez qu'à l'intérieur de ces bandes, toutes les zones que vous devez calculer se ressemblent: un "trapèze" dont les deux côtés sont remplacés par des segments circulaires. Donc, si vous pouvez déterminer comment calculer une telle forme, il vous suffit de le faire pour toutes les formes individuelles et de les additionner. La complexité de cette approche naïve est O (N ^ 3), où N est le nombre de cercles de la figure. Avec une utilisation astucieuse de la structure de données, vous pourriez améliorer cette méthode de balayage de lignes en O (N ^ 2 * log (N)), mais à moins que vous en ayez vraiment besoin, cela ne vaut probablement pas la peine.
J'ai trouvé ce lien qui peut être utile. Il ne semble pas y avoir de réponse définitive cependant . Google répond . Une autre référence pour trois cercles est le théorème de Haruki . Il y a aussi un papier.
Voici un algorithme qui devrait être facile à mettre en œuvre dans la pratique et qui pourrait être ajusté pour produire une erreur arbitrairement petite:
Les étapes 2 et 3 peuvent être réalisées à l'aide d'algorithmes standard faciles à trouver issus de la géométrie algorithmique.
Évidemment, plus vous utilisez de côtés pour chaque polygone approximatif, plus votre réponse sera exacte. Vous pouvez utiliser une approximation à l'aide de polygones inscrits et circonscrits pour déterminer la réponse exacte.
En fonction du problème que vous essayez de résoudre, il pourrait suffire d’obtenir une limite supérieure et une limite inférieure. Une limite supérieure est facile, juste la somme de tous les cercles. Pour une limite inférieure, vous pouvez choisir un seul rayon de sorte qu'aucun des cercles ne se chevauchent. Pour améliorer cela, trouvez le plus grand rayon (jusqu'au rayon réel) pour chaque cercle afin qu'il ne se chevauche pas. Il devrait également être assez simple de supprimer tous les cercles qui se chevauchent (Tous ces cercles satisfont | P_a - P_b | <= r_a) où P_a est le centre du cercle A, P_b est le centre du cercle B et r_a est le rayon de A ) et cela améliore la limite supérieure et inférieure. Vous pouvez également obtenir une meilleure borne supérieure si vous utilisez votre formule de paire sur des paires arbitraires au lieu de simplement la somme de tous les cercles. Il existe peut-être un bon moyen de choisir les "meilleures" paires (les paires résultant en une surface totale minimale.
Avec une limite supérieure et une limite inférieure, vous pourrez peut-être mieux accorder une approche Monte-Carlo, mais rien de particulier ne me vient à l’esprit. Une autre option (toujours en fonction de votre application) consiste à pixelliser les cercles et à compter les pixels. C’est fondamentalement l’approche de Monte-Carlo avec une distribution fixe.
Ceci peut être résolu en utilisant le théorème de Green, avec une complexité de n ^ 2log (n) . Si vous n'êtes pas familier avec le théorème de Green et que vous souhaitez en savoir plus, voici le vidéo et notes de Khan Academy. Mais pour le bien de notre problème, je pense que ma description sera suffisante.
Désolé pour les liens vers les photos, je ne peux pas publier d'images. (Pas assez de points de réputation)
Equation générale du théorème de Green
Si je mets L _ et M tels que
alors l'ERS est simplement la zone de la région R et peut être obtenue en résolvant l'intégrale fermée ou LHS et c'est exactement ce que nous allons faire.
Toutes les unions peuvent être divisées en de tels ensembles de cercles disjoints qui se croisent
Ainsi, intégrer le long du chemin dans le sens contraire des aiguilles d'une montre nous donne le Zone de la région et intégrer le long du chemin dans le sens des aiguilles d'une montre nous donne un négatif du Zone. Alors
AreaOfUnion = (Intégration le long des arcs rouges dans le sens antihoraire + Intégration le long des arcs bleus dans le sens des aiguilles d'une montre)
Mais le bon truc, c’est que si pour chaque cercle, si nous intégrons les arcs qui ne se trouvent dans aucun autre cercle, nous obtenons notre zone requise, c’est-à-dire que nous obtenons une intégration dans le sens contraire des aiguilles d’une montre le long de tous les arcs rouges et une intégration dans tous les arcs bleus du sens des aiguilles d’une montre. TRAVAIL ACCOMPLI!!!
Même les cas où un cercle ne recoupe aucun autre sont pris en compte soin de.
Voici le lien GitHub vers mon Code C++