Python - 用矢量图形实现表面和形状的三维可视化

3
鉴于原问题的评论,我想强调回答这个问题应该遵循以下两点:
1)最终绘制的图应该是一个真正的矢量图形,类似于latex中的pgfplots/tikz包产生的结果。
2)最终绘制的图应该是一个正确的3D图,包含几个元素,因此绘图软件可能需要使用Z缓冲来正确地投影和渲染。
我想使用Python在单个图像中可视化/绘制3D曲面和几何形状。我对3D可视化感兴趣,但现在我正在尝试做以下事情:我想绘制一个三维坐标系上的鞍形曲面(例如作为适当函数的表面绘图),并且还要在鞍点处显示一个与之相切的3D球体。是否可以仅使用matplotlib完成此操作,还是需要使用更复杂的3D软件包如VTK?即使可以在matplotlib中完成,您是否建议将其用于此类应用程序,还是应该使用专门为此目的构建的程序?
为了让您了解我想要在Python中实现的内容,请参见此处。这是使用latex中的pgfplots完成的,但正如我在那个问题中提到的,该软件包也存在一些限制。它不是Python。
我对逼真的外观或花哨的渲染不感兴趣。这是针对物理/数学应用程序的,我希望图像具有mplot3D或latex中的pgfplots绘图的“外观”(使曲面呈现此类外观)。我已经查看了Python的3D渲染软件包,并且尽管我无法真正量化其原因(我认为可能是照明和光栅图形),但许多输出看起来更像是视频游戏而不是科学出版物(虽然这可能是这些渲染器预期的)。
我知道这是一个相当广泛的问题,如果有反对意见,我很乐意重新表述问题或使其更加具体。但是,我相信回答是否可以和应该使用matplotlib进行一般3D形状可视化的问题是有趣的。

尝试使用MayaVI,它在过去为我提供了很好的服务。 - berna1111
能否用Mayavi或VTK生成类似我链接的那样的图形?正如我在问题中提到的,我想要像使用mplot3D生成的干净、出版质量的图像。 - Quantum
1
我猜我觉得mplot3D图表有吸引力的原因是它们生成矢量图形,而我认为许多渲染器生成栅格图形。因此,理想情况下,我希望能够可视化形状和表面并将其导出为矢量图形图像。 - Quantum
我还建议使用MayaVI或Matplotlib。在我看来,相比其他两个工具,VTK的使用不太直观。 - dudakl
1个回答

2
Matplotlib和mplot3d可能无法满足您的需求,因为matplotlib不执行3D渲染(参见这里)。但是,VTK可能对您想要做的事情太重了。
以下是使用visvis软件包的示例:(https://github.com/almarklein/visvis)
import visvis as vv
import numpy as np

# Saddle surface.
x_saddle = np.arange(-5, 5, 0.25)
y_saddle = np.arange(-5, 5, 0.25)
x_saddle, y_saddle = np.meshgrid(x_saddle, y_saddle)
z_saddle = x_saddle**2/10. - y_saddle**2/10.

# Sphere
u = np.linspace(0, 2 * np.pi, 100)
v = np.linspace(0, np.pi, 100)

radius = 2.0
x_sphere = radius * np.outer(np.cos(u), np.sin(v))
y_sphere = radius * np.outer(np.sin(u), np.sin(v))
z_sphere = 2.0 + radius * np.outer(np.ones(np.size(u)), np.cos(v))

vv.figure()

# Plot the surfaces
vv.surf(X, Y, Z)
vv.surf(x, y, z)

app = vv.use()
app.Run()

使用visvis渲染的马鞍形和球体

请注意,您可以使用Mayavi实现类似的效果,但是我认为visvis的轴线看起来更好:

from mayavi import mlab
import numpy as np

# Saddle surface.
x_saddle = np.arange(-5, 5, 0.25)
y_saddle = np.arange(-5, 5, 0.25)
x_saddle, y_saddle = np.meshgrid(x_saddle, y_saddle)
z_saddle = x_saddle**2/10. - y_saddle**2/10.

# Sphere
u = np.linspace(0, 2 * np.pi, 100)
v = np.linspace(0, np.pi, 100)

radius = 2
x_sphere = radius * np.outer(np.cos(u), np.sin(v))
y_sphere = radius * np.outer(np.sin(u), np.sin(v))
z_sphere = 2.0 + radius * np.outer(np.ones(np.size(u)), np.cos(v))


# Plot the surface.
mlab.mesh(x_saddle, y_saddle, z_saddle)
mlab.mesh(x_radius, y_radius, z_radius)

mlab.axes()
mlab.show()

Saddle shape and sphere rendered with Mayavi


这看起来很有前途。但是,它们可以导出为矢量图形还是位图?而且,它们的外观与使用mplot3D绘制的内容不完全相同。通过调整这些应用程序的绘图设置,一般情况下可以使其外观类似吗? 我想我想要的是像使用Asymptote或latex的pgf/TikZ包所得到的那种图像,但是使用Python实现。 - Quantum
你无法从visvis(https://github.com/almarklein/visvis/wiki/Publishing)获取矢量图形,但从Mayavi(http://docs.enthought.com/mayavi/mayavi/auto/mlab_figure.html)似乎是可能的。 我怀疑能否完全获得与mplot3d相同的外观,但我可能错了。然而,通过调整绘图设置,应该可以得到可发布的内容。 - jcgiret
还有Vispy(http://vispy.org/plot.html#module-vispy.plot),但似乎目前缺少像mplot3d这样的高级API。 - jcgiret
我在研究这个问题时遇到了VisPy。然而,除了还没有高级API之外,他们目前也没有在导出矢量图形方面进行工作。我很惊讶Python中没有像TikZ这样的包。一个灵活、全面的3D绘图包,可以生成出版质量(矢量图形)的3D图,比mplot3D提供的更多,将会非常有用。TikZ很强大,但受限制。 - Quantum
基本上,您有两个限制条件:1-能够导出矢量图形和2-使用z缓冲区来组合多个形状。如果我没错的话,将这些限制条件清楚地放在您的问题顶部会很有趣。此外,如果您添加一个使用TikZ期望在Python中获得的示例,那就更好了。这将设定一个目标。我将尽可能详细地回答您的问题。但是,如果我们坚持使用Python,似乎要么我们坚持使用mplot3d(但没有z缓冲区),要么我们必须切换到真正的3D渲染,但使用光栅导出。 - jcgiret
1
我已根据您的建议编辑了我的答案。我还添加了一个链接到我在tex.stackexchange上发布的问题,它给出了我想要仅使用Python实现的目标的想法。 - Quantum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接