Open cheradenine opened 3 years ago
this is probably due to versions of matplotlib. I was able to get up and running with the anaconda docker image.
Define do_3d_projection
method to avoid this exception.
Example solution is here. https://github.com/matplotlib/matplotlib/issues/21688#issuecomment-974912574
Define
do_3d_projection
method to avoid this exception.Example solution is here. matplotlib/matplotlib#21688 (comment)
I defined this one in class FancyArrow3D(), however, it still doesn't work.
Define
do_3d_projection
method to avoid this exception.Example solution is here. matplotlib/matplotlib#21688 (comment)
This worked after I restarted the kernel (using VS Code), thanks
Define
do_3d_projection
method to avoid this exception.Example solution is here. matplotlib/matplotlib#21688 (comment)
Follow this answer, it works in matplotlib 3.5.2
I had to tweak FancyArrow3d
to make it work:
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 draw(self, renderer):
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]))
FancyArrowPatch.draw(self, renderer)
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)
Define
do_3d_projection
method to avoid this exception.Example solution is here. matplotlib/matplotlib#21688 (comment)
I checked the code above the link but it still doesn't work, Can you tell me how to copy the code in the link into file(draw3d.py)?
I can't get it working either, tried all solutions posted thus far
WAIT, I got it working. @yebywoo - make sure to save file, restart kernel
Post this in your draw3d.py
from math import sqrt, pi
import matplotlib
import os
from matplotlib.patches import Polygon
from matplotlib.collections import PatchCollection
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from colors import *
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.patches import FancyArrowPatch
from mpl_toolkits.mplot3d import proj3d
class Arrow3D(FancyArrowPatch):
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)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
arrow_prop_dict = dict(mutation_scale=20, arrowstyle='-|>', color='k', shrinkA=0, shrinkB=0)
a = Arrow3D([0, 10], [0, 0], [0, 0], **arrow_prop_dict)
ax.add_artist(a)
plt.show()
## https://stackoverflow.com/a/22867877/1704140
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 draw(self, renderer):
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]))
FancyArrowPatch.draw(self, renderer)
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)
class Polygon3D():
def __init__(self, *vertices, color=blue):
self.vertices = vertices
self.color = color
class Points3D():
def __init__(self, *vectors, color=black):
self.vectors = list(vectors)
self.color = color
class Arrow3D():
def __init__(self, tip, tail=(0,0,0), color=red):
self.tip = tip
self.tail = tail
self.color = color
class Segment3D():
def __init__(self, start_point, end_point, color=blue, linestyle='solid'):
self.start_point = start_point
self.end_point = end_point
self.color = color
self.linestyle = linestyle
class Box3D():
def __init__(self, *vector):
self.vector = vector
# helper function to extract all the vectors from a list of objects
def extract_vectors_3D(objects):
for object in objects:
if type(object) == Polygon3D:
for v in object.vertices:
yield v
elif type(object) == Points3D:
for v in object.vectors:
yield v
elif type(object) == Arrow3D:
yield object.tip
yield object.tail
elif type(object) == Segment3D:
yield object.start_point
yield object.end_point
elif type(object) == Box3D:
yield object.vector
else:
raise TypeError("Unrecognized object: {}".format(object))
def draw3d(*objects, origin=True, axes=True, width=6, save_as=None, azim=None, elev=None, xlim=None, ylim=None, zlim=None, xticks=None, yticks=None, zticks=None,depthshade=False):
fig = plt.gcf()
ax = fig.add_subplot(111, projection='3d')
ax.view_init(elev=elev,azim=azim)
all_vectors = list(extract_vectors_3D(objects))
if origin:
all_vectors.append((0,0,0))
xs, ys, zs = zip(*all_vectors)
max_x, min_x = max(0,*xs), min(0,*xs)
max_y, min_y = max(0,*ys), min(0,*ys)
max_z, min_z = max(0,*zs), min(0,*zs)
x_size = max_x-min_x
y_size = max_y-min_y
z_size = max_z-min_z
padding_x = 0.05 * x_size if x_size else 1
padding_y = 0.05 * y_size if y_size else 1
padding_z = 0.05 * z_size if z_size else 1
plot_x_range = (min(min_x - padding_x,-2), max(max_x + padding_x,2))
plot_y_range = (min(min_y - padding_y,-2), max(max_y + padding_y,2))
plot_z_range = (min(min_z - padding_z,-2), max(max_z + padding_z,2))
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
def draw_segment(start, end, color=black, linestyle='solid'):
xs, ys, zs = [[start[i],end[i]] for i in range(0,3)]
ax.plot(xs, ys, zs, color=color, linestyle=linestyle)
if axes:
draw_segment((plot_x_range[0],0,0), (plot_x_range[1],0,0))
draw_segment((0,plot_y_range[0],0), (0,plot_y_range[1],0))
draw_segment((0,0,plot_z_range[0]), (0,0,plot_z_range[1]))
if origin:
ax.scatter([0],[0],[0], color='k', marker='x')
for object in objects:
if type(object) == Points3D:
xs, ys, zs = zip(*object.vectors)
ax.scatter(xs,ys,zs,color=object.color,depthshade=depthshade)
elif type(object) == Polygon3D:
for i in range(0,len(object.vertices)):
draw_segment(
object.vertices[i],
object.vertices[(i+1)%len(object.vertices)],
color=object.color)
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)
elif type(object) == Segment3D:
draw_segment(object.start_point, object.end_point, color=object.color, linestyle=object.linestyle)
elif type(object) == Box3D:
x,y,z = object.vector
kwargs = {'linestyle':'dashed', 'color':'gray'}
draw_segment((0,y,0),(x,y,0),**kwargs)
draw_segment((0,0,z),(0,y,z),**kwargs)
draw_segment((0,0,z),(x,0,z),**kwargs)
draw_segment((0,y,0),(0,y,z),**kwargs)
draw_segment((x,0,0),(x,y,0),**kwargs)
draw_segment((x,0,0),(x,0,z),**kwargs)
draw_segment((0,y,z),(x,y,z),**kwargs)
draw_segment((x,0,z),(x,y,z),**kwargs)
draw_segment((x,y,0),(x,y,z),**kwargs)
else:
raise TypeError("Unrecognized object: {}".format(object))
if xlim and ylim and zlim:
plt.xlim(*xlim)
plt.ylim(*ylim)
ax.set_zlim(*zlim)
if xticks and yticks and zticks:
plt.xticks(xticks)
plt.yticks(yticks)
ax.set_zticks(zticks)
if save_as:
plt.savefig(save_as)
plt.show()
I am unable to run through the examples in the Jupyter notebook file for chapter 3.
Showing the top of the callstack