2016-05-09 20 views
5

Gegeben eine Menge von Punkten in (X, Y, Z) -Koordinaten, die Punkte auf einer Oberfläche sind Ich würde gerne in der Lage sein, Z-Werte an beliebigen (X, Y) Koordinaten zu interpolieren. Ich habe einige Erfolge mit der Verwendung von mlab.griddata zum Interpolieren von Werten auf einem Gitter gefunden, aber ich möchte in der Lage sein, eine allgemeine Verwendungsfunktion für jede (X, Y) -Koordinate aufzurufen.Gegeben eine Menge von Punkten, die in (X, Y, Z) -Koordinaten definiert sind, interpoliere Z-Wert bei beliebigem (X, Y)

Die Punktmenge bildet eine grob halbkugelförmige Fläche. Um das Problem zu vereinfachen, versuche ich eine Methode zu schreiben, die Werte zwischen bekannten Punkten der Hemisphäre interpoliert, die durch die darunter liegenden x-, y- und z-Koordinaten definiert sind. Obwohl es eine analytische Lösung gibt, um z = f (x, y) für eine perfekte Kugel zu finden, so dass Sie nicht interpolieren müssen, ist die tatsächliche Menge von Punkten keine perfekte Kugel, also sollten wir annehmen, dass wir sie brauchen um Werte bei unbekannten (X, Y) Koordinaten zu interpolieren. Link to IPython notebook with point data

resolution = 10 
u = np.linspace(-np.pi/2, np.pi/2, resolution) 
v = np.linspace(0, np.pi, resolution) 

U, V = np.meshgrid(u, v) 

xs = np.sin(U) * np.cos(V) 
ys = np.sin(U) * np.sin(V) 
zs = np.cos(U) 

Ich habe mit scipy.interpolate.interp2d, die „eine Funktion, deren Aufruf gibt Methode verwendet Spline-Interpolation den Wert der neuen Punkte zu finden.“

def polar(xs, ys, zs, resolution=10): 
    rs = np.sqrt(np.multiply(xs, xs) + np.multiply(ys, ys)) 
    ts = np.arctan2(ys, xs) 
    func = interp2d(rs, ts, zs, kind='cubic') 
    vectorized = np.vectorize(func) 

    # Guesses 
    ri = np.linspace(0, rs.max(), resolution) 
    ti = np.linspace(0, np.pi * 2, resolution) 

    R, T = np.meshgrid(ri, ti) 
    Z = vectorized(R, T) 
    return R * np.cos(T), R * np.sin(T), Z 

Leider bekomme ich ziemlich komisch Ergebnisse, ähnlich wie bei anderen Stackoverflow user who tried to use interp2d.

Polar result

den meisten Erfolg I bisher gefunden haben inverse squares wird unter Verwendung der Z-Werte abzuschätzen bei (X, Y). Aber die Funktion ist nicht perfekt zum Schätzen von Werten von Z in der Nähe von Z = 0.

Inverse Squares result

Was kann ich tun, um eine Funktion z = f(x, y) eine Menge von Punkten in (x, y, z) gegeben zu bekommen? Fehle ich hier etwas ... brauche ich mehr als eine Punktwolke, um einen Wert auf einer Fläche zuverlässig zu schätzen?

EDIT:

Dies ist die Funktion, die ich mit dem Schreiben endete. Die Funktion verwendet Eingabearrays von xs, ys, zs und interpoliert bei x, y unter Verwendung von scipy.interpolate.griddata, die kein regelmäßiges Raster erfordert. Ich bin mir sicher, dass es eine klügere Möglichkeit gibt, dies zu tun, und würde mich über Updates freuen, aber es funktioniert und ich bin nicht an der Leistung interessiert. Ein Snippet für den Fall, dass es jemandem in der Zukunft hilft.

def interpolate(x, y, xs, ys, zs): 
    r = np.sqrt(x*x + y*y) 
    t = np.arctan2(y, x) 

    rs = np.sqrt(np.multiply(xs, xs) + np.multiply(ys, ys)) 
    ts = np.arctan2(ys, xs) 

    rs = rs.ravel() 
    ts = ts.ravel() 
    zs = zs.ravel() 

    ts = np.concatenate((ts - np.pi * 2, ts, ts + np.pi * 2)) 
    rs = np.concatenate((rs, rs, rs)) 
    zs = np.concatenate((zs, zs, zs)) 


    Z = scipy.interpolate.griddata((rs, ts), zs, (r, t)) 
    Z = Z.ravel() 
    R, T = np.meshgrid(r, t) 
    return Z 
+0

Verwenden Sie maschinelles Lernen. :) – erip

+0

hast du versucht scipy.interpolate.LinearNDInterpolator? Ich habe gute Erfahrungen damit für diese Art von Problemen –

Antwort

2

Sie sagen, Sie haben versucht, griddata zu verwenden. Warum funktionierte das nicht? griddata funktioniert auch, wenn die neuen Punkte nicht regelmäßig voneinander getrennt sind.Zum Beispiel

# Definitions of xs, ys and zs 
nx, ny = 20, 30 
x = np.linspace(0, np.pi, nx) 
y = np.linspace(0, 2*np.pi, ny) 

X,Y = np.meshgrid(x, y) 

xs = X.reshape((nx*ny, 1)) 
ys = Y.reshape((nx*ny, 1)) 

## Arbitrary definition of zs 
zs = np.cos(3*xs/2.)+np.sin(5*ys/3.)**2 

## new points where I want the interpolations 
points = np.random.rand(1000, 2) 

import scipy.interpolate 
zs2 = scipy.interpolate.griddata(np.hstack((xs, ys)), zs, points) 

Sind Sie nicht danach?

+0

Ja, das funktioniert. Vielen Dank! Ich wollte eine Implementierung, bei der ich den zugrunde liegenden Funktionsaufruf (wie den Rückgabewert von interp2d) abrufen und jeweils einen Punkt übergeben konnte, aber ich kann den anderen Code immer so umformen, dass er im Array von (X, Y) -Punkten übergeben wird. –

1

Wenn ich Ihre Frage zu verstehen, müssen Sie Punkte xs, ys, zs, die von

xs = np.sin(U) * np.cos(V) 
ys = np.sin(U) * np.sin(V) 
zs = np.cos(U) 

definiert sind, was Sie wollen, ist in der Lage sein, einen z-Wert für einen bestimmten zu interpolieren und finden x und y? Warum brauchst du eine Interpolation? Die obigen Gleichungen stellen eine Kugel, können sie als xs*xs + ys*ys + zs*zs = 1 neu geschrieben werden, so gibt es eine einfache analytische Lösung für dieses Problem:

def Z(X, Y): 
    return np.sqrt(1-X**2-Y**2) 
    ## or return -np.sqrt(1-X**2-Y**2) since this equation has two solutions 

, wenn ich die Frage falsch verstanden.

+0

Ah, um zu klären, ist die Menge der Punkte grob halbkugelförmig, so dass die analytische Lösung nicht unbedingt wahr sein wird. Ich werde meine Frage bearbeiten, um dies zu umfassen ... –

Verwandte Themen