3D ábrák

A matplotlib csomag elsősorban 2D ábrák gyártására lett kitalálva. Ennek ellenére rendelkezik néhány 3D-s ábrakészítési függvénnyel is. Vizsgáljunk meg ebből párat! Ahhoz, hogy a 3D-s ábrázolási függvényeket el tudjuk érni, be kell tölteni a matplotlib csomag mpl_toolkits.mplot3d alcsomagját.

In [1]:
%pylab inline     
from mpl_toolkits.mplot3d import * #3D-s ábrák alcsomagja
from ipywidgets import *  #interaktivitáshoz szükséges függvények
Populating the interactive namespace from numpy and matplotlib

Térbeli görbék, adathalmazok

Ahhoz hogy egy ábrát térben tudjunk megjeleníteni, fel kell készíteni a környezetet. A térbeli ábrák megjelenítése és azok tulajdonságainak beállítása kicsit körülményesebb a 2D-s ábráknál. A legszembetűnőbb különbség, hogy az ábrák úgynevezett axes (körül belül itt a koordinátatengelyekre kell gondolni...) objektumok köré csoportosulnak, s ezek tulajdonságaiként, illetve ezeken alkalmazott függvényekként jönnek létre maguk az ábrák. Példaképpen ábrázoljunk egy egszerű paraméteres térbeli görbét! Legyen ez a görbe a következő spirális függvény:

\begin{equation} \mathbf{r}(t)=\left(\begin{array}{c} \cos(3t)\\ \sin(3t)\\ t \end{array}\right) \end{equation}

Először is gyártsuk let a $t$ paraméter mintavételezési pontjait a $[0,2\pi]$ intervallumban:

In [3]:
t=linspace(0,2*pi,100) # 100 pont 0 és 2*pi között

A következő kódcellában két dolog fog történni. Előszöris létrehozzuk az ax nevű axes objektumot, amelynek expliciten megadjuk, hogy 3D-s koordinátarendszer legyen. Illetve erre az objektumra hatva a plot függvénnyel létrehozzuk magát az ábrát. Figyeljük meg, hogy most a plot függvény háruom bemenő paramétert vár!

In [4]:
ax=subplot(1,1,1,projection='3d') #térbeli koordináta tengely létrehozása
ax.plot(cos(3*t),sin(3*t),t)
Out[4]:
[<mpl_toolkits.mplot3d.art3d.Line3D at 0x7f8e147907b8>]

Ahogy a síkbeli ábráknál láttuk, a plot függvényt itt is használhatjuk rendezetlenül mintavételezett adatok ábrázolására is.

In [5]:
ax=subplot(1,1,1,projection='3d')
ax.plot(rand(10),rand(10),rand(10),'o')
Out[5]:
[<mpl_toolkits.mplot3d.art3d.Line3D at 0x7f8e147900f0>]

A stílusdefiníciók a 2D ábrákhoz hasonló kulcsszavas argumentumok alapján dolgozódnak fel! Lássunk erre is egy példát:

In [6]:
ax=subplot(1,1,1,projection='3d') #térbeli koordináta tengely létrehozása
ax.plot(cos(3*t),sin(3*t),t,color='green',linestyle='dashed',linewidth=3)
Out[6]:
[<mpl_toolkits.mplot3d.art3d.Line3D at 0x7f8e14068400>]

Térbeli ábrák megjelenítése kapcsán rendszeresen felmerülő probléma, hogy jó irányból nézzünk rá az ábrára. Az ábra nézőpontjait a view_init függvény segítségével tudjuk megadni. A view_init két paramétere ekvatoriális gömbi koordinátarendszerben adja meg az ábra nézőpontját. A két bemenő paraméter a deklináció és az azimutszög fokban mérve. Például az $x$-tengely felől így lehet készíteni ábrát:

In [7]:
ax=subplot(1,1,1,projection='3d') #térbeli koordináta tengely létrehozása
ax.plot(cos(3*t),sin(3*t),t)
ax.view_init(0,0)

Az $y$-tengely felől pedig így:

In [8]:
ax=subplot(1,1,1,projection='3d') #térbeli koordináta tengely létrehozása
ax.plot(cos(3*t),sin(3*t),t)
ax.view_init(0,90)

Ha interaktív függvényeket használunk, akkor a nézőpontot az alábbiak szerint interaktívan tudjuk változtatni:

In [9]:
def forog(th,phi):
    ax=subplot(1,1,1,projection='3d')
    ax.plot(sin(3*t),cos(3*t),t)
    ax.view_init(th,phi)

interact(forog,th=(-90,90),phi=(0,360));

Kétváltozós függvények és felületek

A térbeli ábrák egyik előnye, hogy térbeli felületeket is meg tudunk jeleníteni. Ennek a legegyszerűbb esete a kétváltozós $$z=f(x,y)$$ függvények magasságtérképszerű ábrázolása. Ahogy azt már megszoktuk, itt is az első feladat a mintavételezés és a függvény kiértékelése. Az alábbiakban vizsgáljuk meg a $$z=-[\sin(x) ^{10} + \cos(10 + y x) \cos(x)]\exp((-x^2-y^2)/4)$$ függvényt!

