2016-12-10 4 views
9

Gegeben drei 1D-Arrays von X, Y und Z-Koordinaten, wie in eine 3D-Mesh-Pfad mit numpy konvertieren?Wie man Arrays von X-, Y-, Z-Koordinaten in 3D-Pfad in numpy konvertiert

ich es geschafft, dies für 2D zu tun mit numpy (dh keine für Schleifen):

import numpy 

def path_2d_numpy(x, y): 
    m1, m2 = numpy.meshgrid(x, y) 
    m1[1::2] = m1[1::2,::-1] 
    r = numpy.append(m1, m2) 
    r.shape = 2,-1 
    return r.T 

from matplotlib import lines 
from matplotlib import pyplot 

def plot_path_2d(path): 
    x, y = path.T 
    pyplot.plot(x, y, '-ro', lw=3) 
    pyplot.show() 

x = numpy.linspace(4, 1, 4) 
y = numpy.linspace(1, 5, 5) 
path = path_2d_numpy(x, y) 
plot_path_2d(path) 

die Ausgänge:

2D mesh path

... konnte sie aber nicht für 3D tun . Zeige reine Python-Lösung (dh ohne numpy):

import numpy 

def path_3d(x, y, z): 
    nb_points =len(x)*len(y)*len(z) 
    path = numpy.empty((nb_points, 3)) 

    xord, yord, i = True, True, 0 
    for zi in z: 
     for yi in y[::1 if yord else -1]: 
      for xi in x[::1 if xord else -1]: 
       path[i] = xi, yi, zi 
       i += 1 
      xord = not xord 
     yord = not yord 
    return path 

from matplotlib import pyplot 
from mpl_toolkits.mplot3d import Axes3D 

def plot_path_3d(path): 
    fig = pyplot.figure() 
    ax = fig.gca(projection='3d') 
    xx, yy, zz = path.T 
    ax.plot(xx, yy, zz, '-bo', lw=3) 
    pyplot.show() 

x = numpy.linspace(4, 1, 4) 
y = numpy.linspace(1, 5, 5) 
z = numpy.linspace(-3, 0, 3) 

path = path_3d(x, y, z) 
plot_path_3d(path) 

die Ausgänge:

3D mesh path

Essencialy, was ich suche ist eine numpy Implementierung von path_3d wie ich für path_2d_numpy.

Ich brauche das, weil die tatsächlichen Arrays, mit denen ich es zu tun habe ziemlich groß sind. Es ohne zu tun ist einfach zu langsam.

Antwort

6

Wie sieht das aus?

import numpy as np 

def path_3d_numpy(x, y, z): 
    coords = np.stack(np.meshgrid(x, y, z), axis=-1) # shape = (nx, ny, nz, 3) 
    coords[1::2,:,:] = coords[1::2,::-1,:] 
    coords[:,1::2,:] = coords[:,1::2,::-1] 
    return coords.reshape(-1, 3) # flatten out the other axes 

Hat iterieren nicht die Punkte in genau der gleichen Reihenfolge wie bei Ihnen, aber man konnte das in Ordnung bringen einfach durch einige Indizes um

Swapping

Ähnlich Ihr 2d Fall als

geschrieben werden konnte
def path_2d_numpy(x, y): 
    coords = np.stack(np.meshgrid(x, y), axis=-1) 
    coords[1::2] = coords[1::2,::-1] 
    return coords.reshape(-1, 2) 

Für einige echte Overkill, können Sie dies auf N Dimensionen erweitern:

def path_nd(*args): 
    coords = np.stack(np.meshgrid(*args), axis=-1) 
    N = len(args) 

    axes = np.arange(N) 
    for i in range(N-1): 
     # the last axis isn't part of our mesh, so don't roll it 
     rolled_axes = tuple(np.roll(axes, -i)) + (N,) 
     rolled_view = np.transpose(coords, rolled_axes) 
     rolled_view[1::2,:] = rolled_view[1::2,::-1] 

    return coords.reshape(-1, N) 
Verwandte Themen