简体   繁体   中英

Python - Find intersection between lines spanned by several points

I have what I believe is a rather basic issue, to which I cannot find an elegant solution. Imagine I have two rather complex lines (eg B-splines) in 2-D space spanned up by two matrices of dimensions (n,2), where n (the rows) are the number of points along the lines, and the two columns correspond to x and y coordinate respectively. Further information:

  • The distance between two sequential points is similar, but not constant.
  • The point of intersection may not necessarily be a point that spans up the lines.
  • there may be (theoretically) any number of intersections

I want to find the point(s) at which these lines intersect. For my purposes it is sufficient to take the lines as linear between each two sequential points.

Unfortunately, every solution I can come up with so far is incredibly inefficient (eg using two nested for-loops and checking each segment of two points on one line vs each segment on the other line). There has to be a more elegant way of doing this.

Is there any kind of function that may ease an implementation of such a routine?

PS: Below you can find an illustration of the system I described above.

在此输入图像描述

Thanks everyone for the responses, especially Dschoni for relevant publication references, and Piinthesky for the comment that gave me the idea for the solution:

We join the X coordinates of the two line points into a common vector, then interpolate the Y coordinates for each of the two lines. Because we now have points at the same X positions, we can subtract the Y values from each other. Between points, at which the sign of the difference shifts, the lines intersect. Thanks everybody for the help!

Here's my solution code:

import pickle
import numpy as np
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt

# Load data series
X1 = pickle.load(open("X1.p","rb"))
Y1 = pickle.load(open("Y1.p","rb"))
X2 = pickle.load(open("X2.p","rb"))
Y2 = pickle.load(open("Y2.p","rb"))

# Convert X vectors to lists, and merge them
X1_list = list(X1)
X2_list = list(X2)
in_first = set(X1_list)
in_second = set(X2_list)
in_second_but_not_in_first = in_second - in_first
result = X1_list + list(in_second_but_not_in_first)
X_joint = np.asarray(result) # Revert to array

# Create interpolated functions
line_1 = interp1d(X1, Y1, kind='linear', fill_value='extrapolate')
line_2 = interp1d(X2, Y2, kind='linear', fill_value='extrapolate')

# Create joint Ys
Y1_joint = line_1(X_joint)
Y2_joint = line_2(X_joint)

# Calculate difference in Y
difference = Y1_joint-Y2_joint

# Plot the original data series
f, axarr = plt.subplots(2)
axarr[0].plot(X1, Y1,'b')
axarr[0].plot(X2, Y2,'r')

# Plot the difference values
axarr[1].plot(X_joint,difference)
axarr[1].plot([min(X_joint),max(X_joint)],[0,0],'k')

# The intersections are where the difference graph dips below or rises above zero

Interpolate each function f1, f2 linearly between two given data points. Minimize the function f = abs(f1 - f2) using a method that does not require derivatives, but keeps function evaluations low, eg, Brent's method . The location of that minimum is your approximate intersection point. If you don't want to implement the algorithm yourself, use scipy.optimize.minimize_scalar ( docs ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM