只检查,不需要找到点。坐标z不是0。堆栈溢出中的旧问题都是2d。提前致谢
有几种方法可以进行线 - 线交叉测试。经典的方法是使用线性代数(即求解线性矩阵系统),但从软件开发的角度来看,我更像是几何 - 代数方式,以Plucker坐标的形式,它只需要实现向量代数运算(即,交叉产品和点积产品比编码线性系统的矩阵运算更简单。
矢量代数解决方案
给定由点P1和P2限制的线段P和由点Q1和Q2限制的线段Q.
线的参数形式由下式给出:
P(t)= P1 + t(P2 - P1)
Q(t)= Q1 + t(Q2 - Q1)
其中t是区间[0 1]中的实数。
如果两条线相交,则以下等式成立:
P(t0)= Q(t1)
假设存在两个未知数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-a)P1-a P2)/ | 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都在区间[0 1]中,则存在交点P(t0)(或Q(t1))。
Plucker坐标方式
给定由点P1和P2限制的线段P和由点Q1和Q2限制的线段Q.
P行的Plucker坐标由一对3d矢量(Pd,Pm)给出:
Pd = P2-P1
Pm = P1×P2
其中Pm是P1和P2的交叉积。线Q的Plucker坐标(Qd,Qm)可以完全相同的方式计算。
如果它们是共面的,则线P和Q只能相交。线P和Q是共面的iif:
Pd•Qm + Qd•Pm = 0
其中(•)是点积。由于机器具有有限的精度,因此稳健的测试应检查不是零,而是少数。如果Pd×Qd = 0则线是平行的(这里0是零矢量)。同样,稳健的测试应该是(Pd×Qd)的平方长度很小的情况。
如果线不平行则它们是共面的并且它们的交叉点(在Plucker的行话中称为“meet”)将是重点:
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都没有通过原点,那么它们的Plucker坐标Pm和Qm将分别为非零,以下的sinpler公式将起作用
X = PM×GM /钯•了Gm
有关Plucker坐标的介绍,请参阅:
https://en.m.wikipedia.org/wiki/Plücker_coordinates
http://www.realtimerendering.com/resources/RTNews/html/rtnv11n1.html#art3
对于一般的交叉公式,请参阅:“推论6”:
http://web.cs.iastate.edu/~cs577/handouts/plucker-coordinates.pdf
线性代数方法
给定由点P1和P2限制的线段P和由点Q1和Q2限制的线段Q.
线的参数形式由下式给出:
P(t)= P1 + t(P2 - P1)
Q(t)= Q1 + t(Q2 - Q1)
其中t是区间[0 1]中的实数。
如果两条线相交,则以下等式成立:
P(t0)= Q(t1)
假设存在两个未知数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.
见:https://en.m.wikipedia.org/wiki/Generalized_inverse
幸运的是,Python中的任何矩阵包都应该能够非常容易地计算上述计算,也可能非常有效。
如果将A与其伪逆A ^ +相乘等于单位矩阵I,即(A A ^ +)== I,那么就有一个唯一的答案(交集),你可以得到它计算以下产品:
x = A ^ + B.
当然,如果你不能首先计算伪逆,例如,因为(A ^ T A)是单数(即行列式为零),则不存在交集。
由于我们正在处理段,如果x0和x1都在区间[0 1]中,则交点位于点P(x0)或Q(x1)。
我可以告诉你可以使用的数学(虽然它有点复杂)。您以参数形式为每条线编写等式。然后找到每一行的参数。见下面的例子:
(a1,a2,a3)________________(b1,b2,b3)
A B
and second line
(c1,c2,c3)________________(d1,d2,d3)
C D
因此,对于第一行,等式将是A + t(BA)(这实际上表示t在0和1之间的线段上的点)和对于第二行的C + s(DC)其中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之间,以使该点真正位于线段上。所以我希望你能得到它:)代码:
#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')
这是代码段.hope你终于明白了:)