• 1. 原理推导
• 1.1. 直线公式
• 1.2. 求交
• 2. 具体实现
• 3. 参考

# 1. 原理推导

## 1.1. 直线公式

$\frac{x-x_0}{m} = \frac{y-y_0}{n} = \frac{z-z_0}{p}$

$\begin{cases} x = x_0 + m * t\\ y = y_0 + n * t\\ z = z_0 + p * t\\ \end{cases}$

$P=O+tD$

$\begin{cases} x = O_x + D_x * t\\ y = O_y + D_y * t\\ z = O_z + D_z * t\\ \end{cases} \tag {1}$

## 1.2. 求交

$(X-C_x)^2 + (Y-C_y)^2 + (Z-C_z)^2 = R^2 \tag{2}$

$(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$

# 2. 具体实现

#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);
}
}

# 3. 参考

1. 空间直线同球体交点求解

0 条评论

• ### 空间射线与三角形相交算法的两种实现

任何复杂的三维模型都可以视作空间三角面片的集合，很容易碰到的一个问题就是空间射线与三角形相交的问题，例如拾取、遮蔽检测等。这里就总结下该问题的两种算法实现。

• ### 判断点在多边形内算法的C++实现

判断平面内点是否在多边形内有多种算法，其中射线法是其中比较好理解的一种，而且能够支持凹多边形的情况。该算法的思路很简单，就是从目标点出发引一条射线，看这条射线和...

• ### harris角点检测的简要总结

harris角点检测是一种特征提取的方法，而特征提取正是计算机视觉的一种重要手段。尽管它看起来很复杂，其实也是基于数学原理和简单的图像处理来实现的。 本文之前...

• ### C编程常用数学函数集锦

double sqrt(double x) 返回x的开方 double cos(double x) 返回x的余弦cos(x)值,x为弧度 double si...

• ### java计算两个经纬度之间的距离

前一阵项目中，有一个需求：是查找附近的人，其实就是查询某个距离内有多少用户。实现方式还是比较简单的，首先用户在APP上开启定位权限，将自己的经纬度都存储到数据库...

• ### c++(三)

函数在调用之前必须进行声明或者定义,函数的声明:返回值类型 函数名(参数类型 参数名称.......);其中参数名称可以省略;

• ### 爬虫篇 | 学习Selenium并使用Selenium模拟登录知乎

最近整理一个爬虫系列方面的文章，不管大家的基础如何，我从头开始整一个爬虫系列方面的文章，让大家循序渐进的学习爬虫，小白也没有学习障碍.

• ### C++中的数学函数汇总

math.h 数学函数库,一些数学计算的公式的具体实现是放在math.h里,具体有：