admin管理员组文章数量:1323023
The purpose of the code is to use arrow3D to initiate X, Y, Z axis on a 3D plane. The parameters of arrow3D are x, y, z, which default to zero; and dx, dy, dz, which is the length of X, Y, Z axis. That way, I could setup my window on 3D plane. So in the code below, arrow3D inherits FancyArrowPatch and has its attributes _xyz and _dxdydz.
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.proj3d import proj_transform
from mpl_toolkits.mplot3d.axes3d import Axes3D
from matplotlib.text import Annotation
from matplotlib.patches import FancyArrowPatch
# X axis, Y axis, and Z axis should be added into axes like other artists
# class Arrow3D is created for them
# Arrow3D inherits FancyArrowPatch, since those axes are like arrows
class Arrow3D(FancyArrowPatch):
def __init__(self, x, y, z, dx, dy, dz, *args, **kwargs):
super().__init__((0,0), (0,0), *args, **kwargs)
self._xyz = (x,y,z)
self._dxdydz = (dx,dy,dz)
def draw(self, renderer):
x1,y1,z1 = self._xyz
dx,dy,dz = self._dxdydz
x2,y2,z2 = (x1+dx,y1+dy,z1+dz)
xs, ys, zs = proj_transform((x1,x2),(y1,y2),(z1,z2), renderer.M)
self.set_positions((xs[0],ys[0]),(xs[1],ys[1]))
super().draw(renderer)
def _arrow3D(ax, x, y, z, dx, dy, dz, *args, **kwargs):
'''Add an 3d arrow to an `Axes3D` instance.'''
arrow = Arrow3D(x, y, z, dx, dy, dz, *args, **kwargs)
ax.add_artist(arrow)
# an object of class Axes3D will have an attribute-'arrow3D', which is the function _arrow3D
# this object could be axes, when it is created by passing the projection='3d' keyword argument to Figure.add_subplot
setattr(Axes3D,'arrow3D',_arrow3D)
# an object of class Axes3D will have an attribute-'arrow3D', which is the function _arrow3D
# this object could be axes, when it is created by passing the projection='3d' keyword argument to Figure.add_subplot
setattr(Axes3D,'arrow3D',_arrow3D)
class Annotation3D(Annotation):
def __init__(self, text, xyz, *args, **kwargs):
super().__init__(text, xy=(0,0), *args, **kwargs)
self._xyz = xyz
def draw(self, renderer):
x2, y2, z2 = proj_transform(*self._xyz, renderer.M)
self.xy=(x2,y2)
super().draw(renderer)
def _annotate3D(ax,text, xyz, *args, **kwargs):
'''Add anotation `text` to an `Axes3d` instance.'''
annotation= Annotation3D(text, xyz, *args, **kwargs)
ax.add_artist(annotation)
setattr(Axes3D,'annotate3D',_annotate3D)
With arrow3D defined, I then define the _axesSetup so that my 3D background could be set.
import arrow3d
from mpl_toolkits.mplot3d.axes3d import Axes3D
from matplotlib.text import Annotation
from matplotlib.patches import FancyArrowPatch
import numpy as np
def _axesSetup(ax, lX, uX, lY, uY, lZ, uZ):
# set xlimit, draw x axis, annotate x axis
# x axis
ax.set_xlim(lX, uX)
ax.arrow3D(lX, 0, 0, uX - lX, 0, 0, mutation_scale=15, arrowstyle="-|>", color='red')
ax.annotate3D('X', (uX, 0, 0), xytext=(0, 0), textcoords=('offset points'), color = 'xkcd:eggplant', weight="bold")
# y axis
ax.set_ylim(lY, uY)
ax.arrow3D(0, lY, 0, 0, uY - lY, 0, mutation_scale=15, arrowstyle="-|>", color='red')
ax.annotate3D('Y', (0, uY, 0), xytext=(0, 0), textcoords=('offset points'), color = 'xkcd:eggplant', weight="bold")
# z axis
ax.set_zlim(lZ, uZ)
ax.arrow3D(0, 0, lZ, 0, 0, uZ - lZ, mutation_scale=15, arrowstyle="-|>", color='red')
ax.annotate3D('Z', (0, 0, uZ), xytext=(0, 0), textcoords=('offset points'), color = 'xkcd:eggplant', weight="bold")
setattr(Axes3D, 'axesSetup', _axesSetup )
# setattr create 'axesSetup' attribute for class Axes3D if 'axesSetup' is not found
# an object of class Axes3D is the axes projected in 3D
It used to work, but now it shows nothing. Some other post already figured out it's due to Matplotlib's upgrade. Could someone help me to modify my code to make it work?
本文标签:
版权声明:本文标题:python - 'Arrow3D' object has no attribute 'do_3d_projection'; set up X, Y, Z axis on 3D plane - 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736137409a1907166.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论