Comment faire pour déterminer si une liste de polygones points sont dans le sens horaire?
Avoir une liste de points, comment savoir si ils sont dans le sens horaire?
Par exemple:
point[0] = (5,0)
point[1] = (6,4)
point[2] = (4,5)
point[3] = (1,5)
point[4] = (1,0)
dirais qu'il est anti-horaire (ou l'inverse, pour certaines personnes).
- VEUILLEZ NOTER: La accepté de répondre, et beaucoup de réponses après elle, ont besoin de beaucoup d'additions et de multiplications (ils sont basés sur des calculs de la zone cette fin, positif ou négatif; par exemple, "lacet formule"). Avant de mettre en œuvre l'un de ces, envisagez de de lhf réponse, ce qui est plus simple/rapide basé sur wiki - orientation de la simple polygone.
- Je pense toujours en termes de produit vectoriel de deux vecteurs adjacents. Si je marche autour du périmètre du polygone ma tête les points de sortie de l'avion. Je traverse le plan de vecteur dans ma marche vecteur de direction pour obtenir la troisième direction dans mon système de coordonnées. Si ce vecteur de points, de sorte que l'intérieur est sur ma gauche c'est dans le sens antihoraire; si l'intérieur est à ma droite, c'est dans le sens horaire.
Vous devez vous connecter pour publier un commentaire.
Certaines des méthodes proposées échoue dans le cas d'un non-polygone convexe, comme un croissant. Voici un exemple simple qui va travailler avec des non-polygones convexes (il va même travailler avec une auto-intersection polygone comme une figure-huit, en vous disant que c'est surtout dans le sens horaire).
Somme sur les bords, (x2 − x1)(o2 + y1). Si le résultat est positif, la courbe est dans le sens horaire, si il est négatif, la courbe est dans le sens antihoraire. (Le résultat est le double de la zone fermée, avec un +/- de la convention.)
Sum( (x[(i+1) mod N] - x[i]) * (y[i] + y[(i+1) mod N]) )
pour i = 0 à N-1. I. e., doit prendre l'indice Modulo N (N ≡ 0
) La formule ne fonctionne que pour les fermé polygones. Les polygones ont pas imaginaire bords.x<sub>i + 1</sub>*y<sub>i</sub> - x<sub>i</sub>*y<sub>i + 1</sub>
pour déterminer la réponse.point[0] = 0,5 (5-0)(0+5) = 25, point[1] = 5,0 (10-5)(5+0) = 25, point[2] = 10,5 (5-10)(5+10) = -75, point[3] = 5,10 (0-5)(10+5) = -75
== -100. COMPTOIR du DIAMANT:point[0] = 0,5 (5-0)(5+10) = 75, point[1] = 5,10 (10-5)(10+5) = 75, point[2] = 10,5 (5-10)(5+0) = -25, point[3] = 5,0 (0-5)(5+0) = -25
== +100 Est-ce un cas particulier?(point.x + nextPoint.x) * (point.y - nextPoint.y)
.La la croix du produit mesure le degré de la perpendiculaire-ness de deux vecteurs. Imaginez que chaque bord de votre polygone est un vecteur dans le plan x-y de un à trois dimensions (3-D) de l'espace xyz. Alors le produit vectoriel de deux successives bords est un vecteur dans la direction z, (z positif la direction, si le second segment est dans le sens horaire, moins z-direction, si c'est dans le sens antihoraire). L'ampleur de ce vecteur est proportionnelle au sinus de l'angle entre les deux bords, de sorte qu'il atteint un maximum quand ils sont perpendiculaires, et s'estompe pour disparaître lorsque les bords sont colinéaires (parallèle).
Donc, pour chaque vertex (point) du polygone, calculer la croix-produit de l'ampleur des deux bords contigus:
Donc étiqueter les bords de façon consécutive comme
edgeA
est le segment depoint0
àpoint1
etedgeB
entrepoint1
àpoint2
...
edgeE
est entrepoint4
etpoint0
.Alors le Sommet A (
point0
) est entreedgeE
[Depoint4
àpoint0
]edgeA
[Depoint0
à "point1'Ces deux bords sont eux-mêmes des vecteurs, dont les coordonnées x et y peut être déterminé en soustrayant les coordonnées de leurs points de début et fin:
edgeE
=point0
-point4
=(1, 0) - (5, 0)
=(-4, 0)
edgeA
=point1
-point0
=(6, 4) - (1, 0)
=(5, 4)
etEt le produit vectoriel de ces deux bords contigus est calculé en utilisant le déterminant de la matrice suivante, qui est construit en mettant les coordonnées des deux vecteurs ci-dessous les symboles représentant les trois axes des coordonnées (
i
,j
, &k
). La troisième (zéro)-valeur de coordonnées est là parce que la croix concept de produit est un 3-D de construire, et donc, nous prolongeons ces 2-D vecteurs en 3-D afin d'appliquer le produit croisé:Étant donné que tous les produits de produire un vecteur perpendiculaire au plan des deux vecteurs étant multipliés, le déterminant de la matrice ci-dessus n'a qu'une
k
, (ou de l'axe z) du composant.La formule pour le calcul de l'ampleur de la
k
ou composant axe z esta1*b2 - a2*b1 = -4* 4 - 0* 1
=-16
L'ampleur de cette valeur (
-16
), est une mesure du sinus de l'angle entre les 2 vecteurs d'origine, multiplié par le produit de la grandeur de l'2 vecteurs.En fait, une autre formule pour sa valeur est
A X B (Cross Product) = |A| * |B| * sin(AB)
.Donc, pour en revenir à seulement une mesure de l'angle que vous avez besoin de diviser cette valeur, (
-16
), par le produit des grandeurs de ces deux vecteurs.|A| * |B|
=4 * Sqrt(17)
=16.4924...
De sorte que la mesure de sin(AB) =
-16 /16.4924
=-.97014...
C'est une mesure de savoir si le segment suivant après le sommet est courbé vers la gauche ou la droite, et de combien. Il n'y a pas besoin de prendre de l'arc-sinus. Tout ce que nous ne se soucient est son ampleur, et bien sûr, son signe (positif ou négatif)!
Le faire pour chacun des 4 autres points autour de la trajectoire fermée, et additionner les valeurs de ce calcul à chaque sommet..
Si la somme finale est positive, vous êtes allé dans le sens horaire, négatif, dans le sens antihoraire.
Je suppose que c'est une très vieille question, mais je vais jeter une autre solution de toute façon, parce que c'est simple et pas mathématiquement intensif - il utilise juste de base de l'algèbre. Calculer la signature de l'aire du polygone. Si il est négatif, les points sont dans le sens horaire, si elle est positive, ils sont dans le sens antihoraire. (Ceci est très similaire à la Bêta de la solution).
Calculer la signature de la zone:
A = 1/2 * (x1*y2 - x2*y1 + x2*y3 - x3*y2 + ... + xn*y1 - x1*yn)
Ou en pseudo-code:
Noter que si vous êtes la seule vérification de la commande, vous n'avez pas besoin de s'embêter en le divisant par 2.
Sources: http://mathworld.wolfram.com/PolygonArea.html
previousPoint
pour la prochaine itération. Avant de commencer la boucle, un jeu depreviousPoint
à la matrice du dernier point. Compromis est variable locale supplémentaires copie, mais de moins en moins accès à des tableaux. Et surtout, ne touchez pas à l'entrée de tableau.Trouver le sommet avec le plus petit y (et les plus grands de x s'il existe des liens). Laissez le vertex être
A
et le précédent sommet de la listeB
et le sommet suivant dans la listeC
. Maintenant calculer la signe de la croix de produits deAB
etAC
.Références:
Comment puis-je trouver de l'orientation d'un simple polygone? dans
Foire aux Questions: comp.les graphiques.les algorithmes de.
La courbe de l'orientation sur Wikipédia.
O(1)
solution. Toutes les autres réponses rendementO(n)
solutions pourn
le nombre de polygone points. Pour encore plus profond des optimisations, voir la Considérations Pratiques paragraphe de Wikipedia est fantastique Courbe d'orientation l'article.O(1)
seulement si A ce polygone est convexe (dans ce cas, n'importe quel sommet se trouve sur l'enveloppe convexe, et donc suffit) ou B vous savez déjà le sommet avec la plus petite coordonnée Y de la. Si c'est pas dans le cas (c'est à dire, ce polygone est non-convexe et vous ne savez rien à ce sujet), unO(n)
de recherche est nécessaire. Depuis pas de sommation est nécessaire, cependant, c'est toujours beaucoup plus rapide que toute autre solution pour de simples polygones.Ici est un simple C# de mise en œuvre de l'algorithme basé sur cette réponse.
Supposons que nous avons un
Vector
type ayantX
etY
les propriétés de typedouble
.%
est le modulo ou de ce qui reste de l'opérateur effectuant le modulo qui (selon Wikipedia) trouve le reste après la division d'un nombre par un autre.Commencer à l'un des sommets, et de calculer l'angle sous-tendu par chaque côté.
Le premier et le dernier sera égal à zéro (donc ignorer ces); pour le reste, le sinus de l'angle sera donné par le produit vectoriel des normalisations pour unité de longueur de (point de[n] point[0]) et (point[n-1] point[0]).
Si la somme des valeurs est positif, alors votre polygone est dessiné dans le sens anti-horaire sens.
Pour ce qu'il vaut, j'ai utilisé ce mixin pour calculer la dissolution de l'ordre pour l'API Google Maps v3 apps.
Le code de démultiplier les effets secondaires de polygone domaines: l'une dans le sens des aiguilles d'enroulement afin de sommets positive alors qu'une des aiguilles d'une montre à remontage afin de les mêmes sommets produit la même zone comme une valeur négative. Le code utilise aussi une sorte d'API privée dans le Google Maps de la géométrie de la bibliothèque. Je me sentais à l'aise de l'utiliser - utiliser à vos propres risques.
Exemple d'utilisation:
Exemple complet avec les tests unitaires @ http://jsfiddle.net/stevejansen/bq2ec/
De mise en œuvre de Sean répondre en JavaScript:
JS:
Assez sûr de ce qui est juste. Il semble être au travail 🙂
Ces polygones ressembler à ceci, si vous vous demandez:
C'est la mise en œuvre de la fonction de OpenLayers 2. La condition pour avoir un polygone dans le sens des aiguilles est
area < 0
, il a confirmé par cette référence.Si vous utilisez Matlab, la fonction
ispolycw
retourne true si le polygone de sommets sont dans le sens horaire.Comme il est expliqué dans cet article de Wikipédia La courbe de l'orientation, 3 points
p
,q
etr
sur le plan (c'est à dire avec des coordonnées x et y), vous pouvez calculer le signe de la suivante déterminantSi le déterminant est négatif (c'est à dire
Orient(p, q, r) < 0
), alors le polygone est orientée dans le sens horaire (CW). Si le déterminant est positif (c'est à direOrient(p, q, r) > 0
), le polygone est orientée dans le sens antihoraire (CCW). Le déterminant est égal à zéro (c'est à direOrient(p, q, r) == 0
) si les pointsp
,q
etr
sont colinéaires.Dans la formule ci-dessus, on ajoute celles en face de l'coordonnées de
p
,q
etr
parce que nous sommes à l'aide de homogène coordonnées.Je pense que pour certains points dans le sens des aiguilles toutes les arêtes doivent être positifs, non seulement la somme des bords. Si une arête est plus négative que d'au moins 3 points sont donnés dans le sens antihoraire.
Mon C# /LINQ solution est basée sur la croix, avis sur des produits de @charlesbretana est ci-dessous. Vous pouvez spécifier une référence normale pour le remontage. Il devrait fonctionner aussi longtemps que la courbe est la plupart du temps dans le plan défini par le vecteur up.
avec un test unitaire
C'est ma solution à l'aide des explications dans les autres réponses:
Beaucoup de calcul méthode plus simple, si vous connaissez déjà un point à l'intérieur du polygone:
Choisir n'importe quel segment de ligne à partir de l'original de polygones, points et leurs coordonnées dans l'ordre.
Ajouter un connu "à l'intérieur" point de, et de former un triangle.
Calculer CW ou CCW, comme l'a suggéré ici avec ces trois points.
Après l'essai de plusieurs fiables implémentations de l'algorithme qui a fourni des résultats satisfaisants concernant la CW/CCW orientation de la boîte a été l'un, publié par les OP dans cette fil (
shoelace_formula_3
).Comme toujours, un nombre positif représente un CW orientation, alors que d'un nombre négatif CCW.
Voici swift 3.0 solution basée sur les réponses ci-dessus:
Une autre solution pour cela;
Prendre tous les sommets comme un tableau comme ceci;
Solution pour R pour déterminer la direction et l'inverse si des aiguilles d'une montre (jugé nécessaire pour owin objets):
Bien que ces réponses sont correctes, ils sont plus mathématiquement complexes que nécessaire. Assumer les coordonnées de carte, où la plupart des nord-point est le point le plus haut sur la carte. Trouver plus de north point, et si les 2 points de la cravate, c'est le plus au nord, puis plus à l'est (c'est le point que lhf utilise dans sa réponse). Dans vos points,
point[0] = (5,0)
point[1] = (6,4)
point[2] = (4,5)
point[3] = (1,5)
point[4] = (1,0)
Si nous supposons que P2 est la plus au nord puis à l'est point le précédent ou suivant le point de déterminer, dans le sens horaire CW ou CCW. Depuis la plupart des nord-est sur la face nord, si P1 (précédent) pour P2 se déplace de l'est, la direction est à la CW. Dans ce cas, il se déplace à l'ouest, de sorte que la direction est à GAUCHE que l'on a accepté la réponse dit. Si le point précédent n'a pas de mouvement horizontal, puis le même système s'applique pour le point suivant, P3. Si P3 est à l'ouest de P2, il est, alors le mouvement est CCW. Si la P2 à P3 mouvement est à l'est, c'est-ouest dans ce cas, le mouvement est CW. Supposons que nte, P2 dans vos données, est la plus au nord puis à l'est point et le prv est le point précédent, P1 dans vos données, et nxt est le point suivant, le P3 de vos données, et [0] est à l'horizontale ou est/ouest, où l'ouest est inférieure à l'est, et [1] est à la verticale.
.x
et.y
d'une struct, au lieu de[0]
et[1]
. Je ne savais pas ce que votre code a été de dire, la première fois j'ai jeté un coup d'oeil à elle.)De code C# pour mettre en œuvre lhf réponse:
trouver le centre de masse de ces points.
supposons qu'il y a des lignes de ce point de vos points.
trouver l'angle entre les deux lignes pour line0 line1
que faire pour ligne1 et ligne2
...
...
si cet angle est de plus en plus monotone que c'est dans le sens antihoraire ,
d'autre si monotone décroissante, c'est dans le sens des aiguilles
d'autre (il n'est pas monotonical)
vous ne pouvez pas décider, de sorte qu'il n'est pas sage