3D 绘图纵横比 [matplotlib] [英] 3D plot aspect ratio [matplotlib]

查看:73
本文介绍了3D 绘图纵横比 [matplotlib]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用

解决方案

看起来没有正确"的方法可以做到这一点,但我们可以尝试通过猴子修补解决问题的方法.这是我能做的最好的混搭:

from mpl_toolkits.mplot3d import proj3ddef make_get_proj(self, rx, ry, rz):'''返回 :func:`~mpl_toolkit.mplot2d.axes3d.Axes3D.getproj` 的变体使用轴对象 *self* 使框长宽比等于 *rx:ry:rz*.'''rm = 最大值(rx,ry,rz)kx = rm/rx;ky = rm/ry;kz = rm/rz;# 直接从mpl_toolkit/mplot3d/axes3d.py复制.新的或修改的行是#由##标记def get_proj():相关,razim = np.pi * self.elev/180,np.pi * self.azim/180xmin, xmax = self.get_xlim3d()ymin, ymax = self.get_ylim3d()zmin, zmax = self.get_zlim3d()# 转换为统一的世界坐标 0-1.0,0-1.0,0-1.0worldM = proj3d.world_transformation(xmin, xmax,ymin, ymax,zmin, zmax)#调整纵横比##aspectM = proj3d.world_transformation(-kx + 1, kx, ##-ky + 1, ky, ##-kz + 1, kz) ### 查看新坐标的中间位置R = np.array([0.5, 0.5, 0.5])xp = R[0] + np.cos(razim) * np.cos(relev) * self.distyp = R[1] + np.sin(razim) * np.cos(relev) * self.distzp = R[2] + np.sin(relev) * self.distE = np.array((xp, yp, zp))self.eye = Eself.vvec = R - Eself.vvec = self.vvec/proj3d.mod(self.vvec)如果 abs(relev) >np.pi/2:# 倒挂V = np.array((0, 0, -1))别的:V = np.array((0, 0, 1))zfront, zback = -self.dist, self.distviewM = proj3d.view_transformation(E, R, V)perspM = proj3d.persp_transformation(zfront, zback)M0 = np.dot(viewM, np.dot(aspectM, worldM)) ##M = np.dot(perspM, M0)返回 M返回 get_proj# 以及后面的代码:ax.get_proj = make_get_proj(ax, 1, 1, 2)ax.set_aspect(1.0)

I am using the code written here to make a plot like this one below.

The problem is, that I want to adjust an aspect ratio, namely, to stretch it along the z-axis, so that all the stacked images are more or less visible. Is there an easy way of doing that?

解决方案

Looks like there is no "proper" way to do it, but we can try monkey-patching our way around the problem. Here’s the best kludge I could do:

from mpl_toolkits.mplot3d import proj3d

def make_get_proj(self, rx, ry, rz):
    '''
    Return a variation on :func:`~mpl_toolkit.mplot2d.axes3d.Axes3D.getproj` that
    makes the box aspect ratio equal to *rx:ry:rz*, using an axes object *self*.
    '''

    rm = max(rx, ry, rz)
    kx = rm / rx; ky = rm / ry; kz = rm / rz;

    # Copied directly from mpl_toolkit/mplot3d/axes3d.py. New or modified lines are
    # marked by ##
    def get_proj():
        relev, razim = np.pi * self.elev/180, np.pi * self.azim/180

        xmin, xmax = self.get_xlim3d()
        ymin, ymax = self.get_ylim3d()
        zmin, zmax = self.get_zlim3d()

        # transform to uniform world coordinates 0-1.0,0-1.0,0-1.0
        worldM = proj3d.world_transformation(xmin, xmax,
                                             ymin, ymax,
                                             zmin, zmax)

        # adjust the aspect ratio                          ##
        aspectM = proj3d.world_transformation(-kx + 1, kx, ##
                                              -ky + 1, ky, ##
                                              -kz + 1, kz) ##

        # look into the middle of the new coordinates
        R = np.array([0.5, 0.5, 0.5])

        xp = R[0] + np.cos(razim) * np.cos(relev) * self.dist
        yp = R[1] + np.sin(razim) * np.cos(relev) * self.dist
        zp = R[2] + np.sin(relev) * self.dist
        E = np.array((xp, yp, zp))

        self.eye = E
        self.vvec = R - E
        self.vvec = self.vvec / proj3d.mod(self.vvec)

        if abs(relev) > np.pi/2:
            # upside down
            V = np.array((0, 0, -1))
        else:
            V = np.array((0, 0, 1))
        zfront, zback = -self.dist, self.dist

        viewM = proj3d.view_transformation(E, R, V)
        perspM = proj3d.persp_transformation(zfront, zback)
        M0 = np.dot(viewM, np.dot(aspectM, worldM)) ##
        M = np.dot(perspM, M0)
        return M
    return get_proj

# and later in the code:
ax.get_proj = make_get_proj(ax, 1, 1, 2)
ax.set_aspect(1.0)

这篇关于3D 绘图纵横比 [matplotlib]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