空间直线与球面相交算法
文章目录
- 1. 原理推导
- 1.1. 直线公式
- 1.2. 求交
- 2. 具体实现
- 3. 参考
1. 原理推导
1.1. 直线公式
在严格的数学定义中,直线是无线延长,没有端点的线;射线是一端有端点,另外一段没有端点无线延长的线。但在具体的计算机几何实现中,不可能去找到这种无线延长,没有端点的线,所以这里直线的定义更加近于线段,如果线段选的够长,那么这个线段就可以认为是直线或者射线。
空间直线的数学定义是,已知直线L上一点M0(x0,y0,c0)M_0(x_0,y_0,c_0)M0(x0,y0,c0),以及直线L的方向向量s(m,n,p)s(m,n,p)s(m,n,p),那么空间直线L的方程为:
x−x0m=y−y0n=z−z0p\frac{x-x_0}{m} = \frac{y-y_0}{n} = \frac{z-z_0}{p}mx−x0=ny−y0=pz−z0
以上是空间直线的标准式方程(点向式方程)。令上面式子的比值为ttt,那么直线的参数式方程为:
{x=x0+m∗ty=y0+n∗tz=z0+p∗t\begin{cases} x = x_0 + m * t\\ y = y_0 + n * t\\ z = z_0 + p * t\\ \end{cases} ⎩⎪⎨⎪⎧x=x0+m∗ty=y0+n∗tz=z0+p∗t
这两个方程是无法直接在实际情况中使用的,毕竟很多时候都是直接给出经过直线的两个点。我在《已知线段上某点与起点的距离,求该点的坐标》这篇博文中论述过:
对于知道线段的起点OOO和终点EEE,显然方向向量为D=E−OD=E−OD=E−O。这时,根据射线的向量方程,线段上某一点P为
P=O+tDP=O+tDP=O+tD
很明显,直线的参数式方程与上篇博文中描述的其实是一个意思,起点OOO就是M0(x0,y0,c0)M_0(x_0,y_0,c_0)M0(x0,y0,c0),方向向量DDD就是s(m,n,p)s(m,n,p)s(m,n,p):
{x=Ox+Dx∗ty=Oy+Dy∗tz=Oz+Dz∗t(1)\begin{cases} x = O_x + D_x * t\\ y = O_y + D_y * t\\ z = O_z + D_z * t\\ \end{cases} \tag {1} ⎩⎪⎨⎪⎧x=Ox+Dx∗ty=Oy+Dy∗tz=Oz+Dz∗t(1)
并且,采取这种公式描述还有个好处,局势t的取值范围为0到1,否则就在直线的两个端点之外,也就很有可能不是你需要的点。
1.2. 求交
根据数学定义,已知球心坐标C(Cx,Cy,Cz)C(C_x, C_y, C_z)C(Cx,Cy,Cz)与球的半径R,球面的公式为:
(X−Cx)2+(Y−Cy)2+(Z−Cz)2=R2(2)(X-C_x)^2 + (Y-C_y)^2 + (Z-C_z)^2 = R^2 \tag{2} (X−Cx)2+(Y−Cy)2+(Z−Cz)2=R2(2)
联立(1)(2)两式,最终会得到一个关于t的一元二次方程:
(Ox+Dx∗t−Cx)2+(Oy+Dy∗t−Cy)2+(Oz+Dz∗t−Cz)2=R2(O_x + D_x * t-C_x)^2 + ( O_y + D_y * t-C_y)^2 + (O_z + D_z * t-C_z)^2 = R^2 (Ox+Dx∗t−Cx)2+(Oy+Dy∗t−Cy)2+(Oz+Dz∗t−Cz)2=R2
一元二次方程组的有无解,单个解,以及双解三种可能,这也符合空间直线与球面相交的直观认识,要么相切有一个交点,要么相交有两个交点,否则的话可能没有交点。
得到ttt后,将其带入到(1)式中,就得到想要的交点。不过注意t的范围一般是0到1,这是与直线给的起点位置与终点位置有关的。
推到这里就会发现原来全部都是高中数学知识,应该还做过题目来着。
2. 具体实现
具体的C++实现如下:
#include <iostream>
#include <string>
#include <vector>using namespace std;const double EPSILON = 0.0000000001;// 3D vector
struct Vector3d
{public:Vector3d(){}~Vector3d(){}Vector3d(double dx, double dy, double dz){x = dx;y = dy;z = dz;}// 矢量赋值void set(double dx, double dy, double dz){x = dx;y = dy;z = dz;}// 矢量相加Vector3d operator + (const Vector3d& v) const{return Vector3d(x + v.x, y + v.y, z + v.z);}// 矢量相减Vector3d operator - (const Vector3d& v) const{return Vector3d(x - v.x, y - v.y, z - v.z);}//矢量数乘Vector3d Scalar(double c) const{return Vector3d(c*x, c*y, c*z);}// 矢量点积double Dot(const Vector3d& v) const{return x * v.x + y * v.y + z * v.z;}// 矢量叉积Vector3d Cross(const Vector3d& v) const{return Vector3d(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);}bool operator == (const Vector3d& v) const{if (abs(x - v.x) < EPSILON && abs(y - v.y) < EPSILON && abs(z - v.z) < EPSILON){return true;}return false;}double x, y, z;
};//求解一元二次方程组ax*x + b*x + c = 0
void SolvingQuadratics(double a, double b, double c, vector<double>& t)
{double delta = b * b - 4 * a * c;if (delta < 0){return;}if (abs(delta) < EPSILON){t.push_back(-b / (2 * a));}else{t.push_back((-b + sqrt(delta)) / (2 * a));t.push_back((-b - sqrt(delta)) / (2 * a));}
}void LineIntersectSphere(Vector3d& O, Vector3d& E, Vector3d& Center, double R, vector<Vector3d>& points)
{Vector3d D = E - O; //线段方向向量double a = (D.x * D.x) + (D.y * D.y) + (D.z * D.z);double b = (2 * D.x * (O.x - Center.x) + 2 * D.y * (O.y - Center.y) + 2 * D.z* (O.z - Center.z));double c = ((O.x - Center.x)*(O.x - Center.x) + (O.y - Center.y) * (O.y - Center.y) + (O.z - Center.z) * (O.z - Center.z)) - R * R;vector<double> t;SolvingQuadratics(a, b, c, t);for (auto it : t){ if (it >= 0 && it <= 1){points.push_back(O + D.Scalar(it));} }
}int main()
{Vector3d O(20, 30, 40);Vector3d E(20, 20, 20); Vector3d Center(20, 20, 20);double R = 15;vector<Vector3d> points;LineIntersectSphere(O, E, Center, R, points);cout<<"该直线(线段)与球面有"<< points.size() <<"个交点"<<endl;for (auto it : points){printf("%lf\t%lf\t%lf\n", it.x, it.y, it.z);}
}
最终运行的结果:
再次注意,我这里是把线段当成直线判断的,如果希望判断整个直线与球面的交点,应该略去最后的关于ttt是否在0到1之间的判断,此时应该会有两个交点。
3. 参考
- 空间直线同球体交点求解
空间直线与球面相交算法相关推荐
- 空间射线与三角形相交算法的两种实现
文章目录 1. 概述 2. 常规算法 2.1. 理论推导 2.2. 具体实现 3. 优化算法 3.1. 理论推导 3.2. 具体实现 4. 参考 1. 概述 任何复杂的三维模型都可以视作空间三角面片的 ...
- 基于带约束S型加减速曲线的空间直线插补与空间圆弧插补算法(Matlab)
写在前面 学习代码都记录在个人github上,欢迎关注~ Matlab机器人工具箱版本9.10 在前面的博文中: 基于抛物线过渡(梯形加减速)的空间直线插补算法与空间圆弧插补算法(Matlab) 基于 ...
- 图形学 射线相交算法_计算机图形学中的阴极射线管(CRT)
图形学 射线相交算法 什么是阴极射线管(CRT)? (What is Cathode Ray Tube (CRT)?) CRT stands for "Cathode Ray Tube&qu ...
- 【unity shader】unity游戏特效-仿《幽灵特警》生命扫描仪索敌效果(运用深度、相交算法、CommandBuffer)
街机游戏<幽灵特警>第一关有个这样的效果: 嗯,透视挂hhhh,关键很炫. 来做个吧. 第一步,做"墙" 仔细观察GIF可见,这个效果像是一堵向前跑的墙,撞到无生命物体 ...
- Möller-Trumbore算法-射线三角形相交算法
Möller-Trumbore算法 一.概述 二.准备知识 三.Möller-Trumbore 算法推导 推导过程 四.代码实现 一.概述 Möller-Trumbore 射线三角相交算法是一种快速计 ...
- 图形学 射线相交算法_计算机图形学中的彩色阴极射线管
图形学 射线相交算法 彩色阴极射线管 (Color Cathode Ray Tube) CRT i.e. Cathode Ray Tubes are used to produce Color dis ...
- 【转载】空间直线同任意形状椭球交点
空间直线同空间中三维椭球相交,其交点即为空间直线方程同椭球方程的解,对于空间直线方程,只要知道两点空间坐标即可,而欧拉角不为零的三维椭球方程则较难描述,但可以考虑对椭球进行变换,使其欧拉角为零,进而转 ...
- 图形学 射线相交算法_计算机图形学中的阴极射线管
图形学 射线相交算法 阴极射线管 (Cathode Ray Tube) Ferdinand Barun of Strasbourg developed the cathode ray tube in ...
- 空间直线和三维物体之间的交线相关问题
1.如何求空间直线在某一平面上的投影直线方程 https://zhidao.baidu.com/question/631349383625570644.html 2. 知道平面一点和平面法向量如何求平 ...
- 8.4 向量应用(二)——空间直线
本篇内容接上篇,还是关于向量应用的内容.没有废话,直接来. 空间直线方程 (一)点向式方程(对称式方程) 从名字上看,点向式两个关键,一个是点,一个是向,点是直线上一点,向是直线的方向,或者是和直线方 ...
最新文章
- java中获取时间的方式,持续更新
- 百度地图 开发 乡镇级区域显示_Tableau导入乡镇级地图进行数据展示
- 【Java】不正当使用break语句的危害
- AbstractQueuedSynchronizer浅析——同步
- Windows Phone标准中文字体
- nodejs实战案例(Express框架+mongoDB)——(15)——爬虫功能
- 怎么样快速修改HOSTS文件?让火绒等小工具来帮忙
- html5手机详情页,H5网页打开app内部详情页
- 前方高能!Netflix推出《怪奇物语》VR体验
- 带您认识弱电工程中常见光纤接头,再也不用傻傻分不清楚
- Java中带有T Z格式(UTC是世界标准时间)的时间转换为date,string,long类型
- 华为p10 android保活,华为P10这八大细节,请看完之后决定要不要买!
- 【BZOJ】4292: [PA2015]Równanie
- ata职业技能评价证书考出来有啥用?
- cad拉伸怎么用_【cad比例缩放教程】cad缩放怎么用?
- 基于阿里云的超级性能测试 亿级企业压力测试神器JMeter4.X实战 抗压神器JMeter课程
- Latex排版 Chapter2格式调整(长度单位、字体、段落、页面、目录)
- serverAdd.sin_addr.s_addr
- 浙江省c语言二级的笔试真题及答案,浙江省高等学校C语言二级----笔试部分真题2007-2010年.doc...
- 计算机应用于软件等待预审,1系统架构-计算机应用与软件.doc
热门文章
- windows日志总结
- u检验中的查u界值表_u检验、t检验、F检验、X2检验
- 四招搞定托业(TOEIC)英语阅读
- php程序 导出表格文件后缀,PHPExcel生成Excel文件---提示导出文件或者文件扩展名不一致,或导出的文件或文件扩展名无效...
- java 全量_七、通过java代码实现增量、全量索引
- 下一跳配置的原则--ensp
- php 打水印,PHP 给图片制作水印的方法
- axio深入实例以及配置
- CUDA矩阵转置(共享内存 tile)
- 组建服务计算机我的电脑有个下三角,excel小三角怎么弄出来