meshes#

La fonction np.meshgrid est intéressante - entre autres - pour dessiner des courbes en 3d

Son fonctionnement est assez similaire à np.indices, mais au lieu de produire des entiers, on va typiquement lui passer des tableaux produits à base de np.linspace.

rappels#

import numpy as np
np.indices((5, 10))
array([[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        [2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
        [3, 3, 3, 3, 3, 3, 3, 3, 3, 3],
        [4, 4, 4, 4, 4, 4, 4, 4, 4, 4]],

       [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]])
np.linspace(-np.pi, np.pi, 10)
array([-3.14159265, -2.44346095, -1.74532925, -1.04719755, -0.34906585,
        0.34906585,  1.04719755,  1.74532925,  2.44346095,  3.14159265])

pour dessiner une courbe en 3D#

Imaginons qu’on veuille représenter une fonction de \(\mathbb{R}^2 \rightarrow \mathbb{R}\)

disons \(f(x, y) = x^2 + y^2\)

sur un domaine rectangulaire

la technique standard consiste à

  1. créer deux tableaux X et Y rectangulaires, qui correspondent à notre pavage
    le premier contient les X, et le second contient les Y, des points du pavage

  2. appliquer la fonction en question à ces deux tableaux, ce qui donne un tableau rectangulaire avec la valeur de la fonction à ce point

  3. on peut ensuite passer ces trois tableaux rectangulaires à plt.plot_surface

étape 1: meshgrid#

# on commence par calculer les domaines

domX = np.linspace(-5, 5, 5)
domY = np.linspace(0, 9, 10)
# avec meshgrid, c'est magique, ça fabrique le pavage pour nous

X, Y = np.meshgrid(domX, domY)
X, Y
(array([[-5. , -2.5,  0. ,  2.5,  5. ],
        [-5. , -2.5,  0. ,  2.5,  5. ],
        [-5. , -2.5,  0. ,  2.5,  5. ],
        [-5. , -2.5,  0. ,  2.5,  5. ],
        [-5. , -2.5,  0. ,  2.5,  5. ],
        [-5. , -2.5,  0. ,  2.5,  5. ],
        [-5. , -2.5,  0. ,  2.5,  5. ],
        [-5. , -2.5,  0. ,  2.5,  5. ],
        [-5. , -2.5,  0. ,  2.5,  5. ],
        [-5. , -2.5,  0. ,  2.5,  5. ]]),
 array([[0., 0., 0., 0., 0.],
        [1., 1., 1., 1., 1.],
        [2., 2., 2., 2., 2.],
        [3., 3., 3., 3., 3.],
        [4., 4., 4., 4., 4.],
        [5., 5., 5., 5., 5.],
        [6., 6., 6., 6., 6.],
        [7., 7., 7., 7., 7.],
        [8., 8., 8., 8., 8.],
        [9., 9., 9., 9., 9.]]))

on voit bien la ressemblance avec indices, en ce sens que le premier tableau contient la coordonnée et X et le second contient la coordonnée en Y

X.shape, Y.shape
((10, 5), (10, 5))

étape 2: calcul de Z#

maintenant on peut appliquer la fonction

Z = X**2 + Y*2
Z.shape
(10, 5)
Z
array([[25.  ,  6.25,  0.  ,  6.25, 25.  ],
       [27.  ,  8.25,  2.  ,  8.25, 27.  ],
       [29.  , 10.25,  4.  , 10.25, 29.  ],
       [31.  , 12.25,  6.  , 12.25, 31.  ],
       [33.  , 14.25,  8.  , 14.25, 33.  ],
       [35.  , 16.25, 10.  , 16.25, 35.  ],
       [37.  , 18.25, 12.  , 18.25, 37.  ],
       [39.  , 20.25, 14.  , 20.25, 39.  ],
       [41.  , 22.25, 16.  , 22.25, 41.  ],
       [43.  , 24.25, 18.  , 24.25, 43.  ]])

étape 3: dessin#

et la dessiner

import matplotlib.pyplot as plt

%matplotlib widget
fig, ax = plt.subplots(subplot_kw=dict(projection='3d'))
surf = ax.plot_surface(X, Y, Z)

plt.show()

naturellement dans la vraie vie on construit des domaines avec plus de points, par défaut linspace met 50 points dans l’intervalle

domX2, domY2 = np.linspace(-5, 5), np.linspace(0, 10)
X2, Y2 = np.meshgrid(domX2, domY2)
Z2 = X2**2 + Y2**2
fig, ax = plt.subplots(subplot_kw=dict(projection='3d'))
surf = ax.plot_surface(X2, Y2, Z2)

plt.show()