如何计算两条线的交点?

问题描述 投票:0回答:11

我有两条线相交于一点。我知道两条线的端点。如何在 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]
python geometry line intersect
11个回答
105
投票

与其他建议不同,这个建议很短,并且不使用像

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。 (如果分母为零,则直线没有唯一的交点。)


89
投票
无法袖手旁观,

所以我们有线性系统:

A

1 * x + B1 * y = C1 A
2 * x + B2 * y = C2

我们用克莱默法则来做,这样就可以在行列式中找到解:

x = D

x/D y = D
y/D

其中

D 是系统的主要决定因素:

A

1 B1 A
2 B2

DxDy可以从矩阵中找到:

C

1 B1 C
2 B2

A

1C1 A
2 C2

(注意,

C列因此取代了xy的系数列)

现在使用 Python,为了让我们清楚起见,为了不把事情搞砸,让我们在数学和 Python 之间进行映射。我们将使用数组

L

来存储线方程的系数
ABC,而不是漂亮的x
y
,我们将拥有
[0]
[1]
,但是反正。因此,我上面写的内容在代码中将具有以下形式:

对于

D

L1[0] L1[1]

L2[0] L2[1]

对于

Dx

L1[2] L1[1]

L2[2] L2[1]

对于

Dy

L1[0] L1[2]

L2[0] L2[2]

现在开始编码:

line

 - 通过提供的两个点生成线方程的系数 
ABC
intersection
 - 查找 coefs 提供的两条线的交点(如果有)。

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"
    

28
投票
这是使用

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)
    

23
投票
使用以下公式:

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]
    

12
投票
如果您的线条是多个点,则可以使用

此版本。

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()
    

7
投票
我在网上没有找到直观的解释,所以现在我解决了,这是我的解决方案。这是针对无限线(我需要的),而不是线段。

您可能还记得的一些术语:

直线定义为 y = mx + b OR 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)
    

6
投票
我发现的最简洁的解决方案使用 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)
    

3
投票
使用

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()


2
投票
已经有一个

答案使用来自维基百科的公式,但没有任何检查点来检查线段是否真正相交,所以在这里

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]
    

0
投票

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))
    

0
投票
还应该提及

Euclid 库。

参见:

https://pypi.org/project/euclid/(2023 年 10 月)

Euclid 库,顾名思义,提供了在 2D 和 3D 中定义点、线、线段、圆和球体的类,以及一组使用它们的基本操作和方法。我发现该包的代码非常可读,这使我可以轻松添加自己的方法。

以下代码查找两条线的交点:

>>> 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)
    
© www.soinside.com 2019 - 2024. All rights reserved.