1

I have a point cloud in 4 dimensions, where each point in the cloud has a location and a value (x,y,z,Value). In addition, I have a 'special' point, S0, within the 3d point cloud; I've used this example to find the closest 10 points in the cloud, relative to S0. Now, I have a numpy array for each of the 10 closest points and their values. How can I interpolate these 10 points, to find the interpolated value at point S0? Example code is shown below:

import numpy as np
import matplotlib.pyplot as plt

numpoints = 20
linexs = 320
lineys = 40
linezs = 60
linexe = 20
lineye = 20
lineze = 0

# Create vectors of points
xpts = np.linspace(linexs, linexe, numpoints)
ypts = np.linspace(lineys, lineye, numpoints)
zpts = np.linspace(linezs, lineze, numpoints)
lin = np.dstack((xpts,ypts,zpts))

# Image line of points
fig = plt.figure()
ax = fig.add_subplot(211, projection='3d')
ax.set_xlim(0,365); ax.set_ylim(-85, 85); ax.set_zlim(0, 100)
ax.plot_wireframe(xpts, ypts, zpts)
ax.view_init(elev=12, azim=78)

def randrange(n, vmin, vmax):
    return (vmax - vmin)*np.random.rand(n) + vmin

n = 10
for n in range(21):
    xs = randrange(n, 0, 350)
    ys = randrange(n, -75, 75)
    zs = randrange(n, 0, 100)
    ax.scatter(xs, ys, zs)
dat = np.dstack((xs,ys,zs))
ax.set_xlabel('X Label')
ax.set_xlim(0,350)
ax.set_ylabel('Y Label')
ax.set_ylim(-75,75)
ax.set_zlabel('Z Label')
ax.set_zlim(0,100)

ax = fig.add_subplot(212, projection='3d')
ax.set_xlim(0,365); ax.set_ylim(-85, 85); ax.set_zlim(0, 100)
ax.plot_wireframe(xpts,ypts,zpts)
ax.view_init(elev=12, azim=78)

plt.show()
dist = []

# Calculate distance from first point to all other points in cloud
for l in range(len(xpts)):
    aaa = lin[0][0]-dat
    dist.append(np.sqrt(aaa[0][l][0]**2+aaa[0][l][1]**2+aaa[0][l][2]**2))
full = np.dstack((dat,dist))
aaa = full[0][full[0][:,3].argsort()]
print(aaa[0:10])
Community
  • 1
  • 1
AaronJPung
  • 1,105
  • 1
  • 19
  • 35
  • Your implementation seems OK. if you are interested in the quantity in interpolating the quantity at only one point. However, if you would like to do it for other points, it seems very inefficient. There are way to do the interpolation based on neighbours, but could you please specify why you want to do this using neighbour particles? – Alejandro Apr 11 '16 at 20:41
  • When you run the script, you get a line segment through the particle cloud. Ultimately, let's imagine that the line segment is made up of 5 points. At the first point in the line segment, I would like to find the nearest N points in the point cloud. I then want to interpolate the nearest N values of the point cloud to find the value at the first point in the line segment. I would then repeat this for the second point, and so on. – AaronJPung Apr 11 '16 at 20:47
  • Edit: The point cloud is based on a dataset in 3d space. I think the best way to find the value at a given point in space, is to use the datapoints closest to the point of interest (e.g. the first point on the line segment) – AaronJPung Apr 11 '16 at 20:48
  • 1
    http://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interpn.html#scipy.interpolate.interpn – roadrunner66 Apr 11 '16 at 21:50
  • @roadrunner66, if you could add a coded example, that would be a lot of help! Thanks for the suggestion. – AaronJPung Apr 11 '16 at 22:00

1 Answers1

2

A basic example. Note that the meshgrid is not needed for the interpolation, but only to make a fast ufunc to generate an example function A=f(x,y,z), here A=x+y+z.

from scipy.interpolate import interpn
import numpy as np

#make up a regular 3d grid 
X=np.linspace(-5,5,11)
Y=np.linspace(-5,5,11)
Z=np.linspace(-5,5,11)
xv,yv,zv = np.meshgrid(X,Y,Z)

# make up a function   
# see http://docs.scipy.org/doc/numpy/reference/ufuncs.html
A = np.add(xv,np.add(yv,zv))   
#this one is easy enough for us to know what to expect at (.5,.5,.5)

# usage : interpn(points, values, xi, method='linear', bounds_error=True, fill_value=nan) 
interpn((X,Y,Z),A,[0.5,0.5,0.5])

Output:

array([ 1.5])

If you pass in an array of points of interest, it will give you multiple answers.

roadrunner66
  • 7,772
  • 4
  • 32
  • 38