visibilidad unicoos una todos tierra ser resueltos recta que puntos punto puede planos plano paralelos online los linea intersectan intersección interseccion hallar geometria entre encuentre encontrar ejercicios descriptiva cuya como math language-agnostic plane

math - unicoos - recta interseccion de dos planos online



Línea de intersección entre dos planos (6)

¿Cómo puedo encontrar la línea de intersección entre dos planos?

Conozco la idea matemática, e hice el producto cruzado entre los vectores normales de los aviones

pero cómo obtener la línea del vector resultante programáticamente


Encontrar un punto en la línea

Para obtener la intersección de 2 planos, necesita un punto en la línea y la dirección de esa línea.

Encontrar la dirección de esa línea es realmente fácil, simplemente cruce las 2 normales de los 2 planos que se cruzan.

lineDir = n1 × n2

Pero esa línea pasa por el origen, y la línea que corre a lo largo de las intersecciones de su avión podría no hacerlo. Entonces, la respuesta de Martinho proporciona un gran comienzo para encontrar un punto en la línea de intersección (básicamente cualquier punto que esté en ambos planos).

En caso de que desee ver la derivación de cómo resolver esto, aquí está la matemática detrás de esto:

Primero, deje x = 0. Ahora tenemos 2 incógnitas en 2 ecuaciones en lugar de 3 incógnitas en 2 ecuaciones (elegimos arbitrariamente una de las incógnitas).

Entonces las ecuaciones del plano son (se eliminaron los términos A ya que elegimos x = 0):

B 1 y + C 1 z + D 1 = 0

B 2 y + C 2 z + D 2 = 0

Queremos yyz tal que esas ecuaciones se resuelven correctamente (= 0) para el B 1 , C 1 dado.

Entonces, simplemente multiplique la ecuación superior por (-B 2 / B 1 ) para obtener

-B 2 y + (-B 2 / B 1 ) * C 1 z + (-B 2 / B 1 ) * D 1 = 0

B 2 y + C 2 z + D 2 = 0

Agregue los eqs para obtener

z = ((-B 2 / B 1 ) * D 1 - D 2 ) / (C 2 * B 2 / B 1 ) * C 1 )

Tira la z que encuentras en la primera ecuación ahora para encontrar y como

y = (-D 1 - C 1 z) / B 1

Tenga en cuenta que la mejor variable para hacer 0 es la que tiene los coeficientes más bajos, porque de todos modos no contiene información. Entonces, si C 1 y C 2 son ambos 0, elegir z = 0 (en lugar de x = 0) sería una mejor opción.

La solución anterior aún puede arruinarse si B 1 = 0 (que no es tan improbable). Podría agregar en algunas sentencias if que verifiquen si B 1 = 0, y si es así, asegúrese de resolver una de las otras variables.

Solución usando la intersección de 3 planos

De la respuesta del usuario , una solución de forma cerrada para la intersección de 3 planos estaba realmente en Graphics Gems 1. La fórmula es:

P_intersection = ((point_on1 • n1) (n2 × n3) + (point_on2 • n2) (n3 × n1) + (point_on3 • n3) (n1 × n2)) / det (n1, n2, n3)

En realidad, point_on1 • n1 = -d1 (suponiendo que escriba sus planos Ax + By + Cz + D = 0, y no = -D). Entonces, podrías reescribirlo como:

P_intersection = ((-d1) (n2 × n3) + (-d2) (n3 × n1) + (-d3) (n1 × n2)) / det (n1, n2, n3)

Una función que intersecta 3 planos:

// Intersection of 3 planes, Graphics Gems 1 pg 305 static Vector3f getIntersection( const Plane& plane1, const Plane& plane2, const Plane& plane3 ) { float det = Matrix3f::det( plane1.normal, plane2.normal, plane3.normal ) ; // If the determinant is 0, that means parallel planes, no intn. if( det == 0.f ) return 0 ; //could return inf or whatever return ( plane2.normal.cross( plane3.normal )*-plane1.d + plane3.normal.cross( plane1.normal )*-plane2.d + plane1.normal.cross( plane2.normal )*-plane3.d ) / det ; }

Prueba de que funciona (el punto amarillo es la intersección de los planos rgb aquí)

Conseguir la línea

Una vez que tienes un punto de intersección común a los 2 aviones, la línea simplemente va

P + t * d

Donde P es el punto de intersección, t puede ir desde (-inf, inf), y d es el vector de dirección que es el producto cruzado de las normales de los dos planos originales.

La línea de intersección entre los planos rojo y azul se ve así

Eficiencia y estabilidad

El "robusto" (2da manera) toma 48 operaciones elementales por mi cuenta, frente a las 36 operaciones elementales que usa la 1ra vía (aislamiento de x, y). Hay una compensación entre estabilidad y # cálculos entre estas 2 formas.

Sería bastante catastrófico recuperar (0, inf, inf) de una llamada a la primera vía en el caso de que B 1 fuera 0 y usted no lo haya verificado. Por lo tanto, agregar las declaraciones if y asegurarse de no dividir por 0 en la primera manera puede brindarle la estabilidad a costa de la saturación del código y la ramificación agregada (que puede ser bastante costosa). El método de intersección de 3 aviones es casi sin sucursales y no le dará infinitos.


El enfoque basado en los determinantes es claro, pero es difícil seguir por qué funciona.

Aquí hay otra forma más intuitiva.

La idea es ir primero desde el origen hasta el punto más cercano en el primer plano ( p1 ), y luego desde allí ir al punto más cercano en la línea de intersección de los dos planos. (A lo largo de un vector al que estoy llamando v continuación)

