python graphics geometry intersection

python - Intersección de Ray y cuadrado/rectángulo en 3D



graphics geometry (3)

Hei. Están haciendo un juego y están buscando una intersección de rayos en un cuadrado o un rectángulo solo en el espacio 3D. Busqué en la web y encontré muchas soluciones, pero nada de lo que puedo entender tiene un guión de intersección de segmentos de línea y línea en 2D, pero no puedo imaginarlo para hacerlo en 3D. No es importante desde qué lado se cruza con el cuadrado o rectángulo pero debe poder recuperar el punto del vector de intersección para que luego se pueda probar la distancia a se si ocurrió antes o después de otras intersecciones en la misma intersección de rayos.

Cualquier ejemplo en python u otros lenguajes de scripting similares será muy apreciado

Editar : No se debe modificar el 2D para mostrar un exaple, pero se hizo un nuevo y se publicaron ambos.

//this is the exaple it test a ray onto a plane then look to se if that point is in the rectangle and saves it to test for distanse later list Faces; //triangle faces list Points; // vector FindPoint(){ //calcute the point of intersection onto the plane and returns it //if it can intersect //else return ZERO_VECTOR } integer point-in-quadrilateral(){ //return 1 if the point is in the rectangular on the plane //else return 0 } default{ state_entry(){ integer n = (Faces != []); //return number of elements integer x = 0; while(x < n){ vector intersection = FindPoint( FromList(Faces, x) ); //take out a element and runs it trough the function if(intersection != ZERO_VECTOR){ integer test = point-in-quadrilateral( FromList(Faces, x) ); //find out if the point is in rectangular if(test == 1){ //if so Points += intersection; //save the point } } ++x; } float first; //the distanse to the box intersection integer l = (Points != []); integer d; while(d < l){ if(Dist( FromList(Points, d) ) < first) //if the new distanse is less then first return 0; //then end script ++d; } } } //this is the 2D version vector lineIntersection(vector one, vector two, vector three, vector four){ float bx = two.x - one.x; float by = two.y - one.y; float dx = four.x - three.x; float dy = four.y - three.y; float b_dot_d_perp = bx*dy - by*dx; if(b_dot_d_perp == 0.0) { return ZERO_VECTOR; } float cx = three.x-one.x; float cy = three.y-one.y; float t = (cx*dy - cy*dx) / b_dot_d_perp; if(LineSeg){ //if true tests for line segment if((t < 0.0) || (t > 1.0)){ return ZERO_VECTOR; } float u = (cx * by - cy * bx) / b_dot_d_perp; if((u < 0.0) || (u > 1.0)) { return ZERO_VECTOR; } } return <one.x+t*bx, one.y+t*by, 0.0>;

}


Crea una ecuación vectorial para una línea en R3, luego resuelve la intersección de esa línea en el plano del rectángulo con el que lo estás probando. Después de eso, es lo suficientemente simple como para probar si ese punto de solución se encuentra dentro de los límites.

el parámetro t de la solución se puede encontrar con:

t = (a * (x0 - rx) + b * (y0 - ry) + c * (x0 - rz)) / (a * vx + b * vy + c * vz)

dónde:

a(x - x0) + b(y - y0) + c(z - z0) = 0

es la ecuación del plano en el que se encuentra tu rectángulo

y:

<x, y, z> = <rx + vx * t, ry + vy * t, rz + vz * t>

es la ecuación vectorial de la línea en cuestión.

tenga en cuenta que:

<rx, ry, rz>

es el punto inicial de la ecuación del vector, y

<vx, vy, vz>

es el vector de dirección de la ecuación anterior

Después de eso, conectar el parámetro t en su ecuación vectorial le dará el punto para probar la distancia.


La solución es muy fácil cuando defines un rayo con un punto (= vector) y un vector de dirección, y el rectángulo con un punto (= vector) y dos vectores que representan los lados.

Supongamos que el rayo se define como R0 + t * D , donde R0 es el origen del rayo, D es un vector unitario que representa su dirección t es su longitud.

El rectángulo se puede representar con un punto de esquina P0 , y dos vectores S1 y S2 que deben representar los lados (su longitud es igual a la longitud de los lados). Necesitarás otro vector N normal a su superficie, que es igual al vector unitario a lo largo del producto cruzado de S1 y S2 .

Ahora, supongamos que el rayo se cruza con el rect en P Entonces, la dirección del rayo, D debe formar un ángulo distinto de cero con el N normal. Esto puede verificarse marcando DN < 0 .

Para encontrar el punto de intersección, suponga P = R0 + a * D (el punto debe estar en el rayo). Necesitas encontrar el valor de a Encuentra el vector P0P . Esto debe ser perpendicular a N , lo que significa P0P.N = 0 que se reduce a a = ((P0 - R0).N) / (DN) .

Ahora necesita verificar si el punto está dentro del rect o no. Para hacer esto, tome la proyección Q1 de P0P largo de S1 y Q2 de P0P largo de S2 . La condición para que el punto esté dentro es entonces 0 <= length(Q1) <= length(S1) y 0 <= length(Q2) <= length(S2) .

Este método es apropiado para cualquier tipo de paralelogramos, no solo para rectángulos.


No dice si el cuadrado / rectángulo en 3D está alineado con los ejes de coordenadas o no. Suponiendo que el rectángulo 3D R está orientado arbitrariamente en el espacio, aquí hay un método. Primero, inserte su rayo r con el plano que contiene R. Esto se puede lograr requiriendo un factor de escala s para multiplicar r y colocarlo en el plano de R , y resolver para s . Esto te da un punto p en el avión. Ahora proyecta el plano, y R y p , en uno de los planos de coordenadas { xy , yz , zx }. Solo debe evitar proyectarse perpendicularmente al vector normal al plano, lo que siempre es posible. Y luego resuelve el problema de punto en cuadrilátero en el plano de proyección.

Antes de comenzar, verifique si su segmento de línea se encuentra en el plano 3D de R , y si es así, manipúlelo por separado.