Как найти пересечение двух прямых python

If your lines are multiple points instead, you can use this version.

enter image description here

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

Stolen directly from https://web.archive.org/web/20111108065352/https://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)

Trenton McKinney's user avatar

answered Jul 15, 2010 at 3:13

Hamish Grubijan's user avatar

Hamish GrubijanHamish Grubijan

10.5k23 gold badges97 silver badges147 bronze badges

6

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

Explanation

Note that the equation of a line is ax+by+c=0. So if a point is on this line, then it is a solution to (a,b,c).(x,y,1)=0 (. is the dot product)

let l1=(a1,b1,c1), l2=(a2,b2,c2) be two lines and p1=(x1,y1,1), p2=(x2,y2,1) be two points.

Finding the line passing through two points:

let t=p1xp2 (the cross product of two points) be a vector representing a line.

We know that p1 is on the line t because t.p1 = (p1xp2).p1=0.
We also know that p2 is on t because t.p2 = (p1xp2).p2=0. So t must be the line passing through p1 and p2.

This means that we can get the vector representation of a line by taking the cross product of two points on that line.

Finding the point of intersection:

Now let r=l1xl2 (the cross product of two lines) be a vector representing a point

We know r lies on l1 because r.l1=(l1xl2).l1=0. We also know r lies on l2 because r.l2=(l1xl2).l2=0. So r must be the point of intersection of the lines l1 and l2.

Interestingly, we can find the point of intersection by taking the cross product of two lines.

answered Mar 10, 2017 at 20:56

Norbu Tsering's user avatar

10

This is is a late response, perhaps, but it was the first hit when I Googled ‘numpy line intersections’. In my case, I have two lines in a plane, and I wanted to quickly get any intersections between them, and Hamish’s solution would be slow — requiring a nested for loop over all line segments.

Here’s how to do it without a for loop (it’s quite fast):

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

Then to use it, provide two lines as arguments, where is arg is a 2 column matrix, each row corresponding to an (x, y) point:

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

have fun

Eric's user avatar

Eric

94.7k52 gold badges239 silver badges370 bronze badges

answered Feb 2, 2012 at 10:44

marmaduke's user avatar

marmadukemarmaduke

1011 silver badge2 bronze badges

2

This is a version of @Hamish Grubijan’s answer that also works for multiple points in each of the input arguments, i.e., a1, a2, b1, b2 can be Nx2 row arrays of 2D points. The perp function is replaced by a dot product.

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

answered Nov 16, 2016 at 16:55

user1248490's user avatar

user1248490user1248490

9539 silver badges16 bronze badges

I would like to add something small here. The original question is about line segments. I arrived here, because I was looking for line segment intersection, which in my case meant that I need to filter those cases, where no intersection of the line segments exists. Here is some code which does that:

def line_intersection(x1, y1, x2, y2, x3, y3, x4, y4):
    """find the intersection of line segments A=(x1,y1)/(x2,y2) and
    B=(x3,y3)/(x4,y4). Returns a point or None"""
    denom = ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4))
    if denom==0: return None
    px = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / denom
    py = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / denom
    if (px - x1) * (px - x2) < 0 and (py - y1) * (py - y2) < 0 
      and (px - x3) * (px - x4) < 0 and (py - y3) * (py - y4) < 0:
        return [px, py]
    else:
        return None

answered Aug 25, 2021 at 14:32

user16751456's user avatar

1

In case you are looking for a vectorized version where we can rule out vertical line segments.

def intersect(a):
    # a numpy array with dimension [n, 2, 2, 2]
    # axis 0: line-pair, axis 1: two lines, axis 2: line delimiters axis 3: x and y coords
    # for each of the n line pairs a boolean is returned stating of the two lines intersect
    # Note: the edge case of a vertical line is not handled.
    m = (a[:, :, 1, 1] - a[:, :, 0, 1]) / (a[:, :, 1, 0] - a[:, :, 0, 0])
    t = a[:, :, 0, 1] - m[:, :] * a[:, :, 0, 0]
    x = (t[:, 0] - t[:, 1]) / (m[:, 1] - m[:, 0])
    y = m[:, 0] * x + t[:, 0]
    r = a.min(axis=2).max(axis=1), a.max(axis=2).min(axis=1)
    return (x >= r[0][:, 0]) & (x <= r[1][:, 0]) & (y >= r[0][:, 1]) & (y <= r[1][:, 1])

A sample invocation would be:

intersect(np.array([
    [[[1, 2], [2, 2]],
     [[1, 2], [1, 1]]], # I
    [[[3, 4], [4, 4]],
     [[4, 4], [5, 6]]], # II
    [[[2, 0], [3, 1]],
     [[3, 0], [4, 1]]], # III
    [[[0, 5], [2, 5]],
     [[2, 4], [1, 3]]], # IV
]))
# returns [False, True, False, False]

