三维空间中判断射线与平面是否相交

摘要

本文内容包括:

  • 三维空间中射线与平面的表示方法,
  • 三维空间中判断射线与平面是否相交。

文末参考链接的资料都不错,但总漏点东西,所以把它们说总结到了一起。


三维空间中射线的表示方法

射线可以用三个量来表示:射线的起始点、射线的方向向量以及射线的长度。
在这里插入图片描述
如图所示的射线的参数方程为:
P ( t ) = P 0 ′ + t u ⃗ P(t) = P_0^{'} + t \vec{u} P(t)=P0+tu
其中, P ( t ) P(t) P(t)为射线上的点,其所有可能的结果构成了整条射线; P 0 ′ P_0^{'} P0是射线的起点, u ⃗ \vec{u} u 为射线的方向向量, t t t为射线的长度且 t ∈ [ 0 , ∞ ) t∈[0,∞) t[0,)

三维空间中平面的表示方法

平面可以用二个量来表示:平面上任一点,过该点的平面法向量。
在这里插入图片描述
如图所示的平面的参数方程为:
( P − P 0 ) n ⃗ = 0 (P - P_0)\vec{n} = 0 (PP0)n =0
其中, P P P为变量,其所有可能的结果组成了这个平面; P 0 P_0 P0为平面上已知的某一点, n ⃗ \vec{n} n 为平面上过已知点 P 0 P_0 P0的法向量。
公式的物理意义为: ( P − P 0 ) (P - P_0) (PP0)表示平面上的向量,其与平面法向量 n ⃗ \vec{n} n 总是垂直的,故它们之间的内积为0.

三维空间中射线与平面是否相交的判断方法

射线不同于直线,射线存在起始点和方向,它与平面存在3种情况:

  1. 射线与平面平行。这时候肯定不相交。
  2. 射线与平面不平行。但平面在射线负方向,这时候也不相交。
  3. 射线与平面不平行。且平面在射线正方向,这时候射线与平面相交。

下面分情况讨论。
n ⃗ u ⃗ = 0 \vec{n}\vec{u} = 0 n u =0时,表示射线与平面平行,这时候肯定不相交。
n ⃗ u ⃗ ≠ 0 \vec{n}\vec{u} \neq 0 n u =0时,表示射线与平面不平行,这时候射线所在的直线与平面必定相交于一点,记该点为 P ( t ) P(t) P(t),那么有:
( P 0 − P ( t ) ) n ⃗ = 0 (P_0 - P(t))\vec{n} = 0 (P0P(t))n =0
带入射线参数方程 P ( t ) = P 0 ′ + t u ⃗ P(t) = P_0^{'} + t \vec{u} P(t)=P0+tu , 有
( P 0 − P 0 ′ − t u ⃗ ) n ⃗ = 0 (P_0 - P_0^{'} - t \vec{u})\vec{n} = 0 (P0P0tu )n =0
解之得
t = ( P 0 − P 0 ′ ) n ⃗ u ⃗ n ⃗ t = \frac{(P_0 - P_0^{'})\vec{n}}{\vec{u}\vec{n}} t=u n (P0P0)n 注意,这里是向量点积,所以分子分母的 n ⃗ \vec{n} n 不能消掉。
所以我们可以求出射线所在的直线与平面交点
P ( t ) = P 0 ′ + t u ⃗ = P 0 ′ + ( P 0 − P 0 ′ ) n ⃗ u ⃗ n ⃗ u ⃗ P(t) = P_0^{'} + t \vec{u} = P_0^{'} + \frac{(P_0 - P_0^{'})\vec{n}}{\vec{u}\vec{n}} \vec{u} P(t)=P0+tu =P0+u n (P0P0)n u
那么如何判断射线是否与平面相交呢?
t > = 0 t >= 0 t>=0时,交点在射线正方向上,所以射线与平面相交,交点即为P(t);
t < 0 t < 0 t<0时,交点在射线负方向上,所以射线与平面不相交,但射线所在的直线与平面相交。

相关/参考链接

  • 6
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
下面是一个简单的 C++ 代码实现: ```c++ #include <iostream> #include <cmath> using namespace std; struct Vector3 { double x, y, z; Vector3() {} Vector3(double x, double y, double z) : x(x), y(y), z(z) {} Vector3 operator+(const Vector3& other) const { return Vector3(x + other.x, y + other.y, z + other.z); } Vector3 operator-(const Vector3& other) const { return Vector3(x - other.x, y - other.y, z - other.z); } Vector3 operator*(double scalar) const { return Vector3(x * scalar, y * scalar, z * scalar); } double dot(const Vector3& other) const { return x * other.x + y * other.y + z * other.z; } Vector3 cross(const Vector3& other) const { return Vector3(y * other.z - z * other.y, z * other.x - x * other.z, x * other.y - y * other.x); } double length() const { return sqrt(x * x + y * y + z * z); } }; struct Ray { Vector3 origin, direction; Ray() {} Ray(const Vector3& origin, const Vector3& direction) : origin(origin), direction(direction) {} }; struct Plane { Vector3 point, normal; Plane() {} Plane(const Vector3& point, const Vector3& normal) : point(point), normal(normal) {} }; bool intersect(const Ray& ray, const Plane& plane, double& t) { double denom = plane.normal.dot(ray.direction); if (abs(denom) < 1e-6) // 判断是否平行 return false; t = plane.normal.dot(plane.point - ray.origin) / denom; return t >= 0; } int main() { // 示例:射线由点(0, 0, 0)出发,方向为(1, 1, 1);平面上的一点为(0, 0, 1),法向量为(0, 0, 1) Ray ray(Vector3(0, 0, 0), Vector3(1, 1, 1)); Plane plane(Vector3(0, 0, 1), Vector3(0, 0, 1)); double t; if (intersect(ray, plane, t)) { Vector3 intersection = ray.origin + ray.direction * t; cout << "Intersection point: (" << intersection.x << ", " << intersection.y << ", " << intersection.z << ")" << endl; } else { cout << "No intersection." << endl; } return 0; } ``` 这里我们定义了三个结构体:`Vector3` 表示三维向量,`Ray` 表示射线,`Plane` 表示平面。`intersect` 函数判断射线平面是否相交,并返回相交参数t。在主函数,我们给出了一个示例并输出相交点的坐标。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值