如何计算两条线的交点?
- 2025-02-11 09:50:00
- admin 原创
- 50
问题描述:
我有两条线相交于一点。我知道这两条线的端点。如何在 Python 中计算交点?
# Given these endpoints
#line 1
A = [X, Y]
B = [X, Y]
#line 2
C = [X, Y]
D = [X, Y]
# Compute this:
point_of_intersection = [X, Y]
解决方案 1:
与其他建议不同,这个建议很短,并且不使用外部库numpy
。(并不是说使用其他库不好……不需要这样做很好,尤其是对于这样一个简单的问题。)
def line_intersection(line1, line2):
xdiff = (line1[0][0] - line1[1][0], line2[0][0] - line2[1][0])
ydiff = (line1[0][1] - line1[1][1], line2[0][1] - line2[1][1])
def det(a, b):
return a[0] * b[1] - a[1] * b[0]
div = det(xdiff, ydiff)
if div == 0:
raise Exception('lines do not intersect')
d = (det(*line1), det(*line2))
x = det(d, xdiff) / div
y = det(d, ydiff) / div
return x, y
print line_intersection((A, B), (C, D))
仅供参考,对于您的观点,我会使用元组而不是列表。例如
A = (X, Y)
编辑:最初有一个拼写错误。感谢 @zidik,该问题已于 2014 年 9 月修复。
这只是以下公式的 Python 音译,其中线为 ( a1 , a2 ) 和 ( b1 , b2 ),交点为p。 (如果分母为零,则线没有唯一的交点。)
解决方案 2:
不能袖手旁观,
因此我们有线性系统:
A1 *x+B1
y = C1A2 x+B2 y = C2
让我们用克莱姆规则来做,这样就可以在行列式中找到解决方案:
x = D x / D
y = D y / D
其中D是系统的主要决定因素:
A 1 B 1
A 2 B 2
并且D x和D y可以通过矩阵找到:
C1B1C2B2
和
A1C1A2C2
(注意,C列随后替换了x和y的系数列)
现在,为了便于理解,为了不弄乱,让我们在数学和 Python 之间进行映射。我们将使用数组L
来存储线方程的系数A、B、C,而不是 pretty x
,y
我们将有[0]
,[1]
,但无论如何。因此,我上面写的内容在代码中将具有以下形式:
对于D
L1[0] L1[1]
L2[0] L2[1]
对于D x
L1[2] L1[1]
L2[2] L2[1]
对于D y
L1[0] L1[2]
L2[0] L2[2]
现在开始编码:
line
-根据提供的两点计算直线方程的系数A , B , C
intersection
, - 根据系数找到两条直线的交点(如果有)。
from __future__ import division
def line(p1, p2):
A = (p1[1] - p2[1])
B = (p2[0] - p1[0])
C = (p1[0]*p2[1] - p2[0]*p1[1])
return A, B, -C
def intersection(L1, L2):
D = L1[0] * L2[1] - L1[1] * L2[0]
Dx = L1[2] * L2[1] - L1[1] * L2[2]
Dy = L1[0] * L2[2] - L1[2] * L2[0]
if D != 0:
x = Dx / D
y = Dy / D
return x,y
else:
return False
使用示例:
L1 = line([0,1], [2,3])
L2 = line([2,3], [0,4])
R = intersection(L1, L2)
if R:
print "Intersection detected:", R
else:
print "No single intersection point detected"
解决方案 3:
这是使用Shapely库的解决方案。Shapely 通常用于 GIS 工作,但其设计初衷是用于计算几何。我将您的输入从列表更改为元组。
问题
# Given these endpoints
#line 1
A = (X, Y)
B = (X, Y)
#line 2
C = (X, Y)
D = (X, Y)
# Compute this:
point_of_intersection = (X, Y)
解决方案
import shapely
from shapely.geometry import LineString, Point
line1 = LineString([A, B])
line2 = LineString([C, D])
int_pt = line1.intersection(line2)
point_of_intersection = int_pt.x, int_pt.y
print(point_of_intersection)
解决方案 4:
使用公式来自:
https: //en.wikipedia.org/wiki/Line%E2%80%93line_intersection
def findIntersection(x1,y1,x2,y2,x3,y3,x4,y4):
px= ( (x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4) ) / ( (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4) )
py= ( (x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4) ) / ( (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4) )
return [px, py]
解决方案 5:
如果您的线是多个点,则可以使用此版本。
import numpy as np
import matplotlib.pyplot as plt
"""
Sukhbinder
5 April 2017
Based on:
"""
def _rect_inter_inner(x1,x2):
n1=x1.shape[0]-1
n2=x2.shape[0]-1
X1=np.c_[x1[:-1],x1[1:]]
X2=np.c_[x2[:-1],x2[1:]]
S1=np.tile(X1.min(axis=1),(n2,1)).T
S2=np.tile(X2.max(axis=1),(n1,1))
S3=np.tile(X1.max(axis=1),(n2,1)).T
S4=np.tile(X2.min(axis=1),(n1,1))
return S1,S2,S3,S4
def _rectangle_intersection_(x1,y1,x2,y2):
S1,S2,S3,S4=_rect_inter_inner(x1,x2)
S5,S6,S7,S8=_rect_inter_inner(y1,y2)
C1=np.less_equal(S1,S2)
C2=np.greater_equal(S3,S4)
C3=np.less_equal(S5,S6)
C4=np.greater_equal(S7,S8)
ii,jj=np.nonzero(C1 & C2 & C3 & C4)
return ii,jj
def intersection(x1,y1,x2,y2):
"""
INTERSECTIONS Intersections of curves.
Computes the (x,y) locations where two curves intersect. The curves
can be broken with NaNs or have vertical segments.
usage:
x,y=intersection(x1,y1,x2,y2)
Example:
a, b = 1, 2
phi = np.linspace(3, 10, 100)
x1 = a*phi - b*np.sin(phi)
y1 = a - b*np.cos(phi)
x2=phi
y2=np.sin(phi)+2
x,y=intersection(x1,y1,x2,y2)
plt.plot(x1,y1,c='r')
plt.plot(x2,y2,c='g')
plt.plot(x,y,'*k')
plt.show()
"""
ii,jj=_rectangle_intersection_(x1,y1,x2,y2)
n=len(ii)
dxy1=np.diff(np.c_[x1,y1],axis=0)
dxy2=np.diff(np.c_[x2,y2],axis=0)
T=np.zeros((4,n))
AA=np.zeros((4,4,n))
AA[0:2,2,:]=-1
AA[2:4,3,:]=-1
AA[0::2,0,:]=dxy1[ii,:].T
AA[1::2,1,:]=dxy2[jj,:].T
BB=np.zeros((4,n))
BB[0,:]=-x1[ii].ravel()
BB[1,:]=-x2[jj].ravel()
BB[2,:]=-y1[ii].ravel()
BB[3,:]=-y2[jj].ravel()
for i in range(n):
try:
T[:,i]=np.linalg.solve(AA[:,:,i],BB[:,i])
except:
T[:,i]=np.NaN
in_range= (T[0,:] >=0) & (T[1,:] >=0) & (T[0,:] <=1) & (T[1,:] <=1)
xy0=T[2:,in_range]
xy0=xy0.T
return xy0[:,0],xy0[:,1]
if __name__ == '__main__':
# a piece of a prolate cycloid, and am going to find
a, b = 1, 2
phi = np.linspace(3, 10, 100)
x1 = a*phi - b*np.sin(phi)
y1 = a - b*np.cos(phi)
x2=phi
y2=np.sin(phi)+2
x,y=intersection(x1,y1,x2,y2)
plt.plot(x1,y1,c='r')
plt.plot(x2,y2,c='g')
plt.plot(x,y,'*k')
plt.show()
解决方案 6:
我在网上没有找到直观的解释,所以现在我找到了答案,下面是我的解决方案。这是针对无限线(我需要的),而不是线段。
您可能还记得一些术语:
直线定义为 y = mx + b 或 y = 斜率 * x + y 截距
坡度 = 上升量 / 下降量 = dy / dx = 高度 / 距离
Y 截距是直线与 Y 轴的交点,其中 X = 0
根据这些定义,这里有一些函数:
def slope(P1, P2):
# dy/dx
# (y2 - y1) / (x2 - x1)
return(P2[1] - P1[1]) / (P2[0] - P1[0])
def y_intercept(P1, slope):
# y = mx + b
# b = y - mx
# b = P1[1] - slope * P1[0]
return P1[1] - slope * P1[0]
def line_intersect(m1, b1, m2, b2):
if m1 == m2:
print ("These lines are parallel!!!")
return None
# y = mx + b
# Set both lines equal to find the intersection point in the x direction
# m1 * x + b1 = m2 * x + b2
# m1 * x - m2 * x = b2 - b1
# x * (m1 - m2) = b2 - b1
# x = (b2 - b1) / (m1 - m2)
x = (b2 - b1) / (m1 - m2)
# Now solve for y -- use either line, because they are equal here
# y = mx + b
y = m1 * x + b1
return x,y
这是两条(无限)线之间的简单测试:
A1 = [1,1]
A2 = [3,3]
B1 = [1,3]
B2 = [3,1]
slope_A = slope(A1, A2)
slope_B = slope(B1, B2)
y_int_A = y_intercept(A1, slope_A)
y_int_B = y_intercept(B1, slope_B)
print(line_intersect(slope_A, y_int_A, slope_B, y_int_B))
输出:
(2.0, 2.0)
解决方案 7:
我发现的最简洁的解决方案是使用 Sympy: https: //www.geeksforgeeks.org/python-sympy-line-intersection-method/
# import sympy and Point, Line
from sympy import Point, Line
p1, p2, p3 = Point(0, 0), Point(1, 1), Point(7, 7)
l1 = Line(p1, p2)
# using intersection() method
showIntersection = l1.intersection(p3)
print(showIntersection)
解决方案 8:
使用scikit-spatial库,您可以按照以下方式轻松完成此操作:
import matplotlib.pyplot as plt
from skspatial.objects import Line
# Define the two lines.
line_1 = Line.from_points([3, -2], [5, 4])
line_2 = Line.from_points([-1, 0], [3, 2])
# Compute the intersection point
intersection_point = line_1.intersect_line(line_2)
# Plot
_, ax = plt.subplots()
line_1.plot_2d(ax, t_1=-2, t_2=3, c="k")
line_2.plot_2d(ax, t_1=-2, t_2=3, c="k")
intersection_point.plot_2d(ax, c="r", s=100)
grid = ax.grid()
解决方案 9:
已经有一个使用维基百科 公式的答案,但没有任何检查点来检查线段是否真正相交,所以你去看看
def line_intersection(a, b, c, d):
t = ((a[0] - c[0]) * (c[1] - d[1]) - (a[1] - c[1]) * (c[0] - d[0])) / ((a[0] - b[0]) * (c[1] - d[1]) - (a[1] - b[1]) * (c[0] - d[0]))
u = ((a[0] - c[0]) * (a[1] - b[1]) - (a[1] - c[1]) * (a[0] - b[0])) / ((a[0] - b[0]) * (c[1] - d[1]) - (a[1] - b[1]) * (c[0] - d[0]))
# check if line actually intersect
if (0 <= t and t <= 1 and 0 <= u and u <= 1):
return [a[0] + t * (b[0] - a[0]), a[1] + t * (b[1] - a[1])]
else:
return False
#usage
print(line_intersection([0,0], [10, 10], [0, 10], [10,0]))
#result [5.0, 5.0]
解决方案 10:
还应该提到欧几里得图书馆。
请参阅: https: //pypi.org/project/euclid/(2023 年 10 月)
正如其名称所示,Euclid 库提供了用于定义二维和三维中的点、线、线段、圆和球的类,以及一组用于处理它们的基本操作和方法。我发现该包的代码非常易读,这使我能够轻松添加自己的方法。
以下代码查找两条线的交点:
>>> from euclid import Line2, Point2
>>> l1 = Line2(Point2(1.0, 2.0), Point2(3.0, 4.0))
>>> l2 = Line2(Point2(3.0, 4.0), Point2(-5.0, 6.0))
>>> l1.intersect(l2)
Point2(3.00, 4.00)
解决方案 11:
这就是我如何得到两条线的交点……
我们可以使用 y = mx + b
所以我们取两条线 (x1,y1) 作为线 1,取 (x2,y2) 作为线 2
y=m1*(x-x1) + y1
y=m2*(x-x2) + y2
我们将右侧重新排列为左侧
y-y1-m1(x-x1) (第二个方程相同)
通过这个我们可以得到两个方程的差并简化
y-y1-m1(x-x1) - y+y2+m2(x-x2)=0
-y1-m1x+m1x1 + y2+m2x-m2x2=0
重新排列以分离 x
m2x-m1x=y1-m1x1-y2+m2x2
因子
x(m2-m1)=y1-m1x1-y2+m2x2
最后除以得到交点
Intersectx=(y1-m1x1-y2+m2x2)(m2-m1)
Intersecty=m1(Intersectx-x1)+y1
解决方案 12:
img你可以使用这个代码
class Nokta:
def __init__(self,x,y):
self.x=x
self.y=y
class Dogru:
def __init__(self,a,b):
self.a=a
self.b=b
def Kesisim(self,Dogru_b):
x1= self.a.x
x2=self.b.x
x3=Dogru_b.a.x
x4=Dogru_b.b.x
y1= self.a.y
y2=self.b.y
y3=Dogru_b.a.y
y4=Dogru_b.b.y
#Notlardaki denklemleri kullandım
pay1=((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3))
pay2=((x2-x1) * (y1 - y3) - (y2 - y1) * (x1 - x3))
payda=((y4 - y3) *(x2-x1)-(x4 - x3)*(y2 - y1))
if pay1==0 and pay2==0 and payda==0:
print("DOĞRULAR BİRBİRİNE ÇAKIŞIKTIR")
elif payda==0:
print("DOĞRULAR BİRBİRNE PARALELDİR")
else:
ua=pay1/payda if payda else 0
ub=pay2/payda if payda else 0
#x ve y buldum
x=x1+ua*(x2-x1)
y=y1+ua*(y2-y1)
print("DOĞRULAR {},{} NOKTASINDA KESİŞTİ".format(x,y))