Visualization (I need more reputation to post images here).

answered Jan 9, 2022 at 16:30

Florian Leicher's user avatar

Here’s a (bit forced) one-liner:

import numpy as np
from scipy.interpolate import interp1d

x = np.array([0, 1])
segment1 = np.array([0, 1])
segment2 = np.array([-1, 2])

x_intersection = interp1d(segment1 - segment2, x)(0)
# if you need it:
y_intersection = interp1d(x, segment1)(x_intersection)

Interpolate the difference (default is linear), and find a 0 of the inverse.

Cheers!

answered Mar 31, 2017 at 17:36

Andy Reagan's user avatar

Andy ReaganAndy Reagan

5797 silver badges16 bronze badges

3

This is what I use to find line intersection, it works having either 2 points of each line, or just a point and its slope. I basically solve the system of linear equations.

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

answered Oct 17, 2014 at 1:01

dashesy's user avatar

dashesydashesy

2,5593 gold badges44 silver badges61 bronze badges

We can solve this 2D line intersection problem using determinant.

To solve this, we have to convert our lines to the following form: ax+by=c. where

 a = y1 - y2
 b = x1 - x2
 c = ax1 + by1 

If we apply this equation for each line, we will got two line equation. a1x+b1y=c1 and a2x+b2y=c2.

Now when we got the expression for both lines.
First of all we have to check if the lines are parallel or not. To examine this we want to find the determinant. The lines are parallel if the determinant is equal to zero.
We find the determinant by solving the following expression:

det = a1 * b2 - a2 * b1

If the determinant is equal to zero, then the lines are parallel and will never intersect. If the lines are not parallel, they must intersect at some point.
The point of the lines intersects are found using the following formula:

equation for finding line intersection using determinant

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)

answered Sep 6, 2019 at 11:32

Sadekujjaman's user avatar

2

I wrote a module for line to compute this and some other simple line operations. It is implemented in c++, so it works very fast. You can install FastLine via pip and then use it in this way:

from FastLine import Line
# define a line by two points
l1 = Line(p1=(0,0), p2=(10,10))
# or define a line by slope and intercept
l2 = Line(m=0.5, b=-1)

# compute intersection
p = l1.intersection(l2)
# returns (-2.0, -2.0)

answered Jan 22, 2022 at 17:13

M.Ali Zarrinzade's user avatar

0

The reason you would want to use numpy code is because it’s faster and it’s only really faster when you can broadcast it. The way you make numpy code fast is by doing everything in a series of of numpy operations without loops. If you’re not going to do this, don’t use numpy.

    def line_intersect(x1, y1, x2, y2, x3, y3, x4, y4):
        denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)
        if denom == 0:
            return None  # Parallel.
        ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom
        ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom
        if 0.0 <= ua <= 1.0 and 0.0 <= ub <= 1.0:
            return (x1 + ua * (x2 - x1)), (y1 + ua * (y2 - y1))
        return None

However, let’s do use numpy:

It’s a bit easier to deal with points as complex numbers (x=real, y=imag). That trick is used elsewhere. And rather than a 2d set of elements we use a numpy 1d complex array for the 2d points.

import numpy as np

def find_intersections(a, b):
    old_np_seterr = np.seterr(divide="ignore", invalid="ignore")
    try:
        ax1, bx1 = np.meshgrid(np.real(a[:-1]), np.real(b[:-1]))
        ax2, bx2 = np.meshgrid(np.real(a[1:]), np.real(b[1:]))
        ay1, by1 = np.meshgrid(np.imag(a[:-1]), np.imag(b[:-1]))
        ay2, by2 = np.meshgrid(np.imag(a[1:]), np.imag(b[1:]))

        # Note if denom is zero these are parallel lines.
        denom = (by2 - by1) * (ax2 - ax1) - (bx2 - bx1) * (ay2 - ay1)

        ua = ((bx2 - bx1) * (ay1 - by1) - (by2 - by1) * (ax1 - bx1)) / denom
        ub = ((ax2 - ax1) * (ay1 - by1) - (ay2 - ay1) * (ax1 - bx1)) / denom
        hit = np.dstack((0.0 <= ua, ua <= 1.0, 0.0 <= ub, ub <= 1.0)).all(axis=2)
        ax1 = ax1[hit]
        ay1 = ay1[hit]
        x_vals = ax1 + ua[hit] * (ax2[hit] - ax1)
        y_vals = ay1 + ua[hit] * (ay2[hit] - ay1)
        return x_vals + y_vals * 1j
    finally:
        np.seterr(**old_np_seterr)

Invoking code:

import svgelements as svge
from random import random
import numpy as np

