Tengo un conjunto de puntos. Quiero separarlos en 2 conjuntos distintos. Para hacer esto, elijo dos puntos ( a y b ) y dibujar una línea imaginaria entre ellos. Ahora quiero tener todos los puntos que quedan de esta línea en un conjunto y los que están directamente desde esta línea en el otro conjunto.
¿Cómo puedo saber para un punto dado z si está en el conjunto izquierdo o derecho? Traté de calcular el ángulo entre azb (los ángulos menores que 180 están en el lado derecho, mayores que 180 en el lado izquierdo), pero debido a la definición de ArcCos, los ángulos calculados siempre son menores que 180 °. ¿Existe una fórmula para calcular ángulos mayores de 180 ° (o alguna otra fórmula para elegir el lado derecho o izquierdo)?
c#
math
geometry
convex-hull
Aaginor
fuente
fuente
Respuestas:
Use el signo del determinante de vectores
(AB,AM)
, dondeM(X,Y)
está el punto de consulta:Está
0
en la línea, y+1
en un lado,-1
en el otro lado.fuente
positions
?Pruebe este código que hace uso de un producto cruzado :
Donde a = línea punto 1; b = punto de línea 2; c = punto para verificar.
Si la fórmula es igual a 0, los puntos son colineales.
Si la línea es horizontal, esto devuelve verdadero si el punto está por encima de la línea.
fuente
return (b.x - a.x)*(c.y - a.y) > (b.y - a.y)*(c.x - a.x);
, pero el compilador probablemente lo optimice de todos modos.Miras el signo del determinante de
Será positivo para los puntos en un lado y negativo en el otro (y cero para los puntos en la línea misma).
fuente
El vector
(y1 - y2, x2 - x1)
es perpendicular a la línea y siempre apunta a la derecha (o siempre apunta a la izquierda, si la orientación de su plano es diferente a la mía).Luego puede calcular el producto de punto de ese vector y
(x3 - x1, y3 - y1)
determinar si el punto se encuentra en el mismo lado de la línea que el vector perpendicular (producto de punto>0
) o no.fuente
Usando la ecuación de la línea ab , obtenga la coordenada x en la línea en la misma coordenada y que el punto a ordenar.
fuente
Primero verifique si tiene una línea vertical:
Luego, calcule la pendiente:
m = (y2-y1)/(x2-x1)
A continuación, crear una ecuación de la línea utilizando la forma pendiente punto:
y - y1 = m*(x-x1) + y1
. Por el bien de mi explicación, simplifíquelo a la forma de pendiente-intercepción (no es necesario en su algoritmo):y = mx+b
.Ahora conecte
(x3, y3)
parax
yy
. Aquí hay un pseudocódigo que detalla lo que debería suceder:fuente
Implementé esto en Java y ejecuté una prueba unitaria (fuente a continuación). Ninguna de las soluciones anteriores funciona. Este código pasa la prueba de la unidad. Si alguien encuentra una prueba unitaria que no pasa, hágamelo saber.
Código: NOTA:
nearlyEqual(double,double)
devuelve verdadero si los dos números están muy cerca.Aquí está la prueba de la unidad:
fuente
Suponiendo que los puntos son (Ax, Ay) (Bx, By) y (Cx, Cy), debe calcular:
(Bx - Hacha) * (Cy - Ay) - (Por - Ay) * (Cx - Hacha)
Esto será igual a cero si el punto C está en la línea formada por los puntos A y B, y tendrá un signo diferente dependiendo del lado. De qué lado es esto depende de la orientación de sus coordenadas (x, y), pero puede insertar valores de prueba para A, B y C en esta fórmula para determinar si los valores negativos están a la izquierda o a la derecha.
fuente
Quería proporcionar una solución inspirada en la física.
Imagina una fuerza aplicada a lo largo de la línea y estás midiendo el torque de la fuerza sobre el punto. Si el par es positivo (en sentido antihorario), entonces el punto está a la "izquierda" de la línea, pero si el par es negativo, el punto está a la "derecha" de la línea.
Entonces, si el vector de fuerza es igual al lapso de los dos puntos que definen la línea
prueba el lado de un punto en
(px,py)
función del signo de la siguiente pruebafuente
Básicamente, creo que hay una solución que es mucho más fácil y directa, para cualquier polígono dado, digamos que consisten en cuatro vértices (p1, p2, p3, p4), encontrar los dos vértices opuestos extremos en el polígono, en otro palabras, encuentre, por ejemplo, el vértice superior izquierdo (digamos p1) y el vértice opuesto que se encuentra en la parte inferior derecha (digamos). Por lo tanto, dado su punto de prueba C (x, y), ahora debe hacer una doble verificación entre C y p1 y C y p4:
if cx> p1x AND cy> p1y ==> significa que C es inferior y a la derecha de p1 siguiente si cx <p2x AND cy <p2y ==> significa que C es superior y a la izquierda de p4
conclusión, C está dentro del rectángulo.
Gracias :)
fuente
La respuesta de @ AVB en rubí
Si
det
es positivo es arriba, si es negativo es abajo. Si 0, está en la línea.fuente
Aquí hay una versión, nuevamente usando la lógica de productos cruzados, escrita en Clojure.
Ejemplo de uso:
Es decir que el punto (0, 10) está a la izquierda de la línea determinada por (-3, -1) y (3, 1).
NOTA: ¡Esta implementación resuelve un problema que ninguno de los otros (hasta ahora) hace! El orden importa al dar los puntos que determinan la línea. Es decir, es una "línea dirigida", en cierto sentido. Entonces, con el código anterior, esta invocación también produce el resultado de
true
:Eso se debe a este fragmento de código:
Finalmente, como con las otras soluciones basadas en productos cruzados, esta solución devuelve un valor booleano y no da un tercer resultado para la colinealidad. Pero dará un resultado que tiene sentido, por ejemplo:
fuente
Una forma alternativa de tener una idea de las soluciones proporcionadas por los netters es comprender algunas implicaciones de la geometría.
Supongamos que pqr = [P, Q, R] son puntos que forman un plano dividido en 2 lados por la línea [P, R] . Debemos averiguar si dos puntos en pqr plano , A, B, están en el mismo lado.
Cualquier punto T en el plano pqr puede representarse con 2 vectores: v = PQ yu = RQ, como:
T '= TQ = i * v + j * u
Ahora las implicaciones de la geometría:
i+j: <0 0 <1 =1 >1 ---------Q------[PR]--------- <== this is PQR plane ^ pr line
En general,
Los otros significados geométricos de i y j (no relacionados con esta solución) son:
El valor de i, j se puede obtener resolviendo las ecuaciones:
Entonces se nos dan 2 puntos, A, B en el avión:
A = a1 * v + a2 * u B = b1 * v + b2 * u
Si A, B están del mismo lado, esto será cierto:
sign(a1+a2-1) = sign(b1+b2-1)
Tenga en cuenta que esto también se aplica a la pregunta: ¿Están A, B en el mismo lado del plano [P, Q, R] , en el que:
T = i * P + j * Q + k * R
e i + j + k = 1 implica que T está en el plano [P, Q, R] y el signo de i + j + k-1 implica su lateralidad. De esto tenemos:
A = a1 * P + a2 * Q + a3 * R B = b1 * P + b2 * Q + b3 * R
y A, B están en el mismo lado del plano [P, Q, R] si
sign(a1+a2+a3-1) = sign(b1+b2+b3-1)
fuente