This is a vague description of an approach to make a linear approximation.
- Determine the Voronoi diagram of your points (for every point in the plane, find the nearest
(x_i,y_i)
)
- Take the dual of this to get the Delaunay triangulation: connect
(x_i,y_i)
and (x_j,y_j)
if there is a line segment of points so that (x_i,y_i)
and (x_j,y_j)
are equidistant (and closer than any other pair).
- On each triangle, find the plane through the three vertices. This is the linear interpolation you need.
The following implements the first two steps in Python. The regularity of your
grid may allow you to speed things up (it may also mess up the triangulation).
import itertools
""" Based on http://stackoverflow.com/a/1165943/2336725 """
def is_ccw(tri):
return ( ( tri[1][0]-tri[0][0] )*( tri[1][1]+tri[0][1] )
+ ( tri[2][0]-tri[1][0] )*( tri[2][1]+tri[1][1] )
+ ( tri[0][0]-tri[2][0] )*( tri[0][1]+tri[2][1] ) ) < 0
def circumcircle_contains_point(triangle,point):
import numpy as np
matrix = np.array( [ [p[0],p[1],p[0]**2+p[1]**2,1] for p in triangle+point ] )
return is_ccw(triangle) == ( np.linalg.det(matrix) > 0 )
triangulation = set()
"""
A triangle is in the Delaunay triangulation if and only if its circumscribing
circle contains no other point. This implementation is O(n^4). Faster methods
are at http://en.wikipedia.org/wiki/Delaunay_triangulation
"""
for triangle in itertools.combinations(points,3):
triangle_empty = True
for point in points:
if point in triangle:
next
if circumcircle_contains_point(triangle,point):
triangle_empty = False
break
if triangle_empty:
triangulation.add(triangle)