简体   繁体   中英

How to find the intersection points of a straight line and a curve-like set of two dimensional points?

Suppose we have:

  1. A curve described by a two-dimensional dataset that describes approximately a high order polynomial curve.
  2. 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?

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

  1. First, do a coordiante transformation A(x,y) with a translation an a rotation such that the red line matches the x axis.

  2. Intersect the transformed curve with the x axis, ie 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.

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

  1. For each range, take the average value 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

  1. 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 eg [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 and y coordinates.
    • Approximate the 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).
    • Use a polynomial solver to solve y(t) == 0 .
    • For each zero 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.

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)

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