Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find the points of intersection of a line and multiple curves in Python?

I have data represented in the figure.

enter image description here

The curves were extrapolated and I have a line whose equation is known. The equation of curves are unknown. Now, how do I find the points of intersection of this line with each of the curves?

The reproducible code:

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


x = np.array([[0.12, 0.11, 0.1, 0.09, 0.08],
              [0.13, 0.12, 0.11, 0.1, 0.09],
              [0.15, 0.14, 0.12, 0.11, 0.1],
              [0.17, 0.15, 0.14, 0.12, 0.11],
              [0.19, 0.17, 0.16, 0.14, 0.12],
              [0.22, 0.19, 0.17, 0.15, 0.13],
              [0.24, 0.22, 0.19, 0.16, 0.14],
              [0.27, 0.24, 0.21, 0.18, 0.15],
              [0.29, 0.26, 0.22, 0.19, 0.16]])

y = np.array([[71.64, 78.52, 84.91, 89.35, 97.58],
              [66.28, 73.67, 79.87, 85.36, 93.24],
              [61.48, 69.31, 75.36, 81.87, 89.35],
              [57.61, 65.75, 71.7, 79.1, 86.13],
              [55.12, 63.34, 69.32, 77.29, 83.88],
              [54.58, 62.54, 68.7, 76.72, 82.92],
              [56.58, 63.87, 70.3, 77.69, 83.53],
              [61.67, 67.79, 74.41, 80.43, 85.86],
              [70.08, 74.62, 80.93, 85.06, 89.84]])


x1 = np.linspace(0, 0.4, 100)
y1 = -100 * x1 + 100
plt.figure(figsize = (5.15,5.15))
plt.subplot(111)
for i in range(5):
    x_val = np.linspace(x[0, i] - 0.05, x[-1, i] + 0.05, 100)
    x_int = np.interp(x_val, x[:, i], y[:, i])
    poly = np.polyfit(x[:, i], y[:, i], deg=2)
    y_int  = np.polyval(poly, x_val)
    plt.plot(x[:, i], y[:, i], linestyle = '', marker = 'o')
    plt.plot(x_val, y_int, linestyle = ':', linewidth = 0.25, color =  'black')
plt.plot(x1, y1, linestyle = '-.', linewidth = 0.5, color =  'black')


plt.xlabel('X')
plt.ylabel('Y')
plt.show()
like image 539
Tom Kurushingal Avatar asked Apr 27 '15 19:04

Tom Kurushingal


People also ask

How do you find the point of intersection between a line and a curve?

To find these points you simply have to equate the equations of the two lines, where they equal eachother must be the points of intersection. And from then this is a simple case of solving the quadratic. This expression factorises to (x+2)(x+3)=0 which implies either x=-2 or x=-3.

How do you know how many points of intersection?

We calculate it by solving the equation f(x) = 0 . When the graphs of y = f(x) and y = g(x) intersect , both graphs have exactly the same x and y values. So we can find the point or points of intersection by solving the equation f(x) = g(x).


Video Answer


1 Answers

We do know the equations of the curves. They are of the form a*x**2 + b*x + c, where a,b, and c are the elements of the vector returned by np.polyfit. Then we just need to find the roots of a quadratic equation in order to find the intersections:

def quadratic_intersections(p, q):
    """Given two quadratics p and q, determines the points of intersection"""
    x = np.roots(np.asarray(p) - np.asarray(q))
    y = np.polyval(p, x)
    return x, y

The above function isn't super robust: there doesn't need to be a real root, and it doesn't really check for that. You're free to make it better.

Anyways, we give quadratic_intersections two quadratics, and it returns the two points of intersection. Putting it into your code, we have:

x1 = np.linspace(0, 0.4, 100)
y1 = -100 * x1 + 100
plt.figure(figsize = (7,7))
plt.subplot(111)

plt.plot(x1, y1, linestyle = '-.', linewidth = 0.5, color =  'black')
for i in range(5):
    x_val = np.linspace(x[0, i] - 0.05, x[-1, i] + 0.05, 100)
    poly = np.polyfit(x[:, i], y[:, i], deg=2)
    y_int  = np.polyval(poly, x_val)
    plt.plot(x[:, i], y[:, i], linestyle = '', marker = 'o')
    plt.plot(x_val, y_int, linestyle = ':', linewidth = 0.25, color =  'black')
    ix = quadratic_intersections(poly, [0, -100, 100])
    plt.scatter(*ix, marker='x', color='black', s=40, linewidth=2)

plt.xlabel('X')
plt.ylabel('Y')
plt.xlim([0,.35])
plt.ylim([40,110])
plt.show()

This makes the following figure:

enter image description here

Now, if you don't know that the functions you are dealing with are polynomials, you can use the optimization tools in scipy.optimize to find the root. For example:

import scipy.optimize
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.style

matplotlib.style.use('fivethirtyeight')
%matplotlib inline

f = lambda x: np.cos(x) - x
g = np.sin

h = lambda x: f(x) - g(x)

x = np.linspace(0,3,100)
plt.plot(x, f(x), zorder=1)
plt.plot(x, g(x), zorder=1)

x_int = scipy.optimize.fsolve(h, 1.0)
y_int = f(x_int)

plt.scatter(x_int, y_int, marker='x', s=150, zorder=2, 
            linewidth=2, color='black')

plt.xlim([0,3])
plt.ylim([-4,2])

Which plots:

enter image description here

like image 107
jme Avatar answered Oct 17 '22 10:10

jme