python - 使用 Matplotlib 绘制 3D 绘图

标签 python matplotlib mplot3d contourf

我只是想在 3D 中绘制一个表面及其轮廓,与 this 中的完全一样。例子。

这是我用来执行此操作的代码:

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
from matplotlib import cm
import numpy

def plot_3d_contour(x_dim, y_dim, x_steps, y_steps, scalar_field, file_path):
    fig = plt.figure()

    x, y = numpy.mgrid[-x_dim/2:x_dim/2:x_steps*1j, -y_dim/2:y_dim/2:y_steps*1j]
    v_min = numpy.min(scalar_field)
    v_max = nupmy.max(scalar_field)

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

    cset = ax.contourf(x, y, scalar_field, zdir='z', offset=v_min, cmap=cm.coolwarm)
    cset = ax.contourf(x, y, scalar_field, zdir='x', offset=-x_dim/2-1, cmap=cm.coolwarm)
    cset = ax.contourf(x, y, scalar_field, zdir='y', offset=y_dim/2+1, cmap=cm.coolwarm)

    ax.plot_surface(x, y, scalar_field, rstride=10, cstride=10, alpha=0.3)

    ax.set_xlabel('X')
    ax.set_xlim(-x_dim/2-1, x_dim/2+1)
    ax.set_ylabel('Y')
    ax.set_ylim(-y_dim/2-1, y_dim/2+1)
    ax.set_zlabel('Z')
    ax.set_zlim(v_min, v_max)

    plt.savefig(file_path + '.jpg')
    plt.close()

scalar_field = numpy.loadtxt('../scalar_field', delimiter=",")
plot_3d_contour(12, 12, 100, 100, scalar_field, 'scalar_field3D')

但是,我遇到了一个奇怪的行为,其中 a 轮廓 (zdir=y) 在表面上。此外,我在 z_dir=z 中得到了一个奇怪的轮廓(缺少一个部分):

enter image description here

我想知道我错过了什么。标量场可以找到here .

最佳答案

我同意阿让的观点。我相信问题的出现是因为每个 matplotlib 的艺术家(即 PolygonCollection)都是单独渲染的。在场景中另一个对象的不同面上,无法将来自同一对象的不同面渲染。

这是一段有用的代码:

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

file_path = "./3D_surface_and_contour.jpg"
p = 0.05
f = -0.01

def get_data(p):
    x, y, z = axes3d.get_test_data(p)
    z = f * z
    return x, y, z

def plot_3d_contour(p, f):
    nrows = 4
    ncols = 5

    x, y, z = get_data(p)

    x_min, x_max = np.min(x), np.max(x)
    y_min, y_max = np.min(y), np.max(y)
    z_min, z_max = np.min(z), np.max(z)

    fig = plt.figure(figsize=(15, 10))
    for n in range(nrows * ncols):
        i = n % ncols
        j = n / ncols
        k = n + 1
        if j == 0:
            azim = -60 + (i - 2) * 15
            elev = 30
        elif j == 1:
            azim = -60
            elev = 30 + (i - 2) * 5
        elif j == 2:
            azim = 60 + (i - 2) * 10
            elev = 30
        elif j == 3:
            azim = 60
            elev = 30 + (i - 2) * 5
        ax = fig.add_subplot(nrows, ncols, k, projection='3d')
        ax.set_title("azim=" + str(azim) + " elev=" + str(elev))
        ax.tick_params(labelsize=8)
        ax.view_init(azim=azim, elev=elev)
        ax.plot_surface(x, y, z, rstride=10, cstride=10, alpha=0.3)
        ax.contourf(x, y, z, zdir='z', offset=z_min, cmap=cm.coolwarm)
        ax.contourf(x, y, z, zdir='x', offset=x_min, cmap=cm.coolwarm)
        if j == 0 or j == 1:
            ax.contourf(x, y, z, zdir='y', offset=y_max, cmap=cm.coolwarm)
        elif j == 2 or j == 3:
            ax.contourf(x, y, z, zdir='y', offset=y_min, cmap=cm.coolwarm)

        ax.set_xlabel('X')
        ax.set_xlim(x_min, x_max)
        ax.set_ylabel('Y')
        ax.set_ylim(y_min, y_max)
        ax.set_zlabel('Z')
        ax.set_zlim(z_min, z_max)

    plt.savefig(file_path, dpi=80)
    plt.close()

plot_3d_contour(p, f)

它给出了以下图像:

enter image description here

前两行由与您的代码类似的代码生成。您可能会注意到使用 view_init 将海拔设置为更高的值可以解决问题。但这并不令人满意。我还确定了 z 值范围的影响(此处未显示),该错误似乎仅在此范围较小时出现(您可以使用 f 参数对其进行测试)解释为什么 example不会受苦。

我建议的解决方案是替换:

ax.contourf(x, y, scalar_field, zdir='y', offset=y_dim/2+1, cmap=cm.coolwarm)

作者:

ax.contourf(x, y, scalar_field, zdir='y', offset=-y_dim/2-1, cmap=cm.coolwarm)

在您的代码中并添加此附加行:

ax.view_init(azim=60, elev=30)

如上图最后两行所示,这样你就可以避免matplotlib的奇思妙想了。

关于python - 使用 Matplotlib 绘制 3D 绘图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27567001/

相关文章:

python - matplotlib 中矩形数组的曲面图

python - 如何提取给定文件中带有 header 和序列的特定 fasta 文件?

python - 如何绘制具有可缩放半径的圆?

python - CSV 数据(时间戳和事件)的时间序列图 : x-label constant

python - pyplot散点图标记大小

python - 来自带有 matplotlib 的数组的 3D 曲线的线条颜色

python - 降低 Matplotlib 中子图的高度

python - 使用 pandas 或 seaborn 通过条形图制作回归线

python - 如何在命令行中接受多个参数并正确处理它?

python - pandas回填并填充不同的值