Reputation: 696
Suppose we have:
This is a sample image:
Supposing the line and the curve intercept each other, how could I find the intersection point between the line and the dataset?
Upvotes: 1
Views: 2498
Reputation: 2233
As per my comment above
import numpy as np
A = np.random.random((20, 2))
A[:,0] = np.arange(20)
A[:,1] = A[:,1] * (7.5 + A[:,0]) # some kind of wiggly line
p0 = [-1.0,-6.5] # point 0
p1 = [22.0, 20.0] # point 1
b = (p1[1] - p0[1]) / (p1[0] - p0[0]) # gradient
a = p0[1] - b * p0[0] # intercept
B = (a + A[:,0] * b) - A[:,1] # distance of y value from line
ix = np.where(B[1:] * B[:-1] < 0)[0] # index of points where the next point is on the other side of the line
d_ratio = B[ix] / (B[ix] - B[ix + 1]) # similar triangles work out crossing points
cross_points = np.zeros((len(ix), 2)) # empty array for crossing points
cross_points[:,0] = A[ix,0] + d_ratio * (A[ix+1,0] - A[ix,0]) # x crossings
cross_points[:,1] = A[ix,1] + d_ratio * (A[ix+1,1] - A[ix,1]) # y crossings
print(ix, B, A, cross_points)
Upvotes: 2
Reputation: 2947
Since the curve data appears to be dense and not scattered (as for example the result of a numerically solved differential equation), interpolating or approximating the whole curve dataset is overkill. In the following, I assume that the points of the dataset are ordered along the curve (as if they were the result of sampling a parametric curve).
First, do a coordiante transformation A(x,y)
with a translation an a rotation such that the red line matches the x
axis.
Intersect the transformed curve with the x
axis, i.e. take all points from the curve dataset with a small absolute value of the y-coordinate (and remember their indices in the dataset). Try y < 0.05
for the depicted curve.
Use the indices from the points selected in 2. to detect ranges of adjacent curve points, each range resembling a small bit of the curve.
Sloppy version
x_mean
of the x-coordinates. The inverse coordinate transformation A_inv(x_mean, 0)
will give you an approximation of the intersection point of that range. Depending on your use case and the complexity of potential curves, the approximation may already be good enough.Sophisticated version
Approximate each range with a line or a polynomial curve of low degree <= 4
.
[103, 104, 105, 106, 107]
becomes [0.0, 0.25, 0.5, 0.75, 1.0]
x
and y
coordinates.x
and y
data separately as 1D-function to express the curve data as a parametric function (x(t), y(t))
with t
from [0, 1]
(using the mapped indices from above as interpolation knots).y(t) == 0
.t_zero
inside [0, 1]
, evaluate the approximation funtcion x(t)
at t_zero
. The inverse coordinate transformation A_inv(x(t_zero), 0)
gives you an approximation of the intersection point at t_zero
in your original coordinates.If you can confirm, that this solution may suit your problem, I may provide an according numpy
example.
Upvotes: 0