【问题标题】:How to obtain 3D colored surface via Python?如何通过 Python 获得 3D 彩色表面?
【发布时间】:2014-07-23 11:27:51
【问题描述】:

如何通过 Matplotlib 获取下面的曲面?

在matlab中很容易通过:

mesh(peaks)

似乎 matplotlib 在 matlab 中没有 mesh 的精确对应物。 Wireframe plots 没有任何 colormap 选项

【问题讨论】:

  • 它们都不起作用。我需要在meshwireframe 上应用完全相同的colormap
  • 您需要mesh 还是surface 就足够了?
  • mesh 不是surface;曲面图可以通过 matplotlib 轻松实现

标签: matlab python-2.7 matplotlib surface colormap


【解决方案1】:

在回答another question 时,我发现您可以轻松地使用plot_surface 生成颜色映射表面,然后交换面和边缘颜色:

surf = ax.plot_surface(X, Y, Z, rstride=2, cstride=2, shade=False, cmap="jet", linewidth=1)
draw()
surf.set_edgecolors(surf.to_rgba(surf._A))
surf.set_facecolors("white")
show()

生产

与另一种解决方案相比,此解决方案的缺点是边缘没有平滑的逐像素着色,而是每个边缘只有一种颜色。

【讨论】:

  • 这在 1.5.1 中似乎不再起作用了。这样做:surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, shade=False, cmap=mpl.colors.ListedColormap(['white']))m = plt.cm.ScalarMappable(surf.norm)surf.set_edgecolors(m.to_rgba(surf.get_array()))
  • @wilywampa 谢谢。你的修复对我不起作用;但是this question 提示我将linewidth 关键字添加到plot_surface 调用中,这确实可以解决问题。
  • 如果不希望在表面后面隐藏线,可以使用surf.set_facecolor([0]*4)而不是'white'
【解决方案2】:

matplotlib 似乎是可能的,即使它有点 hack:

from mpl_toolkits.mplot3d import axes3d
from mpl_toolkits.mplot3d import art3d
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
X, Y, Z = axes3d.get_test_data(0.05)
wire = ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)

# Retrive data from internal storage of plot_wireframe, then delete it
nx, ny, _  = np.shape(wire._segments3d)
wire_x = np.array(wire._segments3d)[:, :, 0].ravel()
wire_y = np.array(wire._segments3d)[:, :, 1].ravel()
wire_z = np.array(wire._segments3d)[:, :, 2].ravel()
wire.remove()

# create data for a LineCollection
wire_x1 = np.vstack([wire_x, np.roll(wire_x, 1)])
wire_y1 = np.vstack([wire_y, np.roll(wire_y, 1)])
wire_z1 = np.vstack([wire_z, np.roll(wire_z, 1)])
to_delete = np.arange(0, nx*ny, ny)
wire_x1 = np.delete(wire_x1, to_delete, axis=1)
wire_y1 = np.delete(wire_y1, to_delete, axis=1)
wire_z1 = np.delete(wire_z1, to_delete, axis=1)
scalars = np.delete(wire_z, to_delete)

segs = [list(zip(xl, yl, zl)) for xl, yl, zl in \
                 zip(wire_x1.T, wire_y1.T, wire_z1.T)]

# Plots the wireframe by a  a line3DCollection
my_wire = art3d.Line3DCollection(segs, cmap="hsv")
my_wire.set_array(scalars)
ax.add_collection(my_wire)

plt.colorbar(my_wire)
plt.show()

【讨论】:

    【解决方案3】:

    官方功能请求正在进行中:

    https://github.com/matplotlib/matplotlib/issues/3562

    当 X 和 Y 数组大小不同时,可接受的解决方案不起作用。

    【讨论】:

      【解决方案4】:

      目前的matplotlib 1.3.1 似乎无法处理此类mesh 绘图或进一步的PDF 导出。在 matplotlib 进一步更新之前,gnuplot.pygnuplot.py 1.8 可能是一个选择。

      这是一个通过 gnuplot 创建的示例:

      MayaVI2 不支持 PDF 导出,但可能是另一个不错的选择。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-28
        • 2011-12-16
        • 1970-01-01
        • 1970-01-01
        • 2011-01-18
        相关资源
        最近更新 更多