Given ===== First plane: n1 • r = k1 Second plane: n2 • r = k2 Working ======= dir = n1 × n2 p1 = (k1 / (n1 • n1)) * n1 v = n1 × dir pt = LineIntersectPlane(line = (p1, v), plane = (n2, k2)) LineIntersectPlane ================== #We have n2 • (p1 + lambda * v) = k2 lambda = (k2 - n2 • p1) / (n2 • v) Return p1 + lambda * v Output ====== Line where two planes intersect: (pt, dir)

Esto debería dar el mismo punto que el enfoque basado en determinantes. Es casi seguro que hay un vínculo entre los dos. Al menos el denominador, n2 • v , es el mismo, si aplicamos la regla de "triple producto escalar". Entonces, estos métodos son probablemente similares en lo que respecta a los números de condición.

No olvide verificar si hay aviones (casi) paralelos. Por ejemplo: if (dir • dir < 1e-8) debería funcionar bien si se usan las normales de la unidad.


El producto cruzado de la línea es la dirección de la línea de intersección. Ahora necesitas un punto en la intersección.

Puede hacer esto tomando un punto en el producto cruzado y luego restando la distancia Normal del plano A * al plano A y la Normal del plano B * al plano b. Limpiador:

p = Punto en producto cruzado

Punto de intersección = ([p] - ([Normal del plano A] * [distancia de p al plano A]) - ([Normal del plano B] * [distancia de p al plano B]))

Editar:

Tienes dos planos con dos normales:

N1 and N2

El producto cruzado es la dirección de la línea de intersección:

C = N1 x N2

La clase anterior tiene una función para calcular la distancia entre un punto y un plano. Úselo para obtener la distancia de algún punto p en C a ambos planos:

p = C //p = 1 times C to get a point on C d1 = plane1.getDistance(p) d2 = plane2.getDistance(p)

Línea de intersección:

resultPoint1 = (p - (d1 * N1) - (d2 * N2)) resultPoint2 = resultPoint1 + C


Este método evita la división por cero siempre que los dos planos no sean paralelos.

Si estos son los aviones:

A1*x + B1*y + C1*z + D1 = 0 A2*x + B2*y + C2*z + D2 = 0

1) Encuentra un vector paralelo a la línea de intersección. Esta es también la normalidad de un tercer plano que es perpendicular a los otros dos planos:

(A3,B3,C3) = (A1,B1,C1) cross (A2,B2,C2)

2) Forme un sistema de 3 ecuaciones. Estos describen 3 planos que se cruzan en un punto:

A1*x1 + B1*y1 + C1*z1 + D1 = 0 A2*x1 + B2*y1 + C2*z1 + D2 = 0 A3*x1 + B3*y1 + C3*z1 = 0

3) Resuélvalos para encontrar x1, y1, z1. Este es un punto en la línea de intersección.

4) Las ecuaciones paramétricas de la línea de intersección son:

x = x1 + A3 * t y = y1 + B3 * t z = z1 + C3 * t


La ecuación del plano es ax + by + cz + d = 0 , donde (a, b, c) es la normal del plano, y d es la distancia al origen. Esto significa que cada punto (x, y, z) que satisface esa ecuación es un miembro del plano.

Dado dos aviones:

P1: a1x + b1y + c1z + d1 = 0 P2: a2x + b2y + c2z + d2 = 0

La intersección entre los dos es el conjunto de puntos que verifica ambas ecuaciones. Para encontrar puntos a lo largo de esta línea, simplemente puede elegir un valor para x, cualquier valor, y luego resolver las ecuaciones para y y z.

y = (-c1z -a1x -d1) / b1 z = ((b2/b1)*(a1x+d1) -a2x -d2)/(c2 - c1*b2/b1)

Si haces x=0 , esto se simplifica:

y = (-c1z -d1) / b1 z = ((b2/b1)*d1 -d2)/(c2 - c1*b2/b1)


Agreguemos esta respuesta para completarla, ya que al momento de escribir, ninguna de las respuestas aquí contiene un código de trabajo, ejemplo que aborda directamente la pregunta.

Aunque otras respuestas aquí ya cubrieron los principios .

El 2''nd, "método más robusto" de la respuesta de bobobobo hace referencia a la intersección de 3 aviones.

Si bien esto funciona bien para 2 planos (donde el tercer plano se puede calcular utilizando el producto cruzado de los dos primeros) , el problema puede reducirse aún más para la versión de 2 planos.

  • No es necesario usar un determinante de matriz 3x3,
    en su lugar, podemos usar la longitud cuadrada del producto cruzado entre el primer y el segundo plano (que es la dirección del plano 3 °) .
  • No es necesario incluir la distancia del tercer avión,
    (calculando la ubicación final) .
  • No es necesario negar las distancias.
    Guarde algunos ciclos cpu intercambiando el pedido cruzado de productos en su lugar.

Incluyendo este código-ejemplo, ya que puede no ser inmediatamente obvio.

// Intersection of 2-planes: a variation based on the 3-plane version. // see: Graphics Gems 1 pg 305 // // Note that the ''normal'' components of the planes need not be unit length bool isect_plane_plane_to_normal_ray( const Plane& p1, const Plane& p2, // output args Vector3f& r_point, Vector3f& r_normal) { // logically the 3rd plane, but we only use the normal component. const Vector3f p3_normal = p1.normal.cross(p2.normal); const float det = p3_normal.length_squared(); // If the determinant is 0, that means parallel planes, no intersection. // note: you may want to check against an epsilon value here. if (det != 0.0) { // calculate the final (point, normal) r_point = ((p3_normal.cross(p2.normal) * p1.d) + (p1.normal.cross(p3_normal) * p2.d)) / det; r_normal = p3_normal; return true; } else { return false; } }