python - triangulo - Cómo dibujar aviones que se cruzan?
reconocimiento de figuras geometricas en python (2)
Matplotlib tiene capacidad de proyección 3D, pero las líneas punteadas se dibujan con un ancho constante en la vista final de la imagen bidimensional, y no se ven como si estuvieran planas en los planos inclinados. Si la geometría es simple, y las "órbitas" circulares, podría funcionar, pero si quieres dibujar elipses vistas en ángulo, el espectador puede desear pistas más visuales sobre toda la disposición 3D.
Si tuviera que hacer una bonita ilustración elegante así, pero aún más bonita y elegante, y no tenía que ser automática, empezaría por crear los gráficos, al menos los círculos de líneas discontinuas, para cada uno de los planos como una imagen bidimensional plana simple usando lo que parece útil en este momento: un programa de dibujo vectorial como Illustrator o Inkscape, o en matplotlib si hay datos que se deben seguir.
Entonces, usaría POV-Ray o Blender para modelar los planos en cualquier ángulo, esferas para las cosas redondas (¿planetas?). Los gráficos 2D ya generados se convertirán en texturas para mapearlas en los planos. POV-Ray usa un lenguaje de scripting que permite guardar, modificar y copiar un registro para futuros proyectos. Si realmente fue una sola vez y no me importó hacerlo todo a mano, Blender es bueno. Cualquiera que sea la herramienta que uso, el resultado es una imagen que muestra la proyección deseada de los elementos geométricos tridimensionales en 2D.
¿Se supone que las cosas redondas, lo que llamo "planetas", son círculos planos en el trabajo final, como en los ejemplos? Luego los dibujaría con una aplicación de dibujo vectorial sobre la imagen renderizada en 3D. Pero sospecho que preferirías esferas en 3D.
Las muestras mostradas no tienen iluminación ni sombras. Las sombras ayudarían a aclarar la geometría en 3D, aunque la primera de esas dos ilustraciones no es tan mala. La corta línea verde que muestra el planeta del plano inclinado sobre la línea roja parece bastante clara, pero una sombra ayudaría. La segunda ilustración se ve un poco más confusa en cuanto a la forma, la ubicación y las intersecciones de las diversas entidades. Aquí, las sombras ayudarían más. POV-Ray o Blender estarán encantados de crear estos con poco esfuerzo. Aún más, las interreflexiones, conocidas como radiosity, ayudan a ver las relaciones 3D en imágenes 2D. Este efecto avanzado es fácil de hacer en estos días, sin necesidad de experiencia en óptica o gráficos, simplemente sabiendo que existe.
Por supuesto, este consejo no es bueno a menos que uno ya esté familiarizado con los gráficos 3D y las herramientas como POV-Ray.
Para una solución automatizada, usar OpenGL en algún programa rápido y sucio puede ser lo mejor. Sin embargo, las sombras pueden tomar algún trabajo.
Quiero usar matplotlib para dibujar más o menos la figura que adjunto a continuación, que incluye los dos planos que se intersectan con la cantidad correcta de transparencia que indica sus orientaciones relativas, y los círculos y vectores en los dos planos proyectados en 2D.
No estoy seguro de si hay un paquete existente para hacer esto, ¿alguna pista?
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111, projection=''3d'')
dim = 10
X, Y = np.meshgrid([-dim, dim], [-dim, dim])
Z = np.zeros((2, 2))
angle = .5
X2, Y2 = np.meshgrid([-dim, dim], [0, dim])
Z2 = Y2 * angle
X3, Y3 = np.meshgrid([-dim, dim], [-dim, 0])
Z3 = Y3 * angle
r = 7
M = 1000
th = np.linspace(0, 2 * np.pi, M)
x, y, z = r * np.cos(th), r * np.sin(th), angle * r * np.sin(th)
ax.plot_surface(X2, Y3, Z3, color=''blue'', alpha=.5, linewidth=0, zorder=-1)
ax.plot(x[y < 0], y[y < 0], z[y < 0], lw=5, linestyle=''--'', color=''green'',
zorder=0)
ax.plot_surface(X, Y, Z, color=''red'', alpha=.5, linewidth=0, zorder=1)
ax.plot(r * np.sin(th), r * np.cos(th), np.zeros(M), lw=5, linestyle=''--'',
color=''k'', zorder=2)
ax.plot_surface(X2, Y2, Z2, color=''blue'', alpha=.5, linewidth=0, zorder=3)
ax.plot(x[y > 0], y[y > 0], z[y > 0], lw=5, linestyle=''--'', color=''green'',
zorder=4)
plt.axis(''off'')
plt.show()
advertencias:
Estoy ejecutando una versión muy cercana al maestro actual, por lo que no estoy seguro de qué funcionará en versiones anteriores
La razón para dividir el trazado es que "arriba" y "abajo" se determinan de una manera algo misteriosa (no estoy estrictamente seguro de que el
zorder
realmente hace algo), y realmente depende del orden en que se dibujan los artistas. Por lo tanto, las superficies no pueden cruzarse (una estará encima de la otra en todas partes), por lo que debe trazar las secciones en cada lado de la intersección por separado. (Puedes verlo en la línea negra que no se dividió en "encima" del plano azul superior).El orden "correcto" de las superficies también parece depender del ángulo de visión.