AttributeError: ‘Arrow3D’ object has no attribute ‘do_3d_projection’ 的修正

AttributeError: ‘Arrow3D’ object has no attribute ‘do_3d_projection’ 的修正

一、错误来源

最近在读《程序员数学:用Python学透线性代数和微积分》,其中“第三章 上升到三维世界”的主要内容是,把二维向量拓展到三维空间,并用matplotlib来作图示意。大多数的画图功能都能展示,只是在画“三维箭头”图形的时候,系统报错“AttributeError: ‘Arrow3D’ object has no attribute ‘do_3d_projection’”。有人建议,安装matplotlib3.4的版本来规避此问题,据说是3.5版本以后都会出现此问题。但是,最新的版本已经是3.7了,担心版本降低以后会影响其他的图形显示。因此,在参考了其他人的观点以后,对书中的源程序进行了部分调整,解决了这个问题,达到了和书中图形相同的效果。

二、修正方式

将源代码中“Chapter 03”下的“draw3d.py”中的FancyArrow3D类,改成如下内容:

class FancyArrow3D(FancyArrowPatch):
    # def __init__(self, xs, ys, zs, *args, **kwargs):
    #     FancyArrowPatch.__init__(self, (0, 0), (0, 0), *args, **kwargs)
    #     self._verts3d = xs, ys, zs
    def __init__(self, xs, ys, zs, *args, **kwargs):
        super().__init__((0, 0), (0, 0), *args, **kwargs)
        self._verts3d = xs, ys, zs

    def do_3d_projection(self, renderer=None):
        xs3d, ys3d, zs3d = self._verts3d
        xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, self.axes.M)
        self.set_positions((xs[0], ys[0]), (xs[1], ys[1]))
        return np.min(zs)

其中的被注释的部分,是原来的代码,后面的那个方法(method)是新增加上去的。

然后,再去修改“draw3d”函数的部分如下:

        elif type(object) == Arrow3D:
            xs, ys, zs = zip(object.tail, object.tip)
            # a = FancyArrow3D(xs, ys, zs, mutation_scale=20, arrowstyle='-|>', color=object.color)
            # ax.add_artist(a)

            arrow_prop_dict = dict(mutation_scale=20, arrowstyle='-|>', color='k', shrinkA=0, shrinkB=0)
            a = FancyArrow3D(xs, ys, zs, **arrow_prop_dict)
            ax.add_artist(a)

说明:那个“elif”语句是原来就有的,注释的部分是原来的代码,修改成下面的部分即可。

修改完毕以后,所有的调用都是不用修改的。

三、一个例子

用书中的一个练习来展示结果。

练习 3.5(小项目):下面的代码创建了一个包含 24个 Python向量的列表。把这 24个向量绘制成首尾相接的 Arrow3D 对象。

from math import sin, cos, pi
vs = [(sin(pi*t/6), cos(pi*t/6), 1.0/3) for t in range(0,24)]

running_sum = (0,0,0) 
arrows = []
for v in vs:
    next_sum = add(running_sum, v) 
    arrows.append(Arrow3D(next_sum, running_sum)) 
    running_sum = next_sum
print(running_sum)
draw3d(*arrows)

执行结果是:

(-4.440892098500626e-16, -7.771561172376096e-16, 7.9999999999999964)

AttributeError: ‘Arrow3D’ object has no attribute ‘do_3d_projection’ 的修正_第1张图片

图像显示结果和书中的效果一致。至此,这个错误修改完成。

你可能感兴趣的:(python)