分段 – 汽缸相交

什么是完整的代码(C#,伪,无关紧要)计算结果段(或缺乏)的一个段和一个圆柱的交集?

该段由Vector3 (x,y,z)定义为StartVector3 (x,y,z)定义为End

气缸由相同的参数加上Radius的值定义。

带有可读符号和LaTeX格式的math解释 – 非常适合一年级或二年级本科学生或熟练的高中生。

那么,如果你需要了解它背后的math,而不是复制一些可能不太好的代码(从SO代码判断是否工作还不清楚)。 这里是步骤:

  • 如果圆柱体与Oxyz框架的Z轴alignment,find相交点更容易。

v = normalize(Cylinder.End – Cylinder.Start)

计算w = cross(v,vec3(0,0,1)) 。 如果w不是零向量,则必须对Cylinder和Segment执行T变换以使场景与oZ轴alignment:

T =旋转(w,arccos(点(v,z)))x平移( – Cylinder.Start)使用此变换查找变换圆柱体和段的坐标: Cylinder2 = T x Cylinder1Segment2 = T x Segment1 。 为了简单起见,我会将结果称为Cylinder和Segment。

  • 由于圆柱体与Z轴alignment,位于其表面上的点的方程为x ^ 2 + y ^ 2 = r ^ 2 ,所以对z分量没有约束。

(x0 + t(x1-x0),y0 + t(y1-y0),z0 + t(z1-z0))其中Segment.Start(x0,y0,z0)Segment.End (x1,y1,z1) 。 为了简单起见,让我们忘记v,w和所有直到现在使用的字母,并称为x1-x0 = u,y1-y0 = v,z1-z0 = w

这意味着段上的点被写为vec3(x0 + tu,y0 + tv,z0 + tw) ,其中t应该在[0,1]区间内! 还记得POINT也在圆柱体的表面上吗? 现在我们得到:

(x0 + tu)^ 2 +(y0 + tv)^ 2 = r ^ 2相当于

(u ^ 2 + v ^ 2)t ^ 2 + 2(u x0 + v y0)t + x0 ^ 2 + y0 ^ 2 – r ^ 2 = 0。

A =(u ^ 2 + v ^ 2),B = 2(u x0 + v y0)t,C = x0 ^ 2 + y0 ^ 2 -r ^ 2 。 你最终得到一个二次方程。 Delta = B ^ 2 – 4AC

  • 讨论:

如果德尔塔<0,你没有交集。

如果Delta = 0 ,则该段与气缸相切。

如果Delta> 0 ,则解出t给出t1t2

在POINT ON SEGMENT方程式中插入t1t2 ,并得到您的P1和P2点是候选。

请记住, t1t2必须介于[0和1]之间,以使P1和P2成为您网段上的点。 如果其中一个在[0,1]之外,则表示您的段在圆柱体内有一个终点。 如果t1,t2都在[0,1]之外,则线段的支撑线与圆柱相交,但不与您的线段相交。

最后一次检查,P1.z和P2.z应该在0和Cylinder.End.Z之间,因为你使用有限的柱面。

结束语:您必须在INITIAL SEGMENT方程中插入t1t2值来恢复交点。 就是这样,我没有时间总结一下C#代码片段,但我希望你明白该怎么做。

你可能会从这个问题find你正在寻找什么。 最后一个答案似乎符合你的要求,记得投票,如果它帮助你。