Work with @unutbu's answer and the intersection algorithm taken straight from numpy-and-line-intersections . I came up with this. It is slow due to the brute force method of finding intersections and loops inside loops inside loops. There may be a way to make cycles faster, but I'm not sure about the intersection algorithm.
import matplotlib.pyplot as plt import numpy as np def find_intersections(A, B): #this function stolen from /questions/41518/numpy-and-line-intersections # min, max and all for arrays amin = lambda x1, x2: np.where(x1<x2, x1, x2) amax = lambda x1, x2: np.where(x1>x2, x1, x2) aall = lambda abools: np.dstack(abools).all(axis=2) slope = lambda line: (lambda d: d[:,1]/d[:,0])(np.diff(line, axis=0)) x11, x21 = np.meshgrid(A[:-1, 0], B[:-1, 0]) x12, x22 = np.meshgrid(A[1:, 0], B[1:, 0]) y11, y21 = np.meshgrid(A[:-1, 1], B[:-1, 1]) y12, y22 = np.meshgrid(A[1:, 1], B[1:, 1]) m1, m2 = np.meshgrid(slope(A), slope(B)) m1inv, m2inv = 1/m1, 1/m2 yi = (m1*(x21-x11-m2inv*y21) + y11)/(1 - m1*m2inv) xi = (yi - y21)*m2inv + x21 xconds = (amin(x11, x12) < xi, xi <= amax(x11, x12), amin(x21, x22) < xi, xi <= amax(x21, x22) ) yconds = (amin(y11, y12) < yi, yi <= amax(y11, y12), amin(y21, y22) < yi, yi <= amax(y21, y22) ) return xi[aall(xconds)], yi[aall(yconds)] x = np.linspace(-1,1,500) X,Y = np.meshgrid(x,x) Z1 = np.abs(np.sin(2*X**2+Y)) Z2 = np.abs(np.cos(2*Y**2+X**2)) contour1 = plt.contour(Z1,colors='k') contour2 = plt.contour(Z2,colors='r') xi = np.array([]) yi = np.array([]) for linecol in contour1.collections: for path in linecol.get_paths(): for linecol2 in contour2.collections: for path2 in linecol2.get_paths(): xinter, yinter = find_intersections(path.vertices, path2.vertices) xi = np.append(xi, xinter) yi = np.append(yi, yinter) plt.scatter(xi, yi, s=20) plt.show()

Edit: find_intersections above does not handle vertical and horizontal lines or overlapping line segments. Below is the linelineintersect function that handles these cases, but the whole process is still slow. I added an account, so you have an idea of ββhow long it should go. I also changed contour1 = plt.contour(Z1,colors='k') to contour1 = plt.contour(X,Y,Z1,colors='k') , so the axes and your intersections are in the actual X and Y coordinates of your mesh, not counting your mesh points.
I think the problem is that you just have a lot of data. One contour set has 24 lines with a total of 12818 segments, another set of contours has 29 lines with 11411 line segments. That there are many combinations of line segments to check (696 calls on linelineintersect ). You can get the result faster by using a coarser grid to calculate your functions (100 to 100 was much faster than your original 500 to 500). You may be able to execute some kind of linear sweep algorithm, but I donβt know how to implement such things. The line crossing problem has many applications in computer games and is known as collision detection - there must be some kind of graphics library that can quickly identify all the points of intersection.
import numpy as np from numpy.lib.stride_tricks import as_strided import matplotlib.pyplot as plt import itertools def unique(a, atol=1e-08): """Find unique rows in 2d array Parameters ---------- a : 2d ndarray, float array to find unique rows in atol : float, optional tolerance to check uniqueness Returns ------- out : 2d ndarray, float array of unique values Notes ----- Adapted to include tolerance from code at https://stackoverflow.com/questions/8560440/removing-duplicate-columns-and-rows-from-a-numpy-2d-array#answer-8564438 """ if np.issubdtype(a.dtype, float): order = np.lexsort(aT) a = a[order] diff = np.diff(a, axis=0) np.abs(diff,out = diff) ui = np.ones(len(a), 'bool') ui[1:] = (diff > atol).any(axis=1) return a[ui] else: order = np.lexsort(aT) a = a[order] diff = np.diff(a, axis=0) ui = np.ones(len(a), 'bool') ui[1:] = (diff != 0).any(axis=1) return a[ui] def linelineintersect(a, b, atol=1e-08): """Find all intersection points of two lines defined by series of x,y pairs Intersection points are unordered Colinear lines that overlap intersect at any end points that fall within the overlap Parameters ---------- a, b : ndarray 2 column ndarray of x,y values defining a two dimensional line. 1st column is x values, 2nd column is x values. Notes ----- An example of 3 segment line is: a = numpy.array([[0,0],[5.0,3.0],[4.0,1]]) Function faster when there are no overlapping line segments """ def x_y_from_line(line): """1st and 2nd column of array""" return (line[:, 0],line[:, 1]) def meshgrid_as_strided(x, y, mask=None): """numpy.meshgrid without copying data (using as_strided)""" if mask is None: return (as_strided(x, strides=(0, x.strides[0]), shape=(y.size, x.size)), as_strided(y, strides=(y.strides[0],0), shape=(y.size, x.size))) else: return (np.ma.array(as_strided(x, strides=(0, x.strides[0]), shape=(y.size, x.size)), mask=mask), np.ma.array(as_strided(y, strides=(y.strides[0],0), shape=(y.size, x.size)), mask=mask))
This graph is for a 50x50 grid with actual X and Y axes: 