Intersección de plano de línea 3D

Si se le da una línea (representada por un vector o dos puntos en la línea) ¿cómo encuentro el punto en el que la línea se cruza con un plano? He encontrado muchos recursos sobre esto, pero no puedo entender las ecuaciones allí (no parecen ser algebraicas estándar). Me gustaría una ecuación (no importa cuánto tiempo) que pueda ser interpretada por un lenguaje de progtwigción estándar (estoy usando Java).

Tendrá que considerar tres casos:

  • El plano es paralelo a la línea, y la línea no se encuentra en el plano (sin intersección)
  • El plano no es paralelo a la línea (un punto de intersección)
  • El plano contiene la línea (la línea se cruza en cada punto sobre ella)

Puedes express la línea en forma patwigterizada, como aquí:

http://answers.yahoo.com/question/index?qid=20080830195656AA3aEBr

Las primeras páginas de esta conferencia hacen lo mismo para el avión:

http://math.mit.edu/classes/18.02/notes/lecture5compl-09.pdf

Si la normal al plano es perpendicular a la dirección a lo largo de la línea, entonces tiene una caja de borde y necesita ver si se cruza en absoluto, o si se encuentra dentro del plano.

De lo contrario, tienes un punto de intersección y puedes resolverlo.

Sé que esto no es código, pero para obtener una solución sólida, probablemente querrá poner esto en el contexto de su aplicación.

EDITAR: Aquí hay un ejemplo para el cual hay exactamente un punto de intersección. Digamos que comienzas con las ecuaciones parametrizadas en el primer enlace:

x = 5 - 13t y = 5 - 11t z = 5 - 8t 

El parámetro t puede ser cualquier cosa. El conjunto (infinito) de todos (x, y, z) que satisfacen estas ecuaciones comprende la línea. Entonces, si tienes la ecuación para un avión, di:

 x + 2y + 2z = 5 

(tomado de aquí ) puede sustituir las ecuaciones para x , y , z arriba en la ecuación para el plano, que ahora está solo en el parámetro t . Resuelve para t . Este es el valor particular de t para esa línea que se encuentra en el plano. Luego puede resolver para x , y y z regresando a las ecuaciones de línea y sustituyendo t por.

Aquí está un ejemplo de Python que encuentra la intersección de una línea y un plano.

Donde el plano puede ser un punto y un vector normal, o un vector 4d (forma normal), en los ejemplos a continuación (se proporciona el código para ambos) .

También tenga en cuenta que esta función calcula un valor que representa dónde está el punto en la línea, (llamado fac en el código a continuación). Es posible que desee devolver esto también, porque los valores de 0 a 1 se cruzan con el segmento de línea, lo que puede ser útil para la persona que llama.

Otros detalles señalados en el código-comentarios.


Nota: Este ejemplo usa funciones puras, sin dependencias, para facilitar el cambio a otros idiomas. Con un tipo de datos Vector y la sobrecarga del operador, puede ser más conciso (incluido en el ejemplo a continuación).

 # intersection function def isect_line_plane_v3(p0, p1, p_co, p_no, epsilon=1e-6): """ p0, p1: define the line p_co, p_no: define the plane: p_co is a point on the plane (plane coordinate). p_no is a normal vector defining the plane direction; (does not need to be normalized). return a Vector or None (when the intersection can't be found). """ u = sub_v3v3(p1, p0) dot = dot_v3v3(p_no, u) if abs(dot) > epsilon: # the factor of the point between p0 -> p1 (0 - 1) # if 'fac' is between (0 - 1) the point intersects with the segment. # otherwise: # < 0.0: behind p0. # > 1.0: infront of p1. w = sub_v3v3(p0, p_co) fac = -dot_v3v3(p_no, w) / dot u = mul_v3_fl(u, fac) return add_v3v3(p0, u) else: # The segment is parallel to plane return None # ---------------------- # generic math functions def add_v3v3(v0, v1): return ( v0[0] + v1[0], v0[1] + v1[1], v0[2] + v1[2], ) def sub_v3v3(v0, v1): return ( v0[0] - v1[0], v0[1] - v1[1], v0[2] - v1[2], ) def dot_v3v3(v0, v1): return ( (v0[0] * v1[0]) + (v0[1] * v1[1]) + (v0[2] * v1[2]) ) def len_squared_v3(v0): return dot_v3v3(v0, v0) def mul_v3_fl(v0, f): return ( v0[0] * f, v0[1] * f, v0[2] * f, ) 

