C# 两条三维线段交点的求法
查找两条二维线段的交点很容易。但是,恐怕找不到两条三维线段的交点 在C#中,最好是找到两条3D线段交点的算法是什么 我找到了一个新的。但我不相信这个解决方案,因为它会优先选择某个平面(看看在“实现”部分下实现C# 两条三维线段交点的求法,c#,math,C#,Math,查找两条二维线段的交点很容易。但是,恐怕找不到两条三维线段的交点 在C#中,最好是找到两条3D线段交点的算法是什么 我找到了一个新的。但我不相信这个解决方案,因为它会优先选择某个平面(看看在“实现”部分下实现perp的方式,它会优先选择z平面。任何通用算法都不能假设任何平面方向或偏好) 有更好的解决办法吗 但是,恐怕找不到两条三维线段的交点 我想是的。可以使用与二维(或任何其他标注)中完全相同的方式找到交点。唯一的区别是,由此产生的线性方程组更可能没有解(这意味着直线不相交) 您可以手工求解一般
perp
的方式,它会优先选择z平面
。任何通用算法都不能假设任何平面方向或偏好)
有更好的解决办法吗
但是,恐怕找不到两条三维线段的交点
我想是的。可以使用与二维(或任何其他标注)中完全相同的方式找到交点。唯一的区别是,由此产生的线性方程组更可能没有解(这意味着直线不相交)
您可以手工求解一般方程,只需使用您的解决方案,或使用编程方式求解,例如…我找到了一个解决方案:
这个想法是利用向量代数,使用点
和交叉
来简化问题,直到这个阶段:
a (V1 X V2) = (P2 - P1) X V2
并计算a
请注意,此实现不需要任何平面或轴作为参考 大多数三维线不相交。一种可靠的方法是在两条三维直线之间找到最短的直线。如果最短直线的长度为零(或距离小于指定的公差),则知道两条原始直线相交 查找方法总结/解释如下: 在下面的内容中,一条线将由其上的两个点定义,a 由点P1和P2定义的线“a”上的点有一个方程式
Pa = P1 + mua (P2 - P1)
类似地,第二条直线“b”上的点由点P4和P4定义
将写为
Pb = P3 + mub (P4 - P3)
mua和mub的值范围从负到正无穷大。
P1 P2和P3 P4之间的线段具有其相应的mu
介于0和1之间
有两种方法可以找到两条直线之间的最短线段
“a”和“b”行
方法一:
第一个是写下行的长度
将两条线连接起来,然后找出最小值。就是,
尽量减少以下情况
|| Pb - Pa ||^2
代入这些线的方程式得到
|| P1 - P3 + mua (P2 - P1) - mub (P4 - P3) ||^2
然后可以在(x,y,z)组件中展开上述内容
至少要满足以下条件,即
关于mua和mub的值必须为零。。。上述功能仅具有以下功能:
一个最小值,没有其他最小值或最大值。这两个方程可以
对于mua和mub,通过
将μ的值代入直线的原始方程
方法二:
另一种方法是,给出完全相同的方程
认识到两条线路之间的最短线段
垂直于这两条线。这让我们可以写两篇文章
点积方程
(Pa - Pb) dot (P2 - P1) = 0
(Pa - Pb) dot (P4 - P3) = 0
根据直线方程展开这些方程
( P1 - P3 + mua (P2 - P1) - mub (P4 - P3) ) dot (P2 - P1) = 0
( P1 - P3 + mua (P2 - P1) - mub (P4 - P3) ) dot (P4 - P3) = 0
用坐标(x,y,z)展开这些。。。
结果如下
d1321 + mua d2121 - mub d4321 = 0
d1343 + mua d4321 - mub d4343 = 0
在哪里
dmnop = (xm - xn)(xo - xp) + (ym - yn)(yo - yp) + (zm - zn)(zo - zp)
注意,dmnop=dopmn
最后,对mua进行求解,得到
mua = ( d1343 d4321 - d1321 d4343 ) / ( d2121 d4343 - d4321 d4321 )
而后面的替换会产生mub
mub = ( d1343 + mua d4321 ) / d4343
该方法是一种优秀的几何资源。站点已经被重新组织,所以向下滚动找到主题。 <代码> //此代码在C++中为我工作在2D和3D中。
// This code in C++ works for me in 2d and 3d
// assume Coord has members x(), y() and z() and supports arithmetic operations
// that is Coord u + Coord v = u.x() + v.x(), u.y() + v.y(), u.z() + v.z()
inline Point
dot(const Coord& u, const Coord& v)
{
return u.x() * v.x() + u.y() * v.y() + u.z() * v.z();
}
inline Point
norm2( const Coord& v )
{
return v.x() * v.x() + v.y() * v.y() + v.z() * v.z();
}
inline Point
norm( const Coord& v )
{
return sqrt(norm2(v));
}
inline
Coord
cross( const Coord& b, const Coord& c) // cross product
{
return Coord(b.y() * c.z() - c.y() * b.z(), b.z() * c.x() - c.z() * b.x(), b.x() * c.y() - c.x() * b.y());
}
bool
intersection(const Line& a, const Line& b, Coord& ip)
// http://mathworld.wolfram.com/Line-LineIntersection.html
// in 3d; will also work in 2d if z components are 0
{
Coord da = a.second - a.first;
Coord db = b.second - b.first;
Coord dc = b.first - a.first;
if (dot(dc, cross(da,db)) != 0.0) // lines are not coplanar
return false;
Point s = dot(cross(dc,db),cross(da,db)) / norm2(cross(da,db));
if (s >= 0.0 && s <= 1.0)
{
ip = a.first + da * Coord(s,s,s);
return true;
}
return false;
}
//假设Coord有成员x()、y()和z(),并支持算术运算
//这就是坐标u+coordv=u.x()+v.x(),u.y()+v.y(),u.z()+v.z()
内联点
dot(恒坐标和u、恒坐标和v)
{
返回u.x()*v.x()+u.y()*v.y()+u.z()*v.z();
}
内联点
norm2(const Coord&v)
{
返回v.x()*v.x()+v.y()*v.y()+v.z()*v.z();
}
内联点
标准(施工协调与验证)
{
返回sqrt(norm2(v));
}
内联
坐标
交叉(常数坐标和b,常数坐标和c)//交叉积
{
返回坐标(b.y()*c.z()-c.y()*b.z(),b.z()*c.x()-c.z()*b.x(),b.x()*c.y()-c.x()*b.y());
}
布尔
交叉口(常数线和a、常数线和b、坐标和ip)
// http://mathworld.wolfram.com/Line-LineIntersection.html
//在3d中;如果z组件为0,也将在二维中工作
{
坐标da=一秒-一秒;
坐标db=b.秒-b.第一;
坐标dc=b.first-a.first;
if(dot(dc,cross(da,db))!=0.0)//直线不共面
返回false;
点s=点(交叉点(直流,分贝),交叉点(直流,分贝))/norm2(交叉点(直流,分贝));
如果(s>=0.0&&s我尝试过,但实际上每次都不起作用,这我可以解释。基于,让我们以这两条线段为例AB和CD
var s = Vector3.Dot(Vector3.Cross(dc, db), Vector3.Cross(da, db)) / Norm2(Vector3.Cross(da, db));
var t = Vector3.Dot(Vector3.Cross(dc, da), Vector3.Cross(da, db)) / Norm2(Vector3.Cross(da, db));
A=(2,1,5),B=(1,2,5)和C=(2,1,3)和D=(2,1,2)
当您尝试获取交点时,它可能会告诉您这是点A(不正确)或没有交点(正确)。这取决于您放置这些线段的顺序
x=A+(B-A)sx=C+(D-C)t Bill为s求解,但从未求解t。既然您希望交点位于两条线段上,s和t都必须来自区间。在我的示例中,实际情况是只有s如果来自该区间和tis-2。A位于C和D定义的直线上,但不在线段CD上
var s = Vector3.Dot(Vector3.Cross(dc, db), Vector3.Cross(da, db)) / Norm2(Vector3.Cross(da, db));
var t = Vector3.Dot(Vector3.Cross(dc, da), Vector3.Cross(da, db)) / Norm2(Vector3.Cross(da, db));
其中da是B-A,db是D-C,dc是C-A,我只是保留了Bill提供的名称
然后就像我说的,你必须检查s和t是否都来自,你可以计算t
if ((s >= 0 && s <= 1) && (k >= 0 && k <= 1))
{
Vector3 res = new Vector3(this.A.x + da.x * s, this.A.y + da.y * s, this.A.z + da.z * s);
}