web-dev-qa-db-ja.com

Numpyとラインの交差

Numpyを使用して2つの線分の交差を計算するにはどうすればよいですか?

コードには、segment1 =((x1、y1)、(x2、y2))とsegment2 =((x1、y1)、(x2、y2))があります。セグメント1はセグメント2と等しくないことに注意してください。したがって、私のコードでは勾配とy切片も計算しています。それを回避できればいいのですが、方法がわかりません。

私はPythonで書いた関数でCramerの規則を使用していますが、これを行うより速い方法を見つけたいと思います。

25
Xavier

http://www.cs.mun.ca/~rod/2500/notes/numpy-arrays/numpy-arrays.html から直接盗まれた

#
# line segment intersection using vectors
# see Computer Graphics by F.S. Hill
#
from numpy import *
def perp( a ) :
    b = empty_like(a)
    b[0] = -a[1]
    b[1] = a[0]
    return b

# line segment a given by endpoints a1, a2
# line segment b given by endpoints b1, b2
# return 
def seg_intersect(a1,a2, b1,b2) :
    da = a2-a1
    db = b2-b1
    dp = a1-b1
    dap = perp(da)
    denom = dot( dap, db)
    num = dot( dap, dp )
    return (num / denom.astype(float))*db + b1

p1 = array( [0.0, 0.0] )
p2 = array( [1.0, 0.0] )

p3 = array( [4.0, -5.0] )
p4 = array( [4.0, 2.0] )

print seg_intersect( p1,p2, p3,p4)

p1 = array( [2.0, 2.0] )
p2 = array( [4.0, 3.0] )

p3 = array( [6.0, 0.0] )
p4 = array( [6.0, 3.0] )

print seg_intersect( p1,p2, p3,p4)
35
Hamish Grubijan
_import numpy as np

def get_intersect(a1, a2, b1, b2):
    """ 
    Returns the point of intersection of the lines passing through a2,a1 and b2,b1.
    a1: [x, y] a point on the first line
    a2: [x, y] another point on the first line
    b1: [x, y] a point on the second line
    b2: [x, y] another point on the second line
    """
    s = np.vstack([a1,a2,b1,b2])        # s for stacked
    h = np.hstack((s, np.ones((4, 1)))) # h for homogeneous
    l1 = np.cross(h[0], h[1])           # get first line
    l2 = np.cross(h[2], h[3])           # get second line
    x, y, z = np.cross(l1, l2)          # point of intersection
    if z == 0:                          # lines are parallel
        return (float('inf'), float('inf'))
    return (x/z, y/z)

if __name__ == "__main__":
    print get_intersect((0, 1), (0, 2), (1, 10), (1, 9))  # parallel  lines
    print get_intersect((0, 1), (0, 2), (1, 10), (2, 10)) # vertical and horizontal lines
    print get_intersect((0, 1), (1, 2), (0, 10), (1, 9))  # another line for fun
_

説明

線の方程式は_ax+by+c=0_であることに注意してください。したがって、点がこの線上にある場合、それは_(a,b,c).(x,y,1)=0_の解決策です(_._はドット積です)

l1=(a1,b1,c1)l2=(a2,b2,c2)を2行とし、p1=(x1,y1,1)p2=(x2,y2,1)を2点とします。


2点を通る線を見つける:

_t=p1xp2_(2点の外積)を線を表すベクトルとします。

_p1_がtであるため、t.p1 = (p1xp2).p1=0であるため、また、t.p2 = (p1xp2).p2=0により、_p2_がtにあることもわかります。したがって、tは_p1_および_p2_を通過する行でなければなりません。

つまり、ライン上の2点の外積を取ることでラインのベクトル表現を取得できますです。


交点を見つける:

ここで_r=l1xl2_(2本の線の外積)を点を表すベクトルとする

rは_l1_に依存していることがわかっています。なぜなら、r.l1=(l1xl2).l1=0だからです。 r.l2=(l1xl2).l2=0であるため、rが_l2_にあることもわかっています。したがって、rは、線_l1_と_l2_の交点でなければなりません。

興味深いことに、2本の線の外積をとることで交点を見つけることができます

20
Norbu Tsering

これはおそらく遅い応答ですが、私が「乱暴な線の交差」をグーグル化したときの最初のヒットでした。私の場合、私は平面に2本の線があり、それらの間の交点をすばやく取得したかったので、ハミッシュのソリューションは遅くなります-すべての線分セグメントにネストされたforループが必要です。

Forループなしで実行する方法は次のとおりです(非常に高速です)。

from numpy import where, dstack, diff, meshgrid

