Python 如何检测两段(在三维空间中)是否相交?

Python 如何检测两段(在三维空间中)是否相交?,python,3d,intersect,segment,Python,3d,Intersect,Segment,只检查,不需要找到重点 坐标z不是0。 堆栈溢出中的旧问题都是针对2d的。 提前谢谢我可以告诉你你可以使用的数学,尽管它有点复杂。 以参数形式为每一行编写方程式。然后找到每行的参数。 见下例: (a1,a2,a3)________________(b1,b2,b3) A B and second line (c1,c2,c3)________________(d1,d2,d3) C

只检查,不需要找到重点 坐标z不是0。 堆栈溢出中的旧问题都是针对2d的。
提前谢谢

我可以告诉你你可以使用的数学,尽管它有点复杂。 以参数形式为每一行编写方程式。然后找到每行的参数。 见下例:

(a1,a2,a3)________________(b1,b2,b3)
A                           B 


and second line 
(c1,c2,c3)________________(d1,d2,d3)
C                            D
所以这个等式是 A+tB-A表示第一条直线这实际上表示t在0和1之间的线段上的一个点 和 第二条线路的C+sD-C 其中t和s是参数 其值应介于0和1之间,以使点位于线段上。0是A,1是B 这里A的意思是a1,a2,a3 因此,你可以将交点的两个方程(如果有)相等,并找到满足三个方程的t和s:

  a1+t(b1-a1)=c1+s(d1-c1)
  a2+t(b2-a2)=c2+s(d2-c2)
  a3+t(b3-a3)=c3+s(d3-c3)
t和s应介于0和1之间,以使点真正位于线段上。所以我希望你能明白: 代码:


这是代码段。希望您最终得到它:

有几种方法可以进行直线相交测试。经典的方法是使用线性代数,即求解线性矩阵系统,但从软件开发的角度来看,我更喜欢几何代数方法,以Pucker坐标的形式,它只需要实现向量代数运算,即。,在求解线性系统时,叉积和点积比矩阵运算更易于编码

向量代数解

给定线段p受点P1和P2限制,线段Q受点Q1和Q2限制

线的参数化形式如下所示:

Pt=P1+tp2-P1

Qt=Q1+tq2-Q1

其中t是区间[0 1]中的实数

如果两条线相交,则以下等式成立:

Pt0=Qt1

假设存在两个未知数字t0和t1。将上述方程展开,我们得到:

t0 P2-P1-t1 Q2-Q1=Q1-P1

为了避免处理矩阵代数,我们可以尝试使用向量代数和替换法求解系统:

t0 P2-P1-t1 Q2-Q1=Q1-P1

t0=a+t1+b

t1=C•Q1-1-AP1-AP2/|C^2

其中:

a=P2-P1•Q1-P1/| P2-P1 | ^2

b=P2-P1•Q2-Q1/| P2-P1 | ^2

C=b P2-P1-Q2-Q1

其中•是点积。如果t0和t1都在区间[01]内,则交点Pt0或Qt1存在

采摘机坐标方式

给定线段p受点P1和P2限制,线段Q受点Q1和Q2限制

线p的拾取器坐标由一对3d向量Pd,Pm给出:

Pd=P2-P1

Pm=P1×P2

式中,Pm是P1和P2的叉积。可以用完全相同的方法计算线Q的采摘器坐标Qd,Qm

线p和Q只有在共面时才能相交。线P和Q是共面iif:

Pd•Qm+Qd•Pm=0

其中•是点积。由于机器的精度有限,稳健测试不应检查零,而应检查少量。如果Pd×Qd=0,则直线平行,此处0为零矢量。同样,应针对instamce进行稳健测试,以确保Pd×Qd的平方长度较小

如果两条线不平行,那么它们是共面的,它们的相交点在普莱克的行话中称为相交点:

x=Pm•N Qd-Qm•N Pd-Pm•Qd N/Pd×Qd•N

其中N是任意坐标轴向量,即1,0,0或0,1,0或0,0,1,使得Pd×Qd•N为非零

如果p和Q均未通过原点,则其采摘器坐标Pm和Qm将分别为非零,且以下sinpler公式将起作用

x=Pm×Qm/Pd•Qm

有关采摘器坐标的介绍,请参见:

关于一般的交点公式,请参见推论6:

线性代数方法

给定线段p受点P1和P2限制,线段Q受点Q1和Q2限制

线的参数化形式如下所示:

Pt=P1+tp2-P1

Qt=Q1+tq2-Q1

其中t是区间[0 1]中的实数

如果两条线相交,则以下等式成立:

Pt0=Qt1

假设存在两个未知数字t0和t1。将上述方程展开,我们得到:

t0 P2-P1-t1 Q2-Q1=Q1-P1

我们可以通过在矩阵代数中表示上述方程来求解t0和t1:

A x=B

其中,A是3x2矩阵,向量P2-P1的坐标在第一列,向量Q2-Q1的坐标在第二列;x是未知量t0和t1的2x1列向量,B是坐标为矢量Q1-P1的3x1列向量

经典地,系统可以通过计算矩阵A的伪逆来求解,表示为A^+:

A^+=A^T A^-1 A^T

见:

幸运的是,Python中的任何矩阵包都应该能够计算上述计算 这很容易,也许也很有效

如果将A与其伪逆A^+相乘等于单位矩阵I,即A^+==I,则存在唯一答案交点,您可以通过计算以下乘积得到它:

x=A^+B

当然,如果你首先不能计算伪逆,例如,因为A^ta是奇异的,即行列式为零,那么就不存在交集


因为我们处理的是线段,交点在点Px0或Qx1,如果x0和x1都在区间[01]。

thx很多!但是除了使用Symphy库之外,我不知道如何解决它。起初,我使用Symphy 3dsegment处理它,但是当我导入Symphy时,然后我将无法通过pyinstaller/py2exe将.py文件编译为.exe文件。然后我希望任何人都能给出一种只使用标准库的方法。我不知道sympy3d。。。如果您正在使用此方法,则不需要使用它。可以使用numpy来求解方程。否则,不需要任何特殊模块。您可以使用numpy搜索解联立方程组。也不能使用numpy,可能会导致编译到exe文件失败或文件非常大。如果您不能使用任何库,则必须使用纯数学解联立方程组!这是我的愿望,但我不知道怎么做,你能给我一些建议吗?Pm•N和Pm•N Qd中的Qd之间的操作是什么?这是标量乘法吗?@VictorSg是的,这是标量乘法,也称为标量积。
#input a1,a2,a3 and all the other components here. 

#define all constants required for solving t and s
A=b1-a1
B=c1-d1
C=c1-a1
D=b2-a2
E=c2-d2
F=c2-a2

#find t and s using formula
t=(C*E-F*B)/(E*A-B*D)
s=(D*C-A*F)/(D*B-A*E)

#check if third equation is also satisfied(we have 3 equations and 2 variable
if ((t*(b3-a3)+s*(c3-d3))==c3-a3):
    if(0<=t<=1 and 0<=s<=1):
       print('line segments intersect')
    else:
       print ('line segments intersect on being produced')