In [10]:
x,y = meshgrid(linspace(-3,3,250),linspace(-5,5,250)) # mintavételezési pontok legyártása.
z = -(sin(x) ** 10 + cos(10 + y * x) * cos(x))*exp((-x**2-y**2)/4) # függvény kiértékelés

A plot_surface függvény segítségével jeleníthetjük meg ezt a függvényt.

In [11]:
ax = subplot(111, projection='3d')
ax.plot_surface(x, y, z)
Out[11]:
<mpl_toolkits.mplot3d.art3d.Poly3DCollection at 0x7f8e142ef2e8>

Sokszor szemléletes a kirajzolódott felületet valamilyen színskála szerint színezni. Ezt a síkbeli ábráknál már megszokott módon a cmap kulcsszó segítségével tehetjük.

In [12]:
ax = subplot(111, projection='3d')
ax.plot_surface(x, y, z,cmap='viridis')
Out[12]:
<mpl_toolkits.mplot3d.art3d.Poly3DCollection at 0x7f8e0e42a400>

A térbeli felületek legáltalánosabb megadása kétparaméteres vektor értékű függvényekkel lehetséges. Azaz

\begin{equation} \mathbf{r}(u,v)=\left(\begin{array}{c} f(u,v)\\ g(u,v)\\ h(u,v) \end{array}\right) \end{equation}

Vizsgáljunk meg erre egy példát, ahol a megjeleníteni kívánt felület egy tórusz! A tórusz egy lehetséges paraméterezése a következő:

\begin{equation} \mathbf{r}(\theta,\varphi)=\left(\begin{array}{c} (R_1 + R_2 \cos \theta) \cos{\varphi}\\ (R_1 + R_2 \cos \theta) \sin{\varphi} \\ R_2 \sin \theta \end{array}\right) \end{equation}

Itt $R_1$ és $R_2$ a tórusz két sugarának paramétere, $\theta$ és $\varphi$ pedig mind a ketten a $[0,2\pi]$ intervallumon futnak végig. Legyen $R_1=4$ és $R_2=1$. Rajzoljuk ki ezt a felületet! Első lépésként gyártsuk le az ábrázolandó felület pontjait:

In [12]:
theta,phi=meshgrid(linspace(0,2*pi,250),linspace(0,2*pi,250))
x=(4 + 1*cos(theta))*cos(phi)
y=(4 + 1*cos(theta))*sin(phi) 
z=1*sin(theta)

Ábrázolni ismét a plot_surface függvény segítségével tudunk:

In [13]:
ax = subplot(111, projection='3d')
ax.plot_surface(x, y, z)
Out[13]:
<mpl_toolkits.mplot3d.art3d.Poly3DCollection at 0x7f70173b3d68>

A fenti ábrát egy kicsit arányosabbá tehetjük, ha a tengelyek megjelenítésének arányát, illetve a tengerek határait átállítjuk. Ezt a set_aspect, illetve a set_xlim, set_ylim és set_zlim függvények segítségével tehetjük meg:

In [14]:
ax = subplot(111, projection='3d')
ax.plot_surface(x, y, z)
ax.set_aspect('equal');
ax.set_xlim(-5,5);
ax.set_ylim(-5,5);
ax.set_zlim(-5,5);

Végül tegyük ezt az ábrát is interaktívvá:

In [15]:
def forog(th,ph):
    ax = subplot(111, projection='3d')
    ax.plot_surface(x, y, z)
    ax.view_init(th,ph)
    ax.set_aspect('equal');
    ax.set_xlim(-5,5);
    ax.set_ylim(-5,5);
    ax.set_zlim(-5,5);

interact(forog,th=(-90,90),ph=(0,360));

Erőterek 3D-ben

Térbeli vektortereket, azaz olyan függvényeket, amelyek a tér minden pontjához egy háromdimenziós vektort rendelnek, a síkbeli ábrákhoz hasonlóan itt is a quiver parancs segítségével tudunk megjeleníteni. Az alábbi példában az egységgömb felületének 100 pontjába rajzolunk egy-egy radiális irányba mutató vektort:

In [16]:
phiv,thv=(2*pi*rand(100),pi*rand(100))                    #Ez a két sor a térbeli egység gömb 
xv,yv,zv=(cos(phiv)*sin(thv),sin(phiv)*sin(thv),cos(thv)) #100 véletlen pontját jelöli ki
uv,vv,wv=(xv,yv,zv)                                       #Ez pedig a megfelelő pontokhoz hozzá rendel egy egy radiális vektort
In [17]:
ax = subplot(111, projection='3d')
ax.quiver(xv, yv, zv, uv, vv, wv, length=0.3,color='darkcyan')
ax.set_aspect('equal')