Si el plano se define como un vector 4d (forma normal) , necesitamos encontrar un punto en el plano y luego calcular la intersección como antes (ver la asignación p_co ).

 def isect_line_plane_v3_4d(p0, p1, plane, epsilon=1e-6): u = sub_v3v3(p1, p0) dot = dot_v3v3(plane, u) if abs(dot) > epsilon: # calculate a point on the plane # (divide can be omitted for unit hessian-normal form). p_co = mul_v3_fl(plane, -plane[3] / len_squared_v3(plane)) w = sub_v3v3(p0, p_co) fac = -dot_v3v3(plane, w) / dot u = mul_v3_fl(u, fac) return add_v3v3(p0, u) else: return None 

Para referencia adicional, esto fue tomado de Blender y adaptado a Python. isect_line_plane_v3() en math_geom.c


Para mayor claridad, aquí hay versiones que usan la API mathutils (que puede modificarse para otras bibliotecas matemáticas con sobrecarga del operador) .

 # point-normal plane def isect_line_plane_v3(p0, p1, p_co, p_no, epsilon=1e-6): u = p1 - p0 dot = p_no * u if abs(dot) > epsilon: w = p0 - p_co fac = -(plane * w) / dot return p0 + (u * fac) else: return None # normal-form plane def isect_line_plane_v3_4d(p0, p1, plane, epsilon=1e-6): u = p1 - p0 dot = plane.xyz * u if abs(dot) > epsilon: p_co = plane.xyz * (-plane[3] / plane.xyz.length_squared) w = p0 - p_co fac = -(plane * w) / dot return p0 + (u * fac) else: return None 

Usando numpy y python:

 #Based on http://geomalgorithms.com/a05-_intersect-1.html from __future__ import print_function import numpy as np epsilon=1e-6 #Define plane planeNormal = np.array([0, 0, 1]) planePoint = np.array([0, 0, 5]) #Any point on the plane #Define ray rayDirection = np.array([0, -1, -1]) rayPoint = np.array([0, 0, 10]) #Any point along the ray ndotu = planeNormal.dot(rayDirection) if abs(ndotu) < epsilon: print ("no intersection or line is within plane") w = rayPoint - planePoint si = -planeNormal.dot(w) / ndotu Psi = w + si * rayDirection + planePoint print ("intersection at", Psi) 

Basado en este código de Matlab (menos las verificaciones de intersección), en Python

 # n: normal vector of the Plane # V0: any point that belongs to the Plane # P0: end point 1 of the segment P0P1 # P1: end point 2 of the segment P0P1 n = np.array([1., 1., 1.]) V0 = np.array([1., 1., -5.]) P0 = np.array([-5., 1., -1.]) P1 = np.array([1., 2., 3.]) w = P0 - V0; u = P1-P0; N = -np.dot(n,w); D = np.dot(n,u) sI = N / D I = P0+ sI*u print I 

Resultado

 [-3.90909091 1.18181818 -0.27272727] 

Lo comprobé gráficamente, parece que funciona,

enter image description here

Esto creo que es una implementación más sólida del enlace compartido antes

Esta pregunta es antigua, pero dado que existe una solución mucho más conveniente, pensé que podría ayudar a alguien.

Las intersecciones de plano y línea son bastante elegantes cuando se expresan en coordenadas homogéneas, pero supongamos que solo quieres la solución:

Hay un vector 4×1 p que describe el plano tal que p ^ T * x = 0 para cualquier punto homogéneo en el plano. Luego calcule las coordenadas del plucker para la línea L = ab ^ T – ba ^ T donde a = {point_1; 1}, b = {point_2; 1}, ambos 4×1 en la línea

calcular: x = L * p = {x0, x1, x2, x3}

x_intersect = ({x0, x1, x2} / x3) donde si x3 es cero no hay intersección en el sentido euclidiano.

Si tiene dos puntos pyq que definen una línea, y un plano en la forma cartesiana general ax + by + cz + d = 0, puede usar el método paramétrico.

Si necesita esto para fines de encoding, aquí hay un fragmento de JavaScript:

 /** * findLinePlaneIntersectionCoords (to avoid requiring unnecessary instantiation) * Given points p with px py pz and q that define a line, and the plane * of formula ax+by+cz+d = 0, returns the intersection point or null if none. */ function findLinePlaneIntersectionCoords(px, py, pz, qx, qy, qz, a, b, c, d) { var tDenom = a*(qx-px) + b*(qy-py) + c*(qz-pz); if (tDenom == 0) return null; var t = - ( a*px + b*py + c*pz + d ) / tDenom; return { x: (px+t*(qx-px)), y: (py+t*(qy-py)), z: (pz+t*(qz-pz)) }; } // Example (plane at y = 10 and perpendicular line from the origin) console.log(JSON.stringify(findLinePlaneIntersectionCoords(0,0,0,0,1,0,0,1,0,-10))); // Example (no intersection, plane and line are parallel) console.log(JSON.stringify(findLinePlaneIntersectionCoords(0,0,0,0,0,1,0,1,0,-10)));