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:
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.