问题
Suppose we have:
- A curve described by a two-dimensional dataset that describes approximately a high order polynomial curve.
- A line defined by two points.
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?
回答1:
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)
回答2:
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 thex
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). Tryy < 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
- For each range, take the average value
x_mean
of the x-coordinates. The inverse coordinate transformationA_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
.- Map the indices of the the range into the unit interval, such that e.g.
[103, 104, 105, 106, 107]
becomes[0.0, 0.25, 0.5, 0.75, 1.0]
- Split the range data into a range of
x
andy
coordinates. - Approximate the
x
andy
data separately as 1D-function to express the curve data as a parametric function(x(t), y(t))
witht
from[0, 1]
(using the mapped indices from above as interpolation knots). - Use a polynomial solver to solve
y(t) == 0
. - For each zero
t_zero
inside[0, 1]
, evaluate the approximation funtcionx(t)
att_zero
. The inverse coordinate transformationA_inv(x(t_zero), 0)
gives you an approximation of the intersection point att_zero
in your original coordinates.
- Map the indices of the the range into the unit interval, such that e.g.
If you can confirm, that this solution may suit your problem, I may provide an according numpy
example.
来源:https://stackoverflow.com/questions/37951631/how-to-find-the-intersection-points-of-a-straight-line-and-a-curve-like-set-of-t