def find_intersections(A, B):

    # min, max and all for arrays
    amin = lambda x1, x2: where(x1<x2, x1, x2)
    amax = lambda x1, x2: where(x1>x2, x1, x2)
    aall = lambda abools: dstack(abools).all(axis=2)
    slope = lambda line: (lambda d: d[:,1]/d[:,0])(diff(line, axis=0))

    x11, x21 = meshgrid(A[:-1, 0], B[:-1, 0])
    x12, x22 = meshgrid(A[1:, 0], B[1:, 0])
    y11, y21 = meshgrid(A[:-1, 1], B[:-1, 1])
    y12, y22 = meshgrid(A[1:, 1], B[1:, 1])

    m1, m2 = meshgrid(slope(A), slope(B))
    m1inv, m2inv = 1/m1, 1/m2

    yi = (m1*(x21-x11-m2inv*y21) + y11)/(1 - m1*m2inv)
    xi = (yi - y21)*m2inv + x21

    xconds = (amin(x11, x12) < xi, xi <= amax(x11, x12), 
              amin(x21, x22) < xi, xi <= amax(x21, x22) )
    yconds = (amin(y11, y12) < yi, yi <= amax(y11, y12),
              amin(y21, y22) < yi, yi <= amax(y21, y22) )

    return xi[aall(xconds)], yi[aall(yconds)]

次に、それを使用するには、引数として2行を指定します。ここで、argは2列の行列で、各行は(x、y)ポイントに対応します。

# example from matplotlib contour plots
Acs = contour(...)
Bsc = contour(...)

# A and B are the two lines, each is a 
# two column matrix
A = Acs.collections[0].get_paths()[0].vertices
B = Bcs.collections[0].get_paths()[0].vertices

# do it
x, y = find_intersections(A, B)

楽しんで

9
marmaduke

これは@Hamish Grubijanの回答のバージョンであり、各入力引数の複数のポイントに対しても機能します。つまり、a1a2b1b2は、2DポイントのNx2行配列にすることができます。 perp関数は、内積で置き換えられます。

T = np.array([[0, -1], [1, 0]])
def line_intersect(a1, a2, b1, b2):
    da = np.atleast_2d(a2 - a1)
    db = np.atleast_2d(b2 - b1)
    dp = np.atleast_2d(a1 - b1)
    dap = np.dot(da, T)
    denom = np.sum(dap * db, axis=1)
    num = np.sum(dap * dp, axis=1)
    return np.atleast_2d(num / denom).T * db + b1
4
user1248490

(ビット強制)ワンライナーは次のとおりです。

import numpy as np
from scipy.interpolate import interp1d

interp1d(segment1-segment2,np.arange(segment1.shape[0]))(0)

差を補間し(デフォルトは線形)、逆数の0を見つけます。

乾杯!

1
Andy Reagan
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y


'''
finding intersect point of line AB and CD 
where A is the first point of line AB
and B is the second point of line AB
and C is the first point of line CD
and D is the second point of line CD
'''



def get_intersect(A, B, C, D):
    # a1x + b1y = c1
    a1 = B.y - A.y
    b1 = A.x - B.x
    c1 = a1 * (A.x) + b1 * (A.y)

    # a2x + b2y = c2
    a2 = D.y - C.y
    b2 = C.x - D.x
    c2 = a2 * (C.x) + b2 * (C.y)

    # determinant
    det = a1 * b2 - a2 * b1

    # parallel line
    if det == 0:
        return (float('inf'), float('inf'))

    # intersect point(x,y)
    x = ((b2 * c1) - (b1 * c2)) / det
    y = ((a1 * c2) - (a2 * c1)) / det
    return (x, y)
0
Sadekujjaman

これは私が線の交点を見つけるために使用するもので、各線の2点、または点とその勾配のいずれかで機能します。私は基本的に線形方程式を解きます。

def line_intersect(p0, p1, m0=None, m1=None, q0=None, q1=None):
    ''' intersect 2 lines given 2 points and (either associated slopes or one extra point)
    Inputs:
        p0 - first point of first line [x,y]
        p1 - fist point of second line [x,y]
        m0 - slope of first line
        m1 - slope of second line
        q0 - second point of first line [x,y]
        q1 - second point of second line [x,y]
    '''
    if m0 is  None:
        if q0 is None:
            raise ValueError('either m0 or q0 is needed')
        dy = q0[1] - p0[1]
        dx = q0[0] - p0[0]
        lhs0 = [-dy, dx]
        rhs0 = p0[1] * dx - dy * p0[0]
    else:
        lhs0 = [-m0, 1]
        rhs0 = p0[1] - m0 * p0[0]

    if m1 is  None:
        if q1 is None:
            raise ValueError('either m1 or q1 is needed')
        dy = q1[1] - p1[1]
        dx = q1[0] - p1[0]
        lhs1 = [-dy, dx]
        rhs1 = p1[1] * dx - dy * p1[0]
    else:
        lhs1 = [-m1, 1]
        rhs1 = p1[1] - m1 * p1[0]

    a = np.array([lhs0, 
                  lhs1])

    b = np.array([rhs0, 
                  rhs1])
    try:
        px = np.linalg.solve(a, b)
    except:
        px = np.array([np.nan, np.nan])

    return px
0
dashesy