Trazar un cubo 3d, una esfera y un vector en Matplotlib

80

Busco cómo trazar algo con menos instrucción posible con Matplotlib pero no encuentro ninguna ayuda para esto en la documentación.

Quiero trazar las siguientes cosas:

  • un cubo de estructura alámbrica centrado en 0 con una longitud de lado de 2
  • una esfera de "estructura alámbrica" ​​centrada en 0 con un radio de 1
  • un punto en las coordenadas [0, 0, 0]
  • un vector que comienza en este punto y va a [1, 1, 1]

¿Como hacer eso?

Vincent
fuente
3
También echa un vistazo a mayavi2 . Es un poco dependiente, pero tiene algunos comandos de alto nivel realmente impresionantes. Puedo armar una respuesta más detallada basada en ese paquete si lo deseo. . .
meawoppl

Respuestas:

180

Es un poco complicado, pero puedes dibujar todos los objetos con el siguiente código:

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from itertools import product, combinations


fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_aspect("equal")

# draw cube
r = [-1, 1]
for s, e in combinations(np.array(list(product(r, r, r))), 2):
    if np.sum(np.abs(s-e)) == r[1]-r[0]:
        ax.plot3D(*zip(s, e), color="b")

# draw sphere
u, v = np.mgrid[0:2*np.pi:20j, 0:np.pi:10j]
x = np.cos(u)*np.sin(v)
y = np.sin(u)*np.sin(v)
z = np.cos(v)
ax.plot_wireframe(x, y, z, color="r")

# draw a point
ax.scatter([0], [0], [0], color="g", s=100)

# draw a vector
from matplotlib.patches import FancyArrowPatch
from mpl_toolkits.mplot3d import proj3d


class Arrow3D(FancyArrowPatch):

    def __init__(self, xs, ys, zs, *args, **kwargs):
        FancyArrowPatch.__init__(self, (0, 0), (0, 0), *args, **kwargs)
        self._verts3d = xs, ys, zs

    def draw(self, renderer):
        xs3d, ys3d, zs3d = self._verts3d
        xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M)
        self.set_positions((xs[0], ys[0]), (xs[1], ys[1]))
        FancyArrowPatch.draw(self, renderer)

a = Arrow3D([0, 1], [0, 1], [0, 1], mutation_scale=20,
            lw=1, arrowstyle="-|>", color="k")
ax.add_artist(a)
plt.show()

output_figure

HYRY
fuente
12

Para dibujar solo la flecha, hay un método más fácil: -

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_aspect("equal")

#draw the arrow
ax.quiver(0,0,0,1,1,1,length=1.0)

plt.show()

carcaj se puede utilizar para trazar múltiples vectores de una sola vez. El uso es el siguiente: - [de http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html?highlight=quiver#mpl_toolkits.mplot3d.Axes3D.quiver]

carcaj (X, Y, Z, U, V, W, ** kwargs)

Argumentos:

X, Y, Z: las coordenadas x, y y z de las ubicaciones de las flechas

U, V, W: Las componentes x, y y z de los vectores flecha

Los argumentos pueden ser escalares o parecidos a una matriz.

Argumentos de palabras clave:

longitud: [1.0 | flotar] La longitud de cada carcaj, por defecto a 1.0, la unidad es la misma con los ejes

arrow_length_ratio: [0.3 | flotar] La proporción de la punta de la flecha con respecto al carcaj, por defecto a 0.3

pivote: ['cola' | 'medio' | 'tip'] La parte de la flecha que está en el punto de la cuadrícula; la flecha gira sobre este punto, de ahí el nombre pivote. El valor predeterminado es 'cola'

normalizar: [Falso | Verdadero] Cuando es Verdadero, todas las flechas tendrán la misma longitud. Este valor predeterminado es Falso, donde las flechas tendrán diferentes longitudes dependiendo de los valores de u, v, w.

Aritra
fuente
0

Mi respuesta es una combinación de los dos anteriores con extensión a la esfera de dibujo de opacidad definida por el usuario y alguna anotación. Encuentra aplicación en la visualización de vectores b en una esfera para imágenes de resonancia magnética (IRM). Esperamos que te sea útil:

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

fig = plt.figure()
ax = fig.gca(projection='3d')

# draw sphere
u, v = np.mgrid[0:2*np.pi:50j, 0:np.pi:50j]
x = np.cos(u)*np.sin(v)
y = np.sin(u)*np.sin(v)
z = np.cos(v)
# alpha controls opacity
ax.plot_surface(x, y, z, color="g", alpha=0.3)


# a random array of 3D coordinates in [-1,1]
bvecs= np.random.randn(20,3)

# tails of the arrows
tails= np.zeros(len(bvecs))

# heads of the arrows with adjusted arrow head length
ax.quiver(tails,tails,tails,bvecs[:,0], bvecs[:,1], bvecs[:,2],
          length=1.0, normalize=True, color='r', arrow_length_ratio=0.15)

ax.set_xlabel('X-axis')
ax.set_ylabel('Y-axis')
ax.set_zlabel('Z-axis')

ax.set_title('b-vectors on unit sphere')

plt.show()
tash
fuente
por favor, explique [0:2*np.pi:50j, 0:np.pi:50j]cómo funcionará este segmento. ¿Cuál es el radio y el centro de la esfera en términos analíticos?
Ragnar