线形对象与平面相交

2023-10-30 09:50
文章标签 对象 相交 平面 线形

本文主要是介绍线形对象与平面相交,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

三维空间中的线形对象包括直线、射线和线段,为了统一三者的表达,在三维图形学中一般使用一个点和方向向量的方式来描述这些线形对象。

假设有一个点P位于线形对象上,方向向量是 d⃗  ,那么这个线形对象可以使用下面的公式来表达:

L(t)=P+td⃗ 

基于这个表达式,直线方程可以描述为:

L(t)=P+td⃗ (t)

射线方程可以描述为(P是射线的端点):

R(t)=P+td⃗ (0t)

在描述线段时,使用一对点{ P0 P1 },则线段方程是:

S(t)=P0+t(P1P0)(0t1)

平面的描述方式很多,最简单的是使用一般式 ax+by+cz+d=0 ,向量 n⃗ =[a,b,c] 是平面的法向量。

1. 直线与平面相交

PlaneLineIntersection

如上图所示,直线方程L是 P+td⃗  , 平面方程是 ax+by+cz+d=0 ,假设二者有交点(交于点Q),那么直线上的Q点也一定满足平面方程,也就是:

Q=P+td⃗  满足 ax+by+cz+D=0 (为区别直线的方向向量,平面方程的常数项写成D),将Q点带入平面方程中,得到:

a(Px+tdx)+b(Py+tdy)+c(Pz+tdz)+D=0

t=(D+aPx+bPy+cPz)adx+bdy+cdz

写成向量的形式是:

t=(D+n⃗ P)n⃗ d⃗ 

针对这个表达式展开讨论:

  1. 如果 n⃗ d⃗ =0 那么说明直线平行于平面或者直线位于平面之内。怎么判断直线是否位于平面之内呢?很简单,判断直线的另一个点P是否位于平面内即可,也就是把P点带入平面方程中,如果满足平面方程,那么直线位于平面内,不满足则二者平行。
  2. 如果 n⃗ d⃗ 0 ,那么直线和平面有唯一的交点,将t值带入到 Q=P+td⃗  可以求出二者的交点坐标。

总结如下:

  1. n⃗ d⃗ =0 aPx+bPy+cPz+D=0 直线位于平面内
  2. n⃗ d⃗ =0 aPx+bPy+cPz+D0 直线与平面平行
  3. n⃗ d⃗ 0 直线与平面有唯一交点

在编码过程中由于浮点数的舍入误差,一般将结果与一个阈值 ϵ 进行比较,通过比较快速判断直线与平面是否相交。

2. 射线与平面相交

射线的方程表达式与直线类似,但是射线稍有不同的是它表达式中的 P一定是射线的端点,如果P是射线的端点,那么计算的过程与直线中的结论完全一样,只不过需要在判断相交的时候t的取值,如果取值范围 t0 ,那么就可以带入到射线方程中求出交点Q,否则(也就是 t<0 )二者没有交点。

总结如下:

  1. n⃗ d⃗ =0 aPx+bPy+cPz+D=0 直线位于平面内
  2. n⃗ d⃗ =0 aPx+bPy+cPz+D0 直线与平面平行
  3. n⃗ d⃗ 0 t0 射线与平面有唯一交点
  4. n⃗ d⃗ 0 t<0 射线与平面没有交点

3. 线段与平面相交

线段的计算过程同样与射线类似,可以通过直线方程

S(t)=P0+t(P1P0)(0t1)

来计算,需要注意的是线段的方向向量 d⃗  ,必须是 P1P0 ,这样t的取值范围就是在[0,1]区间,如果t的取值范围不是[0,1],那么线段与平面无交点。

