【问题标题】:How do I compute the intersection point of two lines?如何计算两条线的交点?
【发布时间】:2014-01-07 18:59:22
【问题描述】:

我有两条相交的线。我知道两条线的端点。如何在 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]

【问题讨论】:

  • 这些是线段还是线?
  • 这个问题主要归结为“做数学”。您可以使用代数运算来找到交点坐标的表达式,然后将该表达式插入到您的程序中。不过记得先检查平行线。
  • 提问前先搜索stackoverflow:[答案][1][1]:stackoverflow.com/questions/3252194/…
  • “我知道如何在纸上做到这一点” — 那你的问题到底是什么?这是你需要在这里应用的纯数学。 Python 是你的计算器。你试过什么?

标签: python geometry line intersect


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    img 你可以用这个kode

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

    【讨论】:

      【解决方案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)
      

      【讨论】:

      • 请务必注意,此解决方案仅适用于定义的端点之间的交点,因为 shapely 仅查找线段的交点,而不是对应的无限线的交点。
      【解决方案4】:

      与其他建议不同,这很短,并且不使用像 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)
      

      编辑:最初有一个错字。那是 fixed 2014 年 9 月,感谢 @zidik。

      这只是下面公式的Python音译,其中的行是(a1, a2)和(b1, b2) 和交叉点是 p。 (如果分母为零,则线条没有唯一的交点。)

      【讨论】:

      • 此解决方案产生 (1.0, 2.0) 与 line_intersection(((0.5, 0.5), (1.5, 0.5)), ((1, 0), (1, 2))) 相交,应为 (1, 0.5)。
      • 我必须同意@xtofl - 这不起作用。我得到了误报和否定。
      • Î 也会避免在此处使用异常。一个简单的False 就可以了,而且它不像处理异常那样昂贵。
      • 哈! @Pithikos 正要说......重新发明轮子只对学习/理解有好处,而对实施没有好处
      • @loved.by.Jesus 我同意。只要您有安装、审核、部署和更新库的好方法。
      【解决方案5】:

      如果你的线是多个点,你可以使用this version.

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

      【讨论】:

      • 必须有listnd.array?
      【解决方案6】:

      使用以下公式: 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]
      

      【讨论】:

      • 我使用这段代码取得了巨大的成功。但是,我正在努力构建一种机制来告诉我该点是否实际上与有限线段相交,而不是与想象中的无限线相交。所以我需要找出点x,y是否在(x1,y1,x2,y2)空间内的任何地方。有什么想法吗?
      • @Mars 你能找到机制来判断这个点是否真的相交吗?
      • @OsamaNaeem 对不起,我不知道。这是很久以前的事了。我找到了一个解决方案,但我不记得了。
      【解决方案7】:

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

      您可能记得的一些术语:

      一条线定义为 y = mx + b OR y = slope * x + y-intercept

      坡度 = 上升超过运行 = 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)
      

      【讨论】:

      • 您可能想尝试以下几点:A1 = [1,1] A2 = [1,3] B1 = [1,3] B2 = [3,1]
      • 任何用 y = ax + b 表示线的东西都会用垂直线崩溃
      【解决方案8】:

      不能袖手旁观,

      所以我们有线性系统:

      A1 * x + B1 * y = C1
      A2 * x + B2 * y = C2

      让我们用克莱默规则来做,所以可以在行列式中找到解决方案:

      x = Dx/D
      y = Dy/D

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

      A1 B1
      A2 B2

      DxDy 可以从矩阵中找到:

      C1 B1
      C2 B2

      A1 C1
      A2 C2

      (注意,因为 C 列因此替换了 xy 的 coef. 列)

      所以现在python,为了我们清楚起见,不要把事情搞砸,让我们在数学和python之间做映射。我们将使用数组L 来存储线方程的系数ABC,而不是漂亮的x、@ 987654323@ 我们会有[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"
      

      【讨论】:

      • 这个解决方案报告了线可能相交的交叉点,因为它们有永恒的长度。
      • @firelynx 我认为您将术语 lineline segment 混淆了。 OP 要求一个线交叉点(故意或由于不理解差异)。当检查线的交点时,必须考虑到线是无限的,即从其中点(由定义它的两个点的给定坐标定义)在两个方向上开始的光线。在线段相交的情况下,仅检查给定点之间的部分线是否相交,并忽略其无限延续。
      • 顺便说一句,重合线怎么样?使用上面的算法,它为两条重合线返回true,这显然不能返回单个交点(因为从数学上讲,这种情况下有无限数量的交点)。我认为算法需要在单独的情况下处理这个问题,因为简单的相交线和重合线是两种截然不同的情况。
      • 是的@rbaleksandar,使用这种方法 - 当Rtrue (D != 0) 我们只能说相交线。 R(当D == 0)的所有其他情况可能意味着除了相交(重合或平行)线之外的任何东西。
      • 抱歉挖掘,但我无法理解 A、B 和 C 的值是如何确定的,因为它们在第一种方法中。谁能详细说明?谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多