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?
python
matplotlib
3d
geometry
Vincent
fuente
fuente
Respuestas:
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()
fuente
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.
fuente
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()
fuente
[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?