J'ai un ensemble de points. Je veux les séparer en 2 ensembles distincts. Pour ce faire, je choisis deux points ( a et b ) et trace une ligne imaginaire entre eux. Maintenant, je veux avoir tous les points qui sont à gauche de cette ligne dans un ensemble et ceux qui sont à droite de cette ligne dans l'autre ensemble.
Comment puis-je savoir pour un point z donné s'il se trouve dans l'ensemble de gauche ou de droite? J'ai essayé de calculer l'angle entre azb - les angles inférieurs à 180 sont sur le côté droit, supérieurs à 180 sur le côté gauche - mais en raison de la définition d'ArcCos, les angles calculés sont toujours inférieurs à 180 °. Existe-t-il une formule pour calculer les angles supérieurs à 180 ° (ou toute autre formule pour choisir le côté droit ou gauche)?
la source
Réponses:
Utilisez le signe du déterminant des vecteurs
(AB,AM)
, oùM(X,Y)
est le point de requête:C'est
0
sur la ligne, et+1
d'un côté,-1
de l'autre côté.la source
positions
?Essayez ce code qui utilise un produit croisé :
Où a = point de ligne 1; b = point de ligne 2; c = point à vérifier.
Si la formule est égale à 0, les points sont colinéaires.
Si la ligne est horizontale, cela renvoie vrai si le point est au-dessus de la ligne.
la source
return (b.x - a.x)*(c.y - a.y) > (b.y - a.y)*(c.x - a.x);
, mais le compilateur optimise probablement cela de toute façon.Vous regardez le signe du déterminant de
Il sera positif pour les points d'un côté et négatif de l'autre (et nul pour les points sur la ligne elle-même).
la source
Le vecteur
(y1 - y2, x2 - x1)
est perpendiculaire à la ligne et pointe toujours vers la droite (ou toujours vers la gauche, si l'orientation de votre plan est différente de la mienne).Vous pouvez ensuite calculer le produit scalaire de ce vecteur et
(x3 - x1, y3 - y1)
déterminer si le point se trouve du même côté de la ligne que le vecteur perpendiculaire (produit scalaire>0
) ou non.la source
En utilisant l' équation de la ligne ab , obtenez la coordonnée x sur la ligne à la même coordonnée y que le point à trier.
la source
Vérifiez d'abord si vous avez une ligne verticale:
Ensuite, calculez la pente:
m = (y2-y1)/(x2-x1)
Ensuite, créer une équation de la droite en utilisant la forme de la pente du point:
y - y1 = m*(x-x1) + y1
. Par souci de mon explication, simplifier la forme pente à l' origine (pas nécessaire dans votre algorithme):y = mx+b
.Maintenant, branchez
(x3, y3)
pourx
ety
. Voici un pseudocode détaillant ce qui devrait se passer:la source
J'ai implémenté cela en java et exécuté un test unitaire (source ci-dessous). Aucune des solutions ci-dessus ne fonctionne. Ce code passe le test unitaire. Si quelqu'un trouve un test unitaire qui ne réussit pas, veuillez me le faire savoir.
Code: REMARQUE:
nearlyEqual(double,double)
renvoie vrai si les deux nombres sont très proches.Voici le test unitaire:
la source
En supposant que les points sont (Ax, Ay) (Bx, By) et (Cx, Cy), vous devez calculer:
(Bx - Axe) * (Cy - Ay) - (Par - Ay) * (Cx - Axe)
Cela sera égal à zéro si le point C est sur la ligne formée par les points A et B, et aura un signe différent selon le côté. De quel côté il s'agit dépend de l'orientation de vos coordonnées (x, y), mais vous pouvez insérer des valeurs de test pour A, B et C dans cette formule pour déterminer si les valeurs négatives sont à gauche ou à droite.
la source
Je souhaitais proposer une solution inspirée de la physique.
Imaginez une force appliquée le long de la ligne et vous mesurez le couple de la force autour du point. Si le couple est positif (sens antihoraire), le point est à la «gauche» de la ligne, mais si le couple est négatif, le point est la «droite» de la ligne.
Donc si le vecteur de force est égal à l'étendue des deux points définissant la ligne
vous testez le côté d'un point en
(px,py)
fonction du signe du test suivantla source
en gros, je pense qu'il existe une solution qui est beaucoup plus simple et directe, pour tout polygone donné, disons se composer de quatre sommets (p1, p2, p3, p4), trouver les deux sommets extrêmes opposés dans le polygone, dans un autre mots, trouvez par exemple le sommet le plus en haut à gauche (disons p1) et le sommet opposé qui est situé au plus en bas à droite (disons). Par conséquent, étant donné votre point de test C (x, y), vous devez maintenant faire une double vérification entre C et p1 et C et p4:
si cx> p1x AND cy> p1y ==> signifie que C est inférieur et à droite de p1 suivant si cx <p2x AND cy <p2y ==> signifie que C est supérieur et à gauche de p4
conclusion, C est à l'intérieur du rectangle.
Merci :)
la source
@ Réponse d'AVB en rubis
Si
det
est positif, c'est au-dessus, si négatif, c'est en dessous. Si 0, c'est sur la ligne.la source
Voici une version, toujours en utilisant la logique cross product, écrite en Clojure.
Exemple d'utilisation:
C'est-à-dire que le point (0, 10) est à gauche de la ligne déterminée par (-3, -1) et (3, 1).
REMARQUE: cette implémentation résout un problème qu'aucun des autres (jusqu'à présent) ne fait! L'ordre est important lorsque l'on attribue les points qui déterminent la ligne. C'est-à-dire que c'est une «ligne dirigée», dans un certain sens. Donc, avec le code ci-dessus, cet appel produit également le résultat de
true
:C'est à cause de cet extrait de code:
Enfin, comme pour les autres solutions basées sur des produits croisés, cette solution renvoie un booléen et ne donne pas de troisième résultat pour la colinéarité. Mais cela donnera un résultat qui a du sens, par exemple:
la source
Une autre façon de se faire une idée des solutions fournies par les filets est de comprendre quelques implications géométriques.
Soit pqr = [P, Q, R] des points qui forment un plan divisé en 2 côtés par la ligne [P, R] . Nous devons savoir si deux points du plan pqr , A, B, sont du même côté.
Tout point T sur le plan pqr peut être représenté avec 2 vecteurs: v = PQ et u = RQ, comme:
T '= TQ = i * v + j * u
Maintenant, les implications géométriques:
i+j: <0 0 <1 =1 >1 ---------Q------[PR]--------- <== this is PQR plane ^ pr line
En général,
Les autres significations géométriques de i et j (non liées à cette solution) sont:
La valeur de i, j peut être obtenue en résolvant les équations:
On nous donne donc 2 points, A, B sur le plan:
A = a1 * v + a2 * u B = b1 * v + b2 * u
Si A, B sont du même côté, ce sera vrai:
sign(a1+a2-1) = sign(b1+b2-1)
Notez que cela s'applique également à la question: A, B sont-ils du même côté du plan [P, Q, R] , dans lequel:
T = i * P + j * Q + k * R
et i + j + k = 1 implique que T est sur le plan [P, Q, R] et le signe de i + j + k-1 implique son côté. De cela, nous avons:
A = a1 * P + a2 * Q + a3 * R B = b1 * P + b2 * Q + b3 * R
et A, B sont du même côté du plan [P, Q, R] si
sign(a1+a2+a3-1) = sign(b1+b2+b3-1)
la source