我试图找到一个球体和一条线之间的交点,但老实说,我不知道如何去做。 任何人都可以帮助我解决这个问题吗?一条线和一个球体之间的相交
回答
找到描述线条和球体的(x,y,z)中两个方程的解。
可能有0,1或2个解决方案。
- 0意味着它们不相交
- 1意味着该线的切线球体
- 2意味着线穿过球体。
查找“射线球体相交” - 同一测试用于射线追踪的所有时间,并且有大量在线示例,甚至在stackoverflow上也有quite a few here。
快速行作为t
一个功能:
{ x(t) = x0*(1-t) + t*x1
{ y(t) = y0*(1-t) + t*y1
{ z(t) = z0*(1-t) + t*z1
当t = 0
,这将是在一端点(x0,y0,z0)
。当t = 1
时,它将在另一个终点(x1,y1,z1)
。
写出到球体的中心的距离的公式(平方)在t
(其中(xc,yc,zc)
是球体的中心):
f(t) = (x(t) - xc)^2 + (y(t) - yc)^2 + (z(t) - zc)^2
求解t
当f(t)
等于R^2
(R
作为球体的半径):
(x(t) - xc)^2 + (y(t) - yc)^2 + (z(t) - zc)^2 = R^2
A = (x0-xc)^2 + (y0-yc)^2 + (z0-zc)^2 - R^2
B = (x1-xc)^2 + (y1-yc)^2 + (z1-zc)^2 - A - C - R^2
C = (x0-x1)^2 + (y0-y1)^2 + (z0-z1)^2
解决A + B*t + C*t^2 = 0
为t
。这是一个正常的quadratic equation。
您最多可以获得两种解决方案。 t
位于0和1之间的任何解决方案均有效。
如果您获得了t
的有效解决方案,请将其插入第一个方程中以获得交点。
我认为你的意思是一个线段(两个终点)。如果你想要一整行(无限长),那么你可以选择沿线的两个点(不要太靠近),并使用它们。也让t
是任意实值,而不仅仅是1.编辑介于0和
:我固定公式B
。我正在混合的迹象。谢谢M Katz,提到它没有用。
您可以使用Wolfram Alpha在球体居中的坐标系中求解它。
在这个系统中,方程为:
球:
x^2 + y^2 + z^2 = r^2
直线:
x = x0 + Cos[x1] t
y = y0 + Cos[y1] t
z = z0 + Cos[z1] t
Then we ask Wolfram Alpha to solve for t:(试试吧!)
之后,你可能会再次改变为您的原始坐标系(简单翻译)
我相信Markus Jarderot在解决方案中存在不准确的地方。不知道问题出在哪里,但我确信我将它忠实地转化为代码,并且当我试图找到已知交叉成球体的线段的交集时,我得到了否定判别(无解)。
我发现这个:http://www.codeproject.com/Articles/19799/Simple-Ray-Tracing-in-C-Part-II-Triangles-Intersec,它给出了一个类似但略有不同的派生。
我转身到这下面的C#代码和它的工作对我来说:使用内积,小于100条交通线,并没有外部链接
public static Point3D[] FindLineSphereIntersections(Point3D linePoint0, Point3D linePoint1, Point3D circleCenter, double circleRadius)
{
// http://www.codeproject.com/Articles/19799/Simple-Ray-Tracing-in-C-Part-II-Triangles-Intersec
double cx = circleCenter.X;
double cy = circleCenter.Y;
double cz = circleCenter.Z;
double px = linePoint0.X;
double py = linePoint0.Y;
double pz = linePoint0.Z;
double vx = linePoint1.X - px;
double vy = linePoint1.Y - py;
double vz = linePoint1.Z - pz;
double A = vx * vx + vy * vy + vz * vz;
double B = 2.0 * (px * vx + py * vy + pz * vz - vx * cx - vy * cy - vz * cz);
double C = px * px - 2 * px * cx + cx * cx + py * py - 2 * py * cy + cy * cy +
pz * pz - 2 * pz * cz + cz * cz - circleRadius * circleRadius;
// discriminant
double D = B * B - 4 * A * C;
if (D < 0)
{
return new Point3D[ 0 ];
}
double t1 = (-B - Math.Sqrt (D))/(2.0 * A);
Point3D solution1 = new Point3D(linePoint0.X * (1 - t1) + t1 * linePoint1.X,
linePoint0.Y * (1 - t1) + t1 * linePoint1.Y,
linePoint0.Z * (1 - t1) + t1 * linePoint1.Z);
if (D == 0)
{
return new Point3D[] { solution1 };
}
double t2 = (-B + Math.Sqrt(D))/(2.0 * A);
Point3D solution2 = new Point3D(linePoint0.X * (1 - t2) + t2 * linePoint1.X,
linePoint0.Y * (1 - t2) + t2 * linePoint1.Y,
linePoint0.Z * (1 - t2) + t2 * linePoint1.Z);
// prefer a solution that's on the line segment itself
if (Math.Abs(t1 - 0.5) < Math.Abs(t2 - 0.5))
{
return new Point3D[] { solution1, solution2 };
}
return new Point3D[] { solution2, solution1 };
}
这里有一个更简洁的提法。此外,该问题被要求提供一条线,而不是线段。
假设球体的中心位置为C
,半径为r
。该行描述为P+l*D
,其中D*D=1
。 P
和C
是分,D
是一个向量,l
是一个数字。
我们设置了PC = P-C
,pd = PC*D
和s = pd*pd - PC*PC + r*r
。如果s < 0
没有解决方案,如果s == 0
只有一个,否则有两个。对于我们设置的解决方案l = -pd +- sqrt(s)
,然后插入P+l*D
。
或者你可以找到两者的公式:
line:(x-x0)/a=(y-y0)/b=(z-z0)/c
,它们是点之间的线段的对称方程,你可以找到。
球体:(x-xc)^2+(y-yc)^2+(z-zc)^2 = R^2
。
使用对称方程找出x和y以及x和z之间的关系。
然后插入y和z到x的球形方程。
然后找到x,然后你可以找到y和z。
如果x给出了一个假想的结果,那就意味着该线和该球体不相交。
没有足够的声望来评论M Katz的答案,但他的回答假设这条线可以在每个方向上无限地进行。如果只需要SEGMENT的交点,则需要t1和t2小于1(根据参数化方程的定义)。请参阅我的回答如下C#:
public static Point3D[] FindLineSphereIntersections(Point3D linePoint0, Point3D linePoint1, Point3D circleCenter, double circleRadius)
{
double cx = circleCenter.X;
double cy = circleCenter.Y;
double cz = circleCenter.Z;
double px = linePoint0.X;
double py = linePoint0.Y;
double pz = linePoint0.Z;
double vx = linePoint1.X - px;
double vy = linePoint1.Y - py;
double vz = linePoint1.Z - pz;
double A = vx * vx + vy * vy + vz * vz;
double B = 2.0 * (px * vx + py * vy + pz * vz - vx * cx - vy * cy - vz * cz);
double C = px * px - 2 * px * cx + cx * cx + py * py - 2 * py * cy + cy * cy +
pz * pz - 2 * pz * cz + cz * cz - circleRadius * circleRadius;
// discriminant
double D = B * B - 4 * A * C;
double t1 = (-B - Math.Sqrt(D))/(2.0 * A);
Point3D solution1 = new Point3D(linePoint0.X * (1 - t1) + t1 * linePoint1.X,
linePoint0.Y * (1 - t1) + t1 * linePoint1.Y,
linePoint0.Z * (1 - t1) + t1 * linePoint1.Z);
double t2 = (-B + Math.Sqrt(D))/(2.0 * A);
Point3D solution2 = new Point3D(linePoint0.X * (1 - t2) + t2 * linePoint1.X,
linePoint0.Y * (1 - t2) + t2 * linePoint1.Y,
linePoint0.Z * (1 - t2) + t2 * linePoint1.Z);
if (D < 0 || t1 > 1 || t2 >1)
{
return new Point3D[0];
}
else if (D == 0)
{
return new [] { solution1 };
}
else
{
return new [] { solution1, solution2 };
}
}
还有一条评论,我的代码不完整 - 参数化线的定义是0
感谢您粘贴您的代码。不过我可能会发现一个错误。我正在查看一个线段,该线段开始于一个球体之外并进入一个球体,但交叉点返回null(空数组)。请参阅:http://paste.ofcode.org/aJSjXFpXvvRGf5hYcn8M9Q。我非常感谢对此的评论,谢谢! – 2016-02-23 19:57:15
我没有名声上Ashavsky的解决方案发表评论,但在最后的检查需要多一点的调整。
if (D < 0)
return new Point3D[0];
else if ((t1 > 1 || t1 < 0) && (t2 > 1 || t2 < 0))
return new Point3D[0];
else if (!(t1 > 1 || t1 < 0) && (t2 > 1 || t2 < 0))
return new [] { solution1 };
else if ((t1 > 1 || t1 < 0) && !(t2 > 1 || t2 < 0))
return new [] { solution2 };
else if (D == 0)
return new [] { solution1 };
else
return new [] { solution1, solution2 };
- 1. 一条线和一个球体相交?
- 2. 找到一条线和一条QPainterPath之间的交点
- 3. three.js - 射线相交和球体位置
- 4. 2条相交线之间的像素
- 5. 如何消除两个球体之间的点相交
- 6. 样条和直线之间的交点
- 7. 球体和三维线段之间的交点的具体位置
- 8. 查找相交的线和三次样条之间的点
- 9. Objective-C中一条直线和一个点之间的距离?
- 10. 2个对象之间的相交线
- 11. 射线球相交的相交问题
- 12. pygame中的一个球和一个矩形之间的碰撞
- 13. 如何阻止一条线段与另一条线段相交?
- 14. 在一条线上移动一个点:用两条线之间的线
- 15. 在两个拉斐尔物体之间拖动画一条线
- 16. VTK:一架飞机和一架Polydata之间的相交处
- 17. 填充两条相交的线之间的区域?
- 18. 查找点时两个球体相交
- 19. C++检查两个球体相交/ Collidiing
- 20. 一组线条之间的距离
- 21. 两条移动线段(或一条移动线段和一个点)的交集
- 22. 两条线之间的交点,Wolfram Mathematica
- 23. Neo4j空间 - 找到一个多边形和一条线的交点
- 24. Three.js - 在相机方向和球体交点处画一个大点
- 25. 蟒蛇(tkinter)中的一条直线和一个圆之间的碰撞检测
- 26. Android:找到一条线和一个图像的交叉点
- 27. C程序来计算一个点和一条线之间的距离
- 28. SpatialLinesDataFrame:如何计算最小值。一个点和一条线之间的距离
- 29. 一个点和一条直线之间的最小垂直向量
- 30. 在地点点之间画一条线
[我的回答](http://stackoverflow.com/a/5883559/22364)中'B'的公式是错误的。我现在修好了。 – 2013-07-06 11:54:21
这对我来说非常合适,我也能够快速将其转换为Java。 – 2015-04-22 11:06:16