判断空间中两条线段是不是有交点
判断原理:
- 先判断线段四点在空间中是否共面
可以用行列式来判断
用四个点求出三个向量分别为(x1,y1,z1),(x2,y2,z2),(x3,y3,z3)
判断行列式
| x1 x2 x3|
| y1 y2 y3|
| z1 z2 z3|
或者它的转置是否为零
若为零则四点共面 - 判断平面内两线段是否有交点
快速排斥实验+跨立实验
算法详解可以了解:
快速排斥、跨立实验判断线段是否相交
代码如下
public bool intersect(double[] aa, double[] bb, double[] cc, double[] dd)
double x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4, r1, r2, r3, r4, r5, r6, r7, r8, r9;
for (int i = 0; i < 3; i++) //将数组中的所有值保留两位小数点
{
aa[i] = Math.Round(aa[i],2) ;
bb[i] = Math.Round(bb[i],2) ;
cc[i] = Math.Round(cc[i], 2);
dd[i] = Math.Round(dd[i], 2);
}
x1 = aa[0]; x2 = bb[0];x3 = cc[0];x4 = dd[0];
y1 = aa[1]; y2 = bb[1]; y3 = cc[1]; y4 = dd[1];
z1 = aa[2]; z2 = bb[2]; z3 = cc[2]; z4 = dd[2];
//计算行列式,判断其行列式值是否为0,说明四点是否共面
r1 = x1 - x2; r2 = y1 - y2; r3 = z1 - z2;
r4 = x1 - x3; r5 = y1 - y3; r6 = z1 - z3;
r7 = x1 - x4; r8 = y1 - y4; r9 = z1 - z4;
if (r1 * r5 * r9 + r2 * r6 * r7 + r3 * r8 * r4 - r1 * r8 * r6 - r2 * r4 * r9 - r3 * r5 * r7 == 0)
{
//快速排斥实验+跨立实验
if (!Fequ(Math.Max(aa[0], bb[0]), Math.Min(cc[0], dd[0])) && Math.Max(aa[0], bb[0]) < Math.Min(cc[0], dd[0]))
{
return false;
}
if (!Fequ(Math.Max(aa[1], bb[1]), Math.Min(cc[1], dd[1])) && Math.Max(aa[1], bb[1]) < Math.Min(cc[1], dd[1]))
{
return false;
}
if (!Fequ(Math.Max(cc[0], dd[0]), Math.Min(aa[0], bb[0])) && Math.Max(cc[0], dd[0]) < Math.Min(aa[0], bb[0]))
{
return false;
}
if (!Fequ(Math.Max(cc[1], dd[1]), Math.Min(aa[1], bb[1])) && Math.Max(cc[1], dd[1]) < Math.Min(aa[1], bb[1]))
{
return false;
}
if (mult(cc, bb, aa) * mult(bb, dd, aa) < 0)
{
return false;
}
if (mult(aa, dd, cc) * mult(dd, bb, cc) < 0)
{
return false;
}
return true;
}
else
{
return false;
}
}
double mult(double[] a, double[] b, double[] c) //叉积计算,c为共用节点
{
double aa= (a[0] - c[0]) * (b[1] - c[1]) - (b[0] - c[0]) * (a[1] - c[1]);
return (a[0] - c[0]) * (b[1] - c[1]) - (b[0] - c[0]) * (a[1] - c[1]);
}