射线与平面相交判断

1 射线

定义

在欧几里德几何中,射线的定义如下:

直线上一点和它一旁的部分,由此知射线有两个性质:

1. 有一个端点

2. 一端无线延伸

参数方程

p(t) = p0 + tu

p0 是射线的起点, u是射线的方向向量,t∈[0,∞) 

解释一下这个方程,见下图,根据t的取值不同,可得射线上不同的点,所有这些点便构成了整个射线(红色部分)

 

 

 

2 平面

定义

中文的没找到,英文的:In mathematics, a plane is a flat surface

一个平面可以由平面上的一点p0 和平面的法向量n来确定(过一点,有且只有一个平面与已知直线垂直),如下图

 

参数方程

平面是由无穷多个点组成的,对于过点p0 且法向量为n的平面来说,其上任意一点p满足如下方程

n•(p - p0) = 0

解释一下, 符号“•”表示dot product(点积),因n与平面垂直,所以n与平面内任意直线垂直,而p - p0则是平面内的一个向量,所以n与p - p0垂直,又因为互相垂直的向量其点积为0,所以就有了上面的方程。见下图

向量的点积:对于任意两个向量V1(x1, y1, z1)与V2(x2, y2, z2),V1•V2 = x1x2 + y1y2 + z1z2  

 

 3 切入正题,射线与平面相交。

  射线若于平面相交,则交点一定在平面上,设交点为p,那么p一定同时满足射线的方程和平面的方程,于是

  p(t) = p0 + tu //这里的p0是射线的起点 

  n•(p - p0) = 0 //这里的p0是平面所过的点

  注意,这两个方程中的p0是不同的,为区别,将平面方程中的p0改为p1,然后将射线方程代入平面方程

  n•(p0 + tu – p1) = 0 整理后得到

  t = (n•p1 – n•p0) / n•u (注意:n不可约去)

      由向量点乘分配律得:

      t = n•(p1-p0)/n•u

  若t∈[0,∞),则射线与平面相交,且交点为p0 + tu,将上面的t带入射线方程即可否则不相交。

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的 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。在主函数中,我们给出了一个示例并输出相交点的坐标。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值