Étant donné deux polygones:
POLYGON((1 0, 1 8, 6 4, 1 0))
POLYGON((4 1, 3 5, 4 9, 9 5, 4 1),(4 5, 5 7, 6 7, 4 4, 4 5))
Comment puis-je calculer l'union (polygone combiné)?
Exemple de Dave utilise SQL Server pour produire l'union, mais je dois accomplir la même chose dans le code. Je cherche une formule mathématique ou un exemple de code dans n'importe quelle langue qui expose les mathématiques réelles. Je tente de produire des cartes qui combinent les pays de manière dynamique en régions. J'ai posé une question connexe ici: Regroupement des formes géographiques
C'est une très bonne question. J'ai implémenté le même algorithme sur c # il y a quelque temps. L’algorithme construit un contour commun de deux polygones (c’est-à-dire construit une union sans trous). C'est ici.
Entrée: premier polygone (n points), deuxième polygone (m points). Sortie: graphique. Sommet - polygone du point d'intersection.
Nous devrions trouver des intersections. Parcourez tous les côtés des polygones des deux polygones [O (n * m)] et recherchez les intersections.
Si aucune intersection n’est trouvée, ajoutez simplement des sommets et connectez-les.
Si des intersections sont trouvées, classez-les par longueur en fonction de leur point de départ, ajoutez tous les sommets (Début, fin et intersections) et connectez-les (déjà dans Ordre trié) au bord .
Si nous n'avons trouvé aucun point d'intersection lors de la création du graphique, l'une des conditions suivantes est remplie:
Trouvez les coordonnées x et y minimales (minx, miny). Trouvez ensuite la distance minimale entre (minx, miny) et les points du polygone. Ce point sera le point en bas à gauche.
Nous commençons à parcourir le graphique à partir du point inférieur gauche et continuons jusqu'à ce que nous y revenions. Au début, nous marquons tous les bords comme non visités. À chaque itération, vous devez sélectionner le point suivant et le marquer comme visité.
Pour choisir le point suivant, choisissez un bord avec un angle interne maximal dans le sens anti-horaire.
Je calcule deux vecteurs: vector1 pour Edge actuel et vector2 pour chaque prochain Edge non visité (comme présenté dans l'image).
Pour les vecteurs, je calcule:
En conséquence, je reçois un bord (et un sommet suivant correspondant) avec l'angle maximum.
J'ajoute à la liste des résultats chaque sommet passé. La liste de résultats est le polygone d'union .
Vous devez déterminer quels points se trouvent à l’intérieur . Après avoir supprimé ces points, vous pouvez insérer un ensemble de points "extérieurs" dans l'autre. Vos points d’insertion (par exemple, où la flèche dans l’image est à droite) sont ceux où vous avez dû supprimer des points des jeux d’entrée.
Bonne question! Je n'ai jamais tenté cela auparavant, mais je vais tenter le coup maintenant.
Premièrement: vous devez savoir où ces deux formes se chevauchent. Pour ce faire, vous pouvez examiner chaque bord du polygone A et voir où il se croise, ainsi que le contour du polygone B. Dans cet exemple, il devrait y avoir deux points d'intersection.
Ensuite: Créez la forme de l'union. Vous pouvez prendre tous les sommets dans A et B, ainsi que les points d'intersection, puis exclure les sommets contenus dans la forme finale. Pour trouver ces points, il semble que vous puissiez trouver n'importe quel sommet de A situé à l'intérieur de B et tout sommet de B situé à l'intérieur de A.
Essayez gpc .
Une solution que j'ai vue en utilisant des arbres BSP est décrite ici .
Fondamentalement, il décrit l'intersection en termes d'une union des arêtes du polygone A qui sont à l'intérieur du polygone B (y compris les arêtes partielles et calculées à l'aide de BSP tree ). Ensuite, vous pouvez définir A/B comme ~ (~UNE/\~B), où ~ désigne l’inversion du polygone,/indique l’union et/\ désigne l’intersection.
En regroupant les pays, j'espère qu'il n'y aura pas de chevauchement - vous pourriez utiliser un algorithme assez naïf qui recherche les sommets partagés - une vue simple consisterait à parcourir les points d'un polygone, en vérifiant s'il en existe un autre , et partage le même point suivant ou précédent pour voir s’il existe une correspondance. Ensuite, supprimez simplement le sommet partagé pour créer votre union.
Il me fallait aujourd'hui résoudre le même problème et trouver la solution avec cette librairie: http://www.cs.man.ac.uk/~toby/alan/software/ .
Il a beaucoup d'implémentations de langage la liste ici incluant Java, Obj-C, C #, Lua, python et plus.
J'ai fait face au même problème et j'ai résolu le problème en utilisant la méthode suivante
Enveloppe Cython pour la traduction en C++ de la bibliothèque Clipper d’Angus Johnson (ver. 6.4.2) https://github.com/fonttools/pyclipper
pc = pyclipper.Pyclipper()
def get_poly_union(polygons):
pc.AddPaths(polygons, pyclipper.PT_SUBJECT, True)
solution = pc.Execute(pyclipper.CT_UNION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO)
return solution[0]
print_image = image.copy()
solution = get_poly_union(polygons_array)
#polygons_array=[polygon,polygon,polygon, ...,polygon] and polygon=[point,point,point...,point]
cv2.drawContours(print_image, [np.asarray(solution)], -1, (0, 255, 0), 2)
plt.imshow(print_image)
C'est une question très ancienne mais Union_ function de Boost a fonctionné pour moi.
Voir cet extrait ci-dessous:
#include <iostream>
#include <vector>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/foreach.hpp>
int main()
{
typedef boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > polygon;
polygon green, blue;
boost::geometry::read_wkt(
"POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))", green);
boost::geometry::read_wkt(
"POLYGON((5 5, 5 15, 15 15, 15 5, 5 5))", blue);
std::vector<polygon> output;
boost::geometry::union_(green, blue, output);
int i = 0;
std::cout << "green || blue:" << std::endl;
BOOST_FOREACH(polygon const& p, output)
{
std::cout << i++ << ": " << boost::geometry::area(p) << std::endl;
for (int i = 0; i < p.outer().size(); i++)
{
std::cout << p.outer().at(i).x() << " " << p.outer().at(i).y() << std::endl;
}
}
return 0;
}