/ / Matplotlib jak trisurf matlab - python, matlab, matplotlib, 3d, mesh

Matplotlib jak trisurf matlab - python, matlab, matplotlib, 3d, mesh

Aby krótko opowiedzieć, chciałbym narysować ogólną trójwymiarową siatkę trójkątną w pytonie, Matplotlib wydaje się być idealnym kandydatem, ale pójdę z dowolnym renderingiem 3D, który może zrobić to, co mam zamiar opisać.

Załóżmy, że mam siatkę trójkątów zdefiniowaną przez X, Y,i Z, współrzędne 3D chmury punktów, każdy wektor o długości n i UVW, macierz 2D m-x-3, w której każdy rząd jest trzema indeksami do chmury punktów. Ta trójka reprezentuje pojedynczy trójkąt. Innymi słowy, mam m trójkąty ponad n punktów. W Matlab, aby wygenerować wykres 3D, po prostu:

trisurf(UVW, X, Y, Z)

Czy ktokolwiek ma z tym jakieś doświadczenie? W szczególności, czy mplots trisurf można przypiąć do butów?

Odpowiedzi:

5 dla odpowiedzi № 1

W zależności od twoich potrzeb, mayavi prawdopodobnie będzie najlepiej do tego pasował - jak na komentarz Davisa.

Jednak matplotlib pochodzi plot_trisurf do którego możesz idealnie przejść generycznie UVW, X, Y , Z jak opisujesz.

Przykład z siatką torusa:

import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib.tri as mtri

R = 1.
r = 0.8
n = 50
m = 50

def torus_triangles(n, m):
""" Returns triangles to mesh a (n, m) torus """
tri = []
for i in range(n):
for j in range(m):
a = i + j*(n)
b = ((i+1) % n) + j*n
d = i + ((j+1) % m) * n
c = ((i+1) % n) + ((j+1) % m) * n
tri += [[a, b, d], [b, c, d]]
return np.array(tri, dtype=np.int32)

theta0 = np.linspace(0, (2*np.pi), n, endpoint=False)
phi0 = np.linspace(0, (2*np.pi), m, endpoint=False)
theta, phi = np.meshgrid(theta0, phi0)

x = (R + r * np.sin(phi)) * np.cos(theta)
y = (R + r * np.sin(phi)) * np.sin(theta)
z = r * np.cos(phi)

triangles = torus_triangles(n , m)
triang = mtri.Triangulation(x.ravel(), y.ravel(), triangles)

fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
ax.plot_trisurf(triang, z.ravel(), lw=0.2, edgecolor="black", color="grey",
alpha=0.5)

plt.show()

wprowadź opis obrazu tutaj


1 dla odpowiedzi nr 2

Plotly ma implementację trisurf Pythona o otwartym kodzie źródłowym, która jest bliższa TRISFAB-s trisurf ().

Kod Pythona i przykłady tutaj:

https://plot.ly/python/tri-surf/

python trisurf


1 dla odpowiedzi nr 3

Szukałem również rozwiązania tego problemu i ta dyskusja pomogła mi odnieść sukces. Oto, jak to działa:

  1. Rozwiązanie bardzo podobnego problemu zostało już podane jako link tutaj w komentarzu z GBy (patrz wyżej: Barwienie powierzchni kuli za pomocą zestawu wartości skalarnych w matplotlib)

  2. Przeniesienie wiedzy na problem powoduje, że powstaje dodatkowa tablica zawierająca amplitudy i przypisująca ją do "leżącego u podstaw ScalarMappable przez set_array metoda ". Odpowiedni kod Pythona wygląda następująco:

    from mpl_toolkits.mplot3d import Axes3D
    from matplotlib import cm
    from matplotlib import pyplot as plt
    import numpy as np
    
    fig = plt.figure()
    ax = fig.gca(projection="3d")
    colors = np.mean(CorticalImage[Face], axis=1)
    collec = ax.plot_trisurf(Xcoordinates, Ycoordinates, Zcoordinates, triangles=Face, cmap=cm.jet, linewidth=0.2)
    collec.set_array(colors)
    collec.autoscale()
    ax.view_init(30, 0)
    cbar = fig.colorbar(collec)
    

Tablice Xcoordinates, Ycoordinates, Zcoordinates zawierają współrzędne X, Y i Z węzłów siatki. Podczas sprawdzania kształtu za pomocą np. Xcoordinates.shape To powinno wyglądać tak (750,), gdzie 750 to liczba węzłów siatki. Macierz Face jest taki sam jak matryca UVW w oryginalnym pytaniu zadawanym przez Larry'ego. Jest to "matryca 2D m-x-3, w której każdy wiersz jest trzema indeksami do chmury punktów". Jeśli sprawdzisz kształt matrycy Face powinno to być coś w stylu (1496, 3), gdzie 1496 to liczba trójkątów w siatce, a 3 to liczba węzłów w jednym trójkącie. Wreszcie tablica CorticalImage zawiera amplitudy dla każdego węzła wmesh i są to wartości, które chcemy zastosować dla kolorów siatki (a nie wartości Z). Kształt tej tablicy powinien być podobny do kształtów macierzy współrzędnych, tj. (750,).

WAŻNY!!! Widać, że liczba węzłów i liczba trójkątów nie są równe. To prawie zawsze tak jest. Dodatkowo amplitudy są zwykle podawane dla węzłów, a nie dla trójkątów. W związku z tym amplitudy należy obliczyć dla trójkątów, aby uzyskać odpowiednie kolory na wykresie. Odbywa się to w linii colors = np.mean(CorticalImage[Face], axis=1).


1 dla odpowiedzi nr 4

Pomyślałem o kompletności, dodałbym mayavi przykład tutaj, używając siatki z odpowiedzi GBy.

import numpy as np
from mayavi import mlab
from tvtk.api import tvtk

R = 1.
r = 0.8
n = 50
m = 50

def torus_triangles(n, m):
""" Returns triangles to mesh a (n, m) torus """
tri = []
for i in range(n):
for j in range(m):
a = i + j*(n)
b = ((i+1) % n) + j*n
d = i + ((j+1) % m) * n
c = ((i+1) % n) + ((j+1) % m) * n
tri += [[a, b, d], [b, c, d]]
return np.array(tri, dtype=np.int32)

theta0 = np.linspace(0, (2*np.pi), n, endpoint=False)
phi0 = np.linspace(0, (2*np.pi), m, endpoint=False)
theta, phi = np.meshgrid(theta0, phi0)

x = (R + r * np.sin(phi)) * np.cos(theta)
y = (R + r * np.sin(phi)) * np.sin(theta)
z = r * np.cos(phi)

triangles = torus_triangles(n , m)

mesh = mlab.triangular_mesh(x,y,z, triangles, representation="wireframe",color=(0,0,1) )

mlab.show()

Wydajność:

wprowadź opis obrazu tutaj