3

I'm trying to speed up a simple interpolation algorithm. The problem is as follows:

There are 4 three-dimensional points which form a rectangle in XY plane. Their Z components are arbitrary.

Top view

The 4 points form a surface between them and their midpoint, like this:

Midpoint and surface

I need to project a point on that surface by the XY coordinates and getting the Z coordinate on the surface as the result:

Projecting

My solution (slow):

def project_point(p1, p2, p3, test):
    """
    Define a plane by 3 points and project the test point on it
    """
    v1 = p3 - p1
    v2 = p2 - p1

    # The cross product is a vector normal to the plane
    cp = np.cross(v1, v2)
    a, b, c = cp

    # This evaluates a * x3 + b * y3 + c * z3 which equals d
    d = np.dot(cp, p3)

    # Z = (d - a * X - b * Y) / c
    return (d - a * test[0] - b * test[1]) / c

# Determine one of the 4 triangles and project on it

# points is a list of 3d numpy arrays
# xy is a 2d numpy array

p1, p2, p3, p4 = tuple(points) 
mid_point = (p1 + p2 + p3 + p4) * 0.25
tri_index = get_triangle_index(p1, p2, p3, p4, xy) # Returns a triangle index at the coordinates xy

z = 0

if tri_index == 0:
    z = project_point(p1, p3, mid_point, xy)
elif tri_index == 1:
    z = project_point(p3, p4, mid_point, xy)
elif tri_index == 2:
    z = project_point(p4, p2, mid_point, xy)
elif tri_index == 3:
    z = project_point(p1, p2, mid_point, xy)

The provided solution works but it's slow and something tells me this has been solved before more elegantly. Can anyone point me in the right direction?

  • 1
    np.cross and np.dot might be slow for smaller arrays . Try to come up with your own functions instead. – altunyurt Aug 03 '19 at 08:29
  • any reason why you can't use scipy's own interpolation functions? `scipy.interpolate.interp2d` should work fine for this – filippo Aug 03 '19 at 08:32
  • @filippo scipy.interpolate.interp2d gives slightly different result. There's a number of interpolation algorithms and I haven't found one that works exactly as described yet. That's why I asked maybe someone knew how it was called. – Anton Fedoruk Aug 03 '19 at 10:51
  • Have you checked the link? I think it should answer your question. – Georgy Aug 03 '19 at 12:18
  • @AntonFedoruk guess you also already tried LinearNDInterpolator as suggested in the linked question, right? by the way your method looks fine to me, are your planes changing or are you defining your geometry and interpolating later? if so you should define an interpolator function for the piecewise surface once and evaluate that instead of recomputing the plane equation each time. – filippo Aug 03 '19 at 12:19
  • @Georgy LinearNDInterpolator works if I supply the midpoints and it is fast! So it solves the problem partially. By default though LinearNDInterpolator builds a surface differently, without the midpoints (I can show plots/code to illustrate this). Anyway supplying the midpoints can work too or maybe I'll have to alter LinearNDInterpolator to work that way. – Anton Fedoruk Aug 03 '19 at 17:07
  • @filippo I'm defining the geometry and interpolating later. You're right I should define it once and reuse. My biggest concern is that the interpolation methods build the surface differently (without the midpoints). They either make a curved surface or connect two of the points of the quad (without calculating the midpoint) which produces poorer output. – Anton Fedoruk Aug 03 '19 at 17:13
  • @AntonFedoruk with LinearNDInterpolator you can define as many fixed points as you want, and it will build a piecewise linear function to interpolate between them. Your mid point is just another fixed point in the geometry. With interp2d you can also have curved surfaces but the default is still linear/planar. – filippo Aug 03 '19 at 17:30

0 Answers0