总结如下:

  1. 直线方程的方向向量必须是 P1P0 (直线和射线只要方向相同即可,甚至可以单位化方向向量,但是线段必须是 P1P0
  2. n⃗ d⃗ =0 aPx+bPy+cPz+D=0 直线位于平面
  3. n⃗ d⃗ =0 aPx+bPy+cPz+D0 直线与平面平行
  4. n⃗ d⃗ 0 t[0,1] 射线与平面有唯一交点
  5. n⃗ d⃗ 0 t[0,1] 射线与平面没有交点

4. 算法实现

使用OpenSceneGraph实现线段和平面的相交判断的代码如下:


/* 
*  线段和平面的相交关系判断:返回值是0表示没有交点,返回值是1表示二者有唯一交点,返回值是2表示线段位于平面内
*
*/int intersectSegmentPlane(const osg::Plane& plane, const osg::LineSegment& lineSegment, osg::Vec3d& intersection)
{double epsilon = 1e-6;osg::Vec3d planeNorm = plane.getNormal();osg::Vec3d segmentDirection = lineSegment.end() - lineSegment.start();double dotPlaneNormSegDir = planeNorm * segmentDirection;osg::Vec4d planeParam = plane.asVec4();double lineInPlane = planeParam.x() * lineSegment.start().x() + planeParam.y() * lineSegment.start().y() +planeParam.z() * planeParam.z() + planeParam.w();if (fabs(dotPlaneNormSegDir) < epsilon){//如果直线端点满足平面方程,那么直线在平面内if (fabs(lineInPlane) < epsilon){return 2;}else{return 0;}}double planeNormDotP = -(planeParam.w() + planeNorm * lineSegment.start());double t = planeNormDotP / dotPlaneNormSegDir;if (t < 0 || t > 1)return 0;intersection = lineSegment.start() + segmentDirection*t;return 1;
}

5. 参考文献

  1. Line and Segment Intersections
  2. [书籍:Geometric Tools for Computer Graphics]

这篇关于线形对象与平面相交的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/307096

相关文章

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os

SpringMVC高效获取JavaBean对象指南

《SpringMVC高效获取JavaBean对象指南》SpringMVC通过数据绑定自动将请求参数映射到JavaBean,支持表单、URL及JSON数据,需用@ModelAttribute、@Requ... 目录Spring MVC 获取 JavaBean 对象指南核心机制:数据绑定实现步骤1. 定义 Ja

Python打印对象所有属性和值的方法小结

《Python打印对象所有属性和值的方法小结》在Python开发过程中,调试代码时经常需要查看对象的当前状态,也就是对象的所有属性和对应的值,然而,Python并没有像PHP的print_r那样直接提... 目录python中打印对象所有属性和值的方法实现步骤1. 使用vars()和pprint()2. 使

MySQL JSON 查询中的对象与数组技巧及查询示例

《MySQLJSON查询中的对象与数组技巧及查询示例》MySQL中JSON对象和JSON数组查询的详细介绍及带有WHERE条件的查询示例,本文给大家介绍的非常详细,mysqljson查询示例相关知... 目录jsON 对象查询1. JSON_CONTAINS2. JSON_EXTRACT3. JSON_TA

C#之List集合去重复对象的实现方法

《C#之List集合去重复对象的实现方法》:本文主要介绍C#之List集合去重复对象的实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C# List集合去重复对象方法1、测试数据2、测试数据3、知识点补充总结C# List集合去重复对象方法1、测试数据

Spring中管理bean对象的方式(专业级说明)

《Spring中管理bean对象的方式(专业级说明)》在Spring框架中,Bean的管理是核心功能,主要通过IoC(控制反转)容器实现,下面给大家介绍Spring中管理bean对象的方式,感兴趣的朋... 目录1.Bean的声明与注册1.1 基于XML配置1.2 基于注解(主流方式)1.3 基于Java

C++/类与对象/默认成员函数@构造函数的用法

《C++/类与对象/默认成员函数@构造函数的用法》:本文主要介绍C++/类与对象/默认成员函数@构造函数的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录名词概念默认成员函数构造函数概念函数特征显示构造函数隐式构造函数总结名词概念默认构造函数:不用传参就可以

C++类和对象之默认成员函数的使用解读

《C++类和对象之默认成员函数的使用解读》:本文主要介绍C++类和对象之默认成员函数的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、默认成员函数有哪些二、各默认成员函数详解默认构造函数析构函数拷贝构造函数拷贝赋值运算符三、默认成员函数的注意事项总结一

golang 对象池sync.Pool的实现

《golang对象池sync.Pool的实现》:本文主要介绍golang对象池sync.Pool的实现,用于缓存和复用临时对象,以减少内存分配和垃圾回收的压力,下面就来介绍一下,感兴趣的可以了解... 目录sync.Pool的用法原理sync.Pool 的使用示例sync.Pool 的使用场景注意sync.

SpringBoot项目中Redis存储Session对象序列化处理

《SpringBoot项目中Redis存储Session对象序列化处理》在SpringBoot项目中使用Redis存储Session时,对象的序列化和反序列化是关键步骤,下面我们就来讲讲如何在Spri... 目录一、为什么需要序列化处理二、Spring Boot 集成 Redis 存储 Session2.1