How to get the coordinates of the intersection of two lines from a ListLinePlot?

Suppose I have two curves intersect at some point, how can I read the coordinates from the graph, not read by eye, but find it with more precision by computer.

For example, here are two lists created by simple functions just for illustration. However, the true list is not created by simple functions. So, using FindRoot is not welcomed. Also, do not assume the points is very dense, so that you can just find the coordinates from the two list with the shortest length. For the sparse points, the coordinates got in that way will have a large error.

For your convenience, you can start with the following code:

lst1 = Table[{x, x^2}, {x, 0, 5, 0.5}];
lst2 = Table[{x, x + 3}, {x, 0, 5, 0.5}];
GraphicsRow[{ListLinePlot[{lst1, lst2}], ListPlot[{lst1, lst2}]}]


• ...actually, you can still use FindRoot[]. Build the piecewise linear interpolating function for both sets (use Interpolation[]), eyeball the possible intersection point, and use FindRoot[] to find the intersection of the two InterpolatingFunction[]s generated, using your eyeballed value as the seed. – J. M. will be back soon Oct 31 '15 at 15:21
• @J.M. Thanks for your comment, I answered it myself. – an offer can't refuse Oct 31 '15 at 15:28
• Related question on Stack Overflow: (7779387) – Mr.Wizard Jul 22 '16 at 16:04

3 Answers

The internal function GraphicsMeshFindIntersections has limitations that are not well understood, but it can be applied directly to plots. For normal plots, it has always worked for me. It will find all the intersections, too, if there are more than one.

lst1 = Table[{x, x^2}, {x, 0, 5, 0.5}];
lst2 = Table[{x, x + 3}, {x, 0, 5, 0.5}];
plot = ListLinePlot[{lst1, lst2}]

GraphicsMeshFindIntersections@plot
(*  {{2.28571, 5.28571}}  *)


To compare with the OP's answer using Interpolation, this method is equivalent to using InterpolationOrder -> 1.

f = Interpolation[lst1, InterpolationOrder -> 1];
g = Interpolation[lst2, InterpolationOrder -> 1];
{x, f[x]} /. FindRoot[f[x] == g[x], {x, 2.1}]
(*  {2.28571, 5.28571}  *)


The default interpolation order, which is cubic, gives a slightly different answer:

f = Interpolation[lst1];
g = Interpolation[lst2];
{x, f[x]} /. FindRoot[f[x] == g[x], {x, 2.1}]
(*  {2.30278, 5.30278}  *)


This agrees exactly with the roots of the functions used to construct the lists because those functions, x^2 and x + 3, have degrees that do not exceed the interpolation order (and there are a sufficient number of data points).

• Note that whether the apparent improvement in accuracy from using the higher interpolation order is significant in a given problem should probably be considered in conjunction with the data, its source, and the model underlying the problem. – Michael E2 Oct 31 '15 at 16:23

Yet another way is to use the interpolation of one set of points as an appropriate mesh function in the plot of the other.

Here

mf = Interpolation[lst2];


and

plt = ListLinePlot[lst1, MeshFunctions -> (#2 - mf[#1] &), Mesh -> {{0}}, MeshStyle -> Red]


You can then extract the point with

plt// Cases[Normal@#, Point[a_] :> a, Infinity] &
(*{{2.28571, 5.28571}}*)

• +1. Funny I just used this (some days ago) in this answer. – Michael E2 Oct 31 '15 at 17:43
• @MichaelE2 I just +1'ed yours there, it's indeed the same idea! Silvia's answer on that question has got me thinking of mesh functions as useful things. – gpap Oct 31 '15 at 18:08

Following the comment by @J.M., here is a solution:

lst1 = Table[{x, x^2}, {x, 0, 5, 0.5}];
lst2 = Table[{x, x + 3}, {x, 0, 5, 0.5}];
GraphicsRow[{ListLinePlot[{lst1, lst2}], ListPlot[{lst1, lst2}]}]
f = Interpolation[lst1];
g = Interpolation[lst2];
cords = {x = x /. FindRoot[f[x] == g[x], {x, 2.1}], f[x]}
cordsExact = {x /. FindRoot[x^2 == x + 3, {x, 2.1}], x^2}


cheers!