Je suis récemment tombé sur un problème où j'avais quatre cercles (milieu et rayon) et devais calculer l'aire de l'union de ces cercles.
Exemple d'image:
Pour deux cercles c'est assez facile,
Je peux simplement calculer la fraction de la zone de chaque cercle qui n'est 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?
Réponses:
Trouvez toutes les intersections de cercles sur le périmètre extérieur (par exemple B, D, F, 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.
la source
Je suis sûr qu'il existe un algorithme intelligent, mais en voici un idiot pour éviter d'avoir à le chercher;
Bien sûr, c'est stupide, mais:
la source
La réponse d'Ants Aasma a donné l'idée de base, mais je voulais la rendre un peu plus concrète. Jetez un œil aux cinq cercles ci-dessous et à la façon dont ils ont été décomposés.
Identifier ces 3 types de points est facile. Construisez 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 une arête entre le milieu du cercle (point bleu) et chacune de ses intersections (points rouges avec intérieur blanc) sur sa limite.
Cela décompose l'union du cercle en un ensemble de polygones (ombrés en bleu) et de morceaux de secteurs circulaires (ombrés en vert) qui sont disjoints par paires et recouvrent l'union d'origine (c'est-à-dire une partition). Étant donné que chaque pièce ici est quelque chose dont il est facile de calculer l'aire, vous pouvez calculer l'aire de l'union en additionnant les aires des pièces.
la source
Pour une solution différente de la précédente, vous pouvez produire une estimation avec une précision arbitraire en utilisant un arbre quaternaire.
Cela fonctionne également pour n'importe quelle union de forme si vous pouvez dire si un carré est à l'intérieur ou à l'extérieur ou croise la forme.
Chaque cellule a l'un des états: vide, plein, partiel
L'algorithme consiste à "dessiner" les cercles dans l'arbre quaternaire en commençant par une faible résolution (4 cellules par exemple marquées comme vides). Chaque cellule est soit:
Lorsque c'est fait, vous pouvez calculer une estimation de la surface: les cellules pleines donnent la borne inférieure, les cellules vides donnent la borne supérieure, les cellules partielles donnent l'erreur de surface maximale.
Si l'erreur est trop importante pour vous, vous affinez les cellules partielles jusqu'à ce que vous obteniez 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 de nombreux cas particuliers.
la source
J'adore l'approche du cas de 2 cercles qui se croisent - voici comment j'utiliserais une légère variation de la même approche pour l'exemple plus complexe.
Cela pourrait donner un meilleur aperçu de la généralisation de l'algorithme pour un plus grand nombre de cercles semi-superposés.
La différence ici est que je commence par relier les centres (il y a donc un sommet entre le centre des cercles, plutôt qu'entre les endroits où les cercles se croisent) Je pense que cela permet de mieux se généraliser.
(en pratique, peut-être que la méthode monte-carlo vaut la peine)
(source: secretGeek.net )
la source
Si vous voulez une réponse discrète (par opposition à une réponse continue), vous pouvez faire quelque chose de similaire à un algorithme de pixel painting.
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 à l'intérieur de l'un des cercles). Faites ceci pour toute la grille (où la grille couvre toute la zone couverte par les cercles), puis comptez le nombre de cellules colorées dans la grille.
la source
Hmm, problème très intéressant. Mon approche serait probablement quelque chose du genre:
(cela est vrai pour n'importe quelle forme, que ce soit un cercle ou autre)
Où
A ∪ B
signifie A union B etA ∩ B
signifie A intersecter B (vous pouvez le calculer à partir de la première étape.(C'est le même que ci-dessus où
A
a été remplacé parA∪B
)Où
area(A∪B)
nous venons de travailler, etarea((A∪B)∩C)
peut être trouvé:Où encore vous pouvez trouver la zone (A∩B∩C) d'en haut.
Le plus délicat est la dernière étape - plus les cercles sont ajoutés, plus cela devient complexe. Je crois qu'il y a une extension pour travailler sur l'aire d'une intersection avec une union finie, ou alternativement, vous pourrez peut-être la résoudre de manière récursive.
Aussi en ce qui concerne l'utilisation de Monte-Carlo pour approximer la zone d'itersection, je pense qu'il est possible de réduire l'intersection d'un nombre arbitraire de cercles à l'intersection de 4 de ces cercles, qui peuvent être calculés exactement (aucune idée de comment faire cela toutefois).
Il existe probablement une meilleure façon de faire cela - la complexité augmente considérablement (peut-être de façon exponentielle, mais je ne suis pas sûr) pour chaque cercle supplémentaire ajouté.
la source
J'ai travaillé sur un problème de simulation de champs d'étoiles qui se chevauchent, en essayant d'estimer le nombre réel d'étoiles à partir des zones de disque réelles dans des champs denses, où les plus grandes étoiles brillantes peuvent masquer les plus faibles. J'avais moi aussi espéré pouvoir le faire par une analyse formelle rigoureuse, mais je n'ai pas pu trouver un algorithme pour la tâche. Je l'ai résolu en générant les champs d'étoiles sur fond bleu sous forme de disques verts, dont le diamètre était déterminé par un algorithme de probabilité. Une simple routine peut les coupler pour voir s'il y a un chevauchement (en tournant la paire d'étoiles en jaune); puis un comptage de pixels des couleurs génère la zone observée à comparer à la zone théorique. Cela génère alors une courbe de probabilité pour les vrais comptes. Force brute peut-être, mais cela semble fonctionner correctement. (source: 2from.com )
la source
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 effectuées à l'aide d'algorithmes standard et faciles à trouver à partir de la géométrie de calcul.
De toute évidence, plus vous utilisez de côtés pour chaque polygone approximatif, plus votre réponse sera proche de l'exactitude. Vous pouvez effectuer une approximation en utilisant des polygones inscrits et circonscrits pour obtenir des limites sur la réponse exacte.
la source
Il existe des solutions efficaces à ce problème en utilisant ce que l'on appelle des diagrammes de puissance. Ce sont des calculs vraiment lourds et pas quelque chose que je voudrais aborder de manière désinvolte. Pour une solution «simple», recherchez des algorithmes de balayage de ligne. Le principe de base ici est que vous divisez la figure en bandes, où le calcul de la surface dans chaque bande est relativement facile.
Ainsi, sur la figure contenant tous les cercles sans aucun frottement, tracez une ligne horizontale à chaque position qui est soit le haut d'un cercle, le 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» avec deux côtés remplacés par des segments circulaires. Donc, si vous pouvez déterminer comment calculer une telle forme, faites-le simplement pour toutes les formes individuelles et ajoutez-les ensemble. La complexité de cette approche naïve est O (N ^ 3), où N est le nombre de cercles de la figure. Avec une utilisation intelligente de la structure de données, vous pouvez améliorer cette méthode de balayage de ligne à O (N ^ 2 * log (N)), mais à moins que vous n'en ayez vraiment besoin, cela ne vaut probablement pas la peine.
la source
J'ai trouvé ce lien qui peut être utile. Cependant, il ne semble pas y avoir de réponse définitive. Google répond . Une autre référence pour trois cercles est le théorème de Haruki . Il y a aussi un article.
la source
En fonction du problème que vous essayez de résoudre, il peut suffire d'obtenir une limite supérieure et inférieure. Une borne supérieure est facile, juste la somme de tous les cercles. Pour une limite inférieure, vous pouvez choisir un rayon unique de sorte qu'aucun des cercles ne se chevauche. Pour mieux trouver le plus grand rayon (jusqu'au rayon réel) pour chaque cercle afin qu'il ne se chevauche pas. Il devrait également être assez trivial de supprimer tous les cercles complètement superposés (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 fois 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 le "meilleur"
Étant donné une limite supérieure et inférieure, vous pourrez peut-être mieux régler une approche Monte-carlo, mais rien de spécifique ne vient à l'esprit. Une autre option (toujours en fonction de votre application) consiste à pixelliser les cercles et à compter les pixels. Il s'agit essentiellement de l'approche Monte-carlo avec une distribution fixe.
la source
Cela 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 voulez en savoir plus, voici la vidéo et les notes de Khan Academy. Mais pour le bien de notre problème, je pense que ma description sera suffisante.
Équation générale du théorème de Green
Si je mets L et M tels que
État
alors le RHS est simplement l'aire de la région R et peut être obtenu 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 des ensembles disjoints de cercles qui se croisent
Donc, intégrer le long du chemin dans le sens inverse des aiguilles d'une montre nous donne la zone de la région et intégrer le long du sens des aiguilles d'une montre nous donne le négatif de la zone . Alors
AreaOfUnion = (Intégration le long des arcs rouges dans le sens anti-horaire + Intégration le long des arcs bleus dans le sens horaire)
Mais le truc sympa est si pour chaque cercle, si nous intégrons les arcs qui ne sont à l'intérieur d'aucun autre cercle, nous obtenons notre zone requise, c'est-à-dire que nous obtenons une intégration dans le sens inverse des aiguilles d'une montre le long de tous les arcs rouges et une intégration le long de tous les arcs bleus dans le sens horaire. TRAVAIL ACCOMPLI!!!
Voici le lien GitHub vers mon code C ++
la source
L'approche de pixel-painting (comme suggéré par @Loadmaster) est supérieure à la solution mathématique de plusieurs manières:
Le seul inconvénient de la peinture au pixel est la précision finie de la solution. Mais cela peut être ajusté en effectuant simplement un rendu sur des toiles plus grandes ou plus petites selon la situation. Notez également que l' anti-aliasing dans le code de rendu 2D (souvent activé par défaut) donnera une précision supérieure au pixel. Ainsi, par exemple, rendre une figure 100x100 dans un canevas de mêmes dimensions devrait, je pense, donner une précision de l'ordre de 1 / (100 x 100 x 255) = .000039% ... ce qui est probablement "assez bon" pour tous sauf les problèmes les plus exigeants.
la source