¿Cómo puedo saber si un círculo y un rectángulo se cruzan en el espacio euclidiano 2D? (es decir, geometría 2D clásica)
192
¿Cómo puedo saber si un círculo y un rectángulo se cruzan en el espacio euclidiano 2D? (es decir, geometría 2D clásica)
Respuestas:
Solo hay dos casos cuando el círculo se cruza con el rectángulo:
Tenga en cuenta que esto no requiere que el rectángulo sea paralelo al eje.
(Una forma de ver esto: si ninguno de los bordes tiene un punto en el círculo (si todos los bordes están completamente "fuera" del círculo), entonces la única forma en que el círculo todavía puede intersecar el polígono es si se encuentra completamente dentro del polígono.)
Con ese conocimiento, algo así como el siguiente trabajo, en el que el círculo tiene centro
P
y el radioR
, y el rectángulo tiene vérticesA
,B
,C
,D
en ese orden (código no completa):Si está escribiendo alguna geometría, probablemente ya tenga las funciones anteriores en su biblioteca. De lo contrario,
pointInRectangle()
se puede implementar de varias maneras; cualquiera de los puntos generales en los métodos de polígono funcionará, pero para un rectángulo puede verificar si esto funciona:Y también
intersectCircle()
es fácil de implementar: una forma sería verificar si el pie de la perpendicular desdeP
la línea está lo suficientemente cerca y entre los puntos finales, y verificar los puntos finales de lo contrario.Lo bueno es que la misma idea funciona no solo para los rectángulos, sino también para la intersección de un círculo con cualquier polígono simple : ¡ni siquiera tiene que ser convexo!
fuente
Así es como lo haría:
Así es como funciona:
El primer par de líneas calcula los valores absolutos de la diferencia xey entre el centro del círculo y el centro del rectángulo. Esto colapsa los cuatro cuadrantes en uno, de modo que los cálculos no tienen que hacerse cuatro veces. La imagen muestra el área en la que ahora debe estar el centro del círculo. Tenga en cuenta que solo se muestra el cuadrante único. El rectángulo es el área gris, y el borde rojo delinea el área crítica que está exactamente a un radio de los bordes del rectángulo. El centro del círculo debe estar dentro de este borde rojo para que ocurra la intersección.
El segundo par de líneas elimina los casos fáciles donde el círculo está lo suficientemente lejos del rectángulo (en cualquier dirección) que no es posible ninguna intersección. Esto corresponde al área verde de la imagen.
El tercer par de líneas maneja los casos fáciles donde el círculo está lo suficientemente cerca del rectángulo (en cualquier dirección) que garantiza una intersección. Esto corresponde a las secciones naranja y gris de la imagen. Tenga en cuenta que este paso debe realizarse después del paso 2 para que la lógica tenga sentido.
Las líneas restantes calculan el caso difícil en el que el círculo puede intersecar la esquina del rectángulo. Para resolver, calcule la distancia desde el centro del círculo y la esquina, y luego verifique que la distancia no sea mayor que el radio del círculo. Este cálculo devuelve falso para todos los círculos cuyo centro está dentro del área sombreada roja y devuelve verdadero para todos los círculos cuyo centro está dentro del área sombreada blanca.
fuente
;)
circleDistance_x = abs(circle.x - (rect.x-rect.w/2)); circleDistance_y = abs(circle.y - (rect.y-rect.h/2));
Aquí hay otra solución que es bastante simple de implementar (y también bastante rápida). Capturará todas las intersecciones, incluso cuando la esfera haya entrado completamente en el rectángulo.
Con cualquier biblioteca matemática decente, eso se puede acortar a 3 o 4 líneas.
fuente
su esfera y rect se cruzan IIF
la distancia entre el centro del círculo y un vértice de su rect es menor que el radio de su esfera
O
la distancia entre el centro del círculo y un borde de su rect es menor que el radio de su esfera ( [ distancia punto-línea ])
O
el centro del círculo está dentro de la
distancia rect -punto-punto:
distancia punto-línea:
centro del círculo dentro del rectángulo:
tome un enfoque de eje separado: si existe una proyección en una línea que separa el rectángulo del punto, no se cruzan
proyecta el punto en líneas paralelas a los lados de su rectángulo y luego puede determinar fácilmente si se cruzan. si no se cruzan en las 4 proyecciones, ellos (el punto y el rectángulo) no pueden cruzarse.
solo necesita el producto interno (x = [x1, x2], y = [y1, y2], x * y = x1 * y1 + x2 * y2)
su prueba se vería así:
esto no asume un rectángulo alineado con el eje y es fácilmente extensible para probar intersecciones entre conjuntos convexos.
fuente
Esta es la solución más rápida:
Tenga en cuenta el orden de ejecución, y la mitad del ancho / alto se calcula previamente. También la cuadratura se realiza "manualmente" para guardar algunos ciclos de reloj.
fuente
La solución más simple que se me ocurrió es bastante sencilla.
Funciona al encontrar el punto en el rectángulo más cercano al círculo y luego comparar la distancia.
Puede hacer todo esto con algunas operaciones e incluso evitar la función sqrt.
¡Y eso es! La solución anterior supone un origen en la esquina superior izquierda del mundo con el eje x apuntando hacia abajo.
Si desea una solución para manejar las colisiones entre un círculo en movimiento y un rectángulo, es mucho más complicado y está cubierto por otra respuesta mía.
fuente
En realidad, esto es mucho más simple. Solo necesitas dos cosas.
Primero, necesitas encontrar cuatro ortogonales distancias desde el centro del círculo hasta cada línea del rectángulo. Entonces su círculo no se intersecará con el rectángulo si tres de ellos son más grandes que el radio del círculo.
En segundo lugar, debe encontrar la distancia entre el centro del círculo y el centro del rectángulo, luego el círculo no estará dentro del rectángulo si la distancia es mayor que la mitad de la longitud diagonal del rectángulo.
¡Buena suerte!
fuente
Aquí está mi código C para resolver una colisión entre una esfera y un cuadro alineado sin eje. Se basa en un par de rutinas de mi propia biblioteca, pero puede resultar útil para algunos. Lo estoy usando en un juego y funciona perfectamente.
fuente
Para visualizar, toma el teclado numérico de tu teclado. Si la tecla '5' representa su rectángulo, entonces todas las teclas 1-9 representan los 9 cuadrantes de espacio divididos por las líneas que forman su rectángulo (con 5 como el interior).
1) Si el centro del círculo está en el cuadrante 5 (es decir, dentro del rectángulo), las dos formas se cruzan.
Con eso fuera del camino, hay dos casos posibles: a) El círculo se cruza con dos o más bordes vecinos del rectángulo. b) El círculo se cruza con un borde del rectángulo.
El primer caso es simple. Si el círculo se cruza con dos bordes vecinos del rectángulo, debe contener la esquina que conecta esos dos bordes. (Eso, o su centro se encuentra en el cuadrante 5, que ya hemos cubierto. También tenga en cuenta que el caso donde el círculo se cruza con solo dos bordes opuestos del rectángulo también está cubierto).
2) Si alguna de las esquinas A, B, C, D del rectángulo se encuentra dentro del círculo, entonces las dos formas se cruzan.
El segundo caso es más complicado. Debemos tener en cuenta que solo puede ocurrir cuando el centro del círculo se encuentra en uno de los cuadrantes 2, 4, 6 u 8. (De hecho, si el centro está en cualquiera de los cuadrantes 1, 3, 7, 8, el la esquina correspondiente será el punto más cercano a ella).
Ahora tenemos el caso de que el centro del círculo está en uno de los cuadrantes de 'borde', y solo se cruza con el borde correspondiente. Luego, el punto en el borde que está más cerca del centro del círculo debe estar dentro del círculo.
3) Para cada línea AB, BC, CD, DA, construya líneas perpendiculares p (AB, P), p (BC, P), p (CD, P), p (DA, P) a través del centro del círculo P. Para cada línea perpendicular, si la intersección con el borde original se encuentra dentro del círculo, entonces las dos formas se cruzan.
Hay un atajo para este último paso. Si el centro del círculo está en el cuadrante 8 y el borde AB es el borde superior, el punto de intersección tendrá la coordenada y de A y B, y la coordenada x del centro P.
Puede construir las cuatro intersecciones de línea y verificar si se encuentran en sus bordes correspondientes, o averiguar en qué cuadrante P está y verificar la intersección correspondiente. Ambos deberían simplificarse a la misma ecuación booleana. Tenga cuidado de que el paso 2 anterior no descarta que P esté en uno de los cuadrantes de "esquina"; solo buscaba una intersección.
Editar: Resulta que he pasado por alto el simple hecho de que el n. ° 2 es un subcampo del n. ° 3 anterior. Después de todo, las esquinas también son puntos en los bordes. Consulte la respuesta de @ ShreevatsaR a continuación para obtener una gran explicación. Y mientras tanto, olvide el # 2 anterior a menos que desee una verificación rápida pero redundante.
fuente
Esta función detecta colisiones (intersecciones) entre Círculo y Rectángulo. Trabaja como el método e.James en su respuesta, pero este detecta colisiones para todos los ángulos de rectángulo (no solo en la esquina superior derecha).
NOTA:
¡aRect.origin.x y aRect.origin.y son coordenadas del ángulo inferior izquierdo del rectángulo!
¡aCircle.x y aCircle.y son coordenadas de Circle Center!
fuente
Tengo un método que evita las costosas pitágoras si no es necesario, es decir. al delimitar cuadros del rectángulo y el círculo no se cruzan.
Y también funcionará para los no euclidianos:
dLat=(lat-circleY); dLon=(lon-circleX); normed=dLat*dLat+dLon*dLon
. Por supuesto, si usa ese método normDist, tendrá que crear unanormedDist = dist*dist;
para el círculoVea el código completo de BBox y Circle de mi proyecto GraphHopper .
fuente
Creé clase para trabajar con formas espero que disfrutes
fuente
Aquí está el código modificado 100% funcionando:
Bassam Alugili
fuente
Aquí hay una prueba rápida de una línea para esto:
Este es el caso alineado con el eje donde
rect_halves
hay un vector positivo que apunta desde el rectángulo en el medio a una esquina. La expresión dentrolength()
es un vector delta desdecenter
un punto más cercano en el rectángulo. Esto funciona en cualquier dimensión.fuente
Es eficiente porque:
fuente
funcionó para mí (solo funciona cuando el ángulo del rectángulo es 180)
fuente
Mejorando un poco la respuesta de e.James:
Esto resta
rect.w / 2
yrect.h / 2
una vez en lugar de hasta tres veces.fuente
Para aquellos que tienen que calcular la colisión de Círculo / Rectángulo en Coordenadas Geográficas con SQL,
esta es mi implementación en el oráculo 11 del algoritmo sugerido por e.James .
En la entrada requiere coordenadas circulares, radio circular en km y dos coordenadas de vértices del rectángulo:
fuente
Funciona, lo descubrí hace una semana, y ahora me puse a probarlo.
fuente
fuente
Suponiendo que tiene los cuatro bordes del rectángulo, verifique la distancia desde los bordes hasta el centro del círculo, si es menor que el radio, entonces las formas se cruzan.
fuente
Si el rectángulo se cruza con el círculo, uno o más puntos de esquina del rectángulo deben estar dentro del círculo. Supongamos que los cuatro puntos de un rectángulo son A, B, C, D. al menos uno de ellos debe cruzar el círculo. entonces, si la distancia desde un punto al centro del círculo es menor que el radio del círculo, debe intersecar el círculo. Para obtener la distancia puedes usar el teorema de Pitágoras,
Esta técnica tiene algunos límites. Pero funcionará mejor para los desarrolladores de juegos. especialmente detección de colisiones
Es una buena actualización del algoritmo de Arvo.
fuente