resueltos rectas recta planos plano parametricas interseccion hallar geometria entre ejercicios descriptiva 3d line intersection plane

3d - rectas - interseccion entre recta y plano geometria descriptiva



Intersección de plano de línea 3D (8)

Aquí hay 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 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 intersecan con el segmento de línea, lo que puede ser útil para la persona que llama.

Otros detalles anotados en el código-comentarios.

Nota: este ejemplo utiliza funciones puras, sin ninguna dependencia, para facilitar el traslado a otros idiomas. Con un tipo de datos Vector y una 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 asignación de 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 mayor referencia, se tomó de Blender y se adaptó a Python. isect_line_plane_v3() en math_geom.c

Para mayor claridad, aquí hay versiones que utilizan la API mathutils (que se puede modificar para otras bibliotecas matemáticas con sobrecarga de operadores) .

# 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

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 cruza un plano? He encontrado un montón de 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 programación estándar (estoy usando Java).


Aquí hay un método en Java que encuentra la intersección entre una línea y un plano. Hay métodos vectoriales que no están incluidos, pero sus funciones son bastante explicativas.

/** * Determines the point of intersection between a plane defined by a point and a normal vector and a line defined by a point and a direction vector. * * @param planePoint A point on the plane. * @param planeNormal The normal vector of the plane. * @param linePoint A point on the line. * @param lineDirection The direction vector of the line. * @return The point of intersection between the line and the plane, null if the line is parallel to the plane. */ public static Vector lineIntersection(Vector planePoint, Vector planeNormal, Vector linePoint, Vector lineDirection) { if (planeNormal.dot(lineDirection) == 0) { return null; } double t = (planeNormal.dot(planePoint) - planeNormal.dot(linePoint)) / planeNormal.dot(lineDirection); return linePoint.plus(lineDirection.scale(t)); }


Basado en this código Matlab (menos los controles 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 funcionar,

Esto creo que es una implementación más robusta del enlace compartido before


Esta pregunta es antigua, pero como hay 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 desea la solución:

Hay un vector 4x1 p que describe el plano tal que p ^ T * x = 0 para cualquier punto homogéneo en el plano. A continuación, calcule las coordenadas del desplumador para la línea L = ab ^ T - ba ^ T donde a = {point_1; 1}, b = {punto_2; 1}, ambos 4x1 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 necesitabas esto para propósitos de codificación, aquí hay un fragmento de código 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)));


Solo para ampliar ZGorlock''s respuesta ZGorlock''s , he hecho el producto de puntos, más y una escalada de vectores 3D. Las referencias para estos cálculos son Producto puntual , Añadir dos vectores 3D y Scaling . Nota: Vec3D es solo una clase personalizada que tiene puntos: x, y y z.

/** * Determines the point of intersection between a plane defined by a point and a normal vector and a line defined by a point and a direction vector. * * @param planePoint A point on the plane. * @param planeNormal The normal vector of the plane. * @param linePoint A point on the line. * @param lineDirection The direction vector of the line. * @return The point of intersection between the line and the plane, null if the line is parallel to the plane. */ public static Vec3D lineIntersection(Vec3D planePoint, Vec3D planeNormal, Vec3D linePoint, Vec3D lineDirection) { //ax × bx + ay × by int dot = (int) (planeNormal.x * lineDirection.x + planeNormal.y * lineDirection.y); if (dot == 0) { return null; } // Ref for dot product calculation: https://www.mathsisfun.com/algebra/vectors-dot-product.html int dot2 = (int) (planeNormal.x * planePoint.x + planeNormal.y * planePoint.y); int dot3 = (int) (planeNormal.x * linePoint.x + planeNormal.y * linePoint.y); int dot4 = (int) (planeNormal.x * lineDirection.x + planeNormal.y * lineDirection.y); double t = (dot2 - dot3) / dot4; float xs = (float) (lineDirection.x * t); float ys = (float) (lineDirection.y * t); float zs = (float) (lineDirection.z * t); Vec3D lineDirectionScale = new Vec3D( xs, ys, zs); float xa = (linePoint.x + lineDirectionScale.x); float ya = (linePoint.y + lineDirectionScale.y); float za = (linePoint.z + lineDirectionScale.z); return new Vec3D(xa, ya, za); }


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 interseca en cada punto de ella)

Puedes expresar la línea en forma paramaterizada, como aquí:

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

Las primeras páginas de esta conferencia hacen lo mismo para el plano:

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

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

De lo contrario, tiene un punto de intersección y puede resolverlo.

Sé que esto no es un 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 empiezas 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. Luego, si tienes la ecuación para un plano, di:

x + 2y + 2z = 5

(tomado de here ) puede sustituir las ecuaciones de 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 puedes resolver para x , y y z regresando a las ecuaciones de línea y sustituyendo t nuevo.


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)