j = svge.Path(svge.Circle(cx=random() * 5, cy=random() * 5, r=random() * 5)).npoint(
    np.arange(0, 1, 0.001)
)
k = svge.Path(svge.Circle(cx=random() * 5, cy=random() * 5, r=random() * 5)).npoint(
    np.arange(0, 1, 0.001)
)
j = j[:, 0] + j[:, 1] * 1j
k = k[:, 0] + k[:, 1] * 1j

intersects = find_intersections(j, k)
print(intersects)
# Random circles will intersect in 0 or 2 points.

In our code, a and b are segment lists. These expect to be a series of connected points and we mesh them to find any segment n -> n+1 segment that intersects with any or all the other segments.

We return all intersections between the polyline a and the polyline b.

Two tricks (for adaptations):

  1. We mesh all the segments. We check every segment in the polyline a list and every segment in the polyline b list. It’s pretty easy to see how you’d arrange this if you wanted other inputs.

  2. Many code examples will check if denom is zero but that’s not allowed in pure array code since there’s a mesh of different points to check, so conditionals need to be in-lined. We turn off the seterr for dividing by 0 and infinity because we expect to do that if we have parallel lines. Which gets rid of the check for denom being zero. If denom is zero then the lines are parallel which means they either meet at 0 points or infinite many points. The typical conditional checking for the values of ua and ub is done in an array stack of each of the checks which then sees if all of these are true for any elements, and then just returns true for those elements.


If you need the value t or the segments within the lists that intersected this should be readily determined from the ua ub and hit.

answered Dec 6, 2022 at 5:33

Tatarize's user avatar

TatarizeTatarize

10.1k4 gold badges57 silver badges64 bronze badges

import numpy as np

data = np.array([
    #  segment1               segment2
    # [[x1, y1], [x2, y2]],  [[x1, y1], [x2, y2]]
    [[0, 0], [1, 1], [0, 1], [1, 0]],
    [[0, 0], [1, 1], [1, 0], [1, 1]],
    [(0, 1), (0, 2), (1, 10), (2, 10)],
    [(0, 1), (1, 2), (0, 10), (1, 9)],
    [[0, 0], [0, 1], [0, 2], [1, 3]],
    [[0, 1], [2, 3], [4, 5], [6, 7]],  
    [[1, 2], [3, 4], [5, 6], [7, 8]]
])

def intersect(data):
    L = len(data)
    x1, y1, x2, y2 = data.reshape(L * 2, -1).T
    R = np.full([L, 2], np.nan)
    X = np.concatenate([
        (y2 - y1).reshape(L * 2, -1), 
        (x1 - x2).reshape(L * 2, -1)], 
        axis=1
    ).reshape(L, 2, 2)
    B = (x1 * y2 - x2 * y1).reshape(L, 2)
    I = np.isfinite(np.linalg.cond(X))
    R[I] = np.matmul(np.linalg.inv(X[I]), B[I][:,:,None]).squeeze(-1)
    return R

intersect(data)

array([[ 0.5,  0.5],
       [ 1. ,  1. ],
       [ 0. , 10. ],
       [ 4.5,  5.5],
       [ 0. ,  2. ],
       [ nan,  nan],
       [ nan,  nan]])

answered Mar 10 at 12:59

xmduhan's user avatar

xmduhanxmduhan

94712 silver badges14 bronze badges

RayProgrammer

Как найти точку пересечения двух координатных прямых?

Есть задача, которую нужно решить на языке программирования Python: Дано две прямые A(x,y,angle) и B(x,y,angle), нужно найти точку пересечения этих прямых.
p.s Облазил все математические сайты, так и не нашёл точного решения на свою задачу.


  • Вопрос задан

    более двух лет назад

  • 624 просмотра

Это же простейшая школьная тригонометрия.
xA + a·sin(angleA) = xB + b·sin(angleB)
yA + a·cos(angleA) = yB + b·cos(angleB)
Решаете систему уравнений, получаете a и b. Подставляете в уравнение прямой, получаете точку пересечения.

www.cleverstudents.ru/line_and_plane/slope_interce…
хорошо вот 2 уравнения прямых A(xa,ya,angle_a) и B(yb,xb,angle_b):

y=ya+(x-xa)*tan(angle_a)
y=yb+(x-xb)*tan(angle_b)

нужно решить их как систему уравнений – выразить x после подстановки y
ya+(x-xa)*tan(angle_a)=yb+(x-xb)*tan(angle_b)
дальше уже лень решать…

не забывайте где в пионе функция тангенса, ну и конверсию из градусов в радианы тоже надеюсь умеете делать
from math import tan
и проверки на вырожденные случаи – когда одинаковые углы или точки лежат на одной прямой

в школе вроде все учатся, только кто-то думает что им это не надо, а потом раз и надо оказывается.

Пригласить эксперта

все я сделала готовую программу это можно сделать вот так https://planet.mblock.cc/project/704229

код открытый смотри
начальные линии ставишь сам можно дописать код от пользователя и тогда оно само будет рисовать

то есть можно спросить где нарисовать линию начальные точки и тогда можно без проблем делать даже голосовой набор и программа сама покажит

я не знаю как это записать математически или выражением, но это очень легко ,как видишь программа работает ,а код можно посмотреть и переписать ,я потратила на это целых 10 минут


  • Показать ещё
    Загружается…

20 мая 2023, в 01:15

100000 руб./за проект

20 мая 2023, в 00:11

10000 руб./за проект

19 мая 2023, в 23:57

40000 руб./за проект

Минуточку внимания



У меня есть две линии, которые пересекаются в одной точке. Я знаю конечные точки этих двух линий. Как вычислить точку пересечения в 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]


4687  


6  

6 ответов:

В отличие от других предложений, он короткий и не использует внешние библиотеки, такие как numpy. (Не то, чтобы использование других библиотек является bad…it приятно не надо, особенно для такой простой задачи.)

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]) #Typo was here

    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)

Не могу стоять в стороне,

Итак, мы имеем линейную систему:

A1 * x + B1 * y = C1
А2 * x + B2 * y = C2

Давайте сделаем это с помощью правила Крамера, чтобы решение можно было найти в детерминантах:

X = D x /D
y = D y/D

Где D – главный детерминант системы:

A1 B1
А2 B2

И D x и D y можно найти из matricies:

C1 B1
С2 B2

И

A1 С1
А2 С2

(обратите внимание, что столбец C соответственно заменяет coef. столбцы x и y )

Итак, теперь python, для ясности для нас, чтобы не испортить вещи, давайте сделаем отображение между math и python. Мы будем использовать массив L для хранения наших coefs A, B, C линейных уравнений и intestead 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 – производит coefs A, B, C линейного уравнения по двум точкам при условии,
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"

Я не нашел интуитивного объяснения в интернете, поэтому теперь, когда я это понял, вот мое решение. Это для бесконечных линий (то, что мне нужно), а не сегментов.

Некоторые термины, которые вы можете запомнить:

Линия определяется как y = mx + b или y = slope * x + y-intercept

Наклон = подъем = ду / ДХ = высота / расстояние

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)

Используя формулу из:
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]

1. Чтобы найти пересечение двух прямых, вы можете использовать одновременные уравнения. Формула выглядит следующим образом:

Вычислите код пересечения двух прямых:

# Рассчитать пересечение двух прямых
#y = a1*x + b1
#y = a2*x + b2
# Если пересечения нет, выбросить исключение и вернуть None
def cal_intersection(a1,b1,a2,b2):
    try:
        x = (b2-b1)/(a1-a2)
        y = a1*(b2-b1)/(a1-a2) + b1
        return (x,y)
    except Exception as e:
        print(str(e))
        return None

2. Найдите крайнюю точку параболы, вычислите значение x, когда производная равна 0, а затем введите формулу, чтобы найти y, формула выглядит следующим образом:

Код для расчета параболических экстремумов:

# Парабола: y = a * x ** 2 + b * x + c 
# Если a равно 0, выбросить исключение и вернуть None
def getExtremePoint(a,b,c):
    try:
        x = -(b/2/a)
        y = (4*a*c - b**2)/4/a
        return (x,y)
    except Exception as e:
        print(str(e))
        return None

Проверить код для поиска пересечения прямых:

import numpy as np  
import matplotlib.pyplot as plt  

a1,b1,a2,b2 = np.random.rand(4)
input_x = np.arange(-5,5,0.1) 

y_predict2 = a1 * input_x + b1
y_predict1 = a2 * input_x + b2

#    
intersection = cal_intersection(a1,b1,a2,b2)

#Рисунок
plt.plot(input_x,y_predict1,color='r',linestyle='-',marker='.',label=u"predict") 
plt.plot(input_x,y_predict2,color='g',linestyle='-',marker='.',label=u"predict") 
plt.scatter(intersection[0],intersection[1],color='b',linestyle='-',marker='.',label=u"intersection",linewidth=11) 
plt.legend(loc='upper left')
plt.show()

Проверить код крайней точки параболы:

import numpy as np  
import matplotlib.pyplot as plt  

a,b,c = (-1) ** np.random.randint(0,2)*np.random.rand(3)
input_x = np.arange(-5,5,0.1) 

y_predict = a * input_x **2 + b * input_x + c

# Найти крайние точки
extreme = getExtremePoint(a,b,c)

#Рисунок
plt.plot(input_x,y_predict,color='r',linestyle='-',marker='.',label=u"predict") 
plt.scatter(extreme[0],extreme[1],color='b',linestyle='-',marker='.',label=u"extreme",linewidth=11) 
plt.legend(loc='upper left')
plt.show()

Добавить комментарий