| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
@patquem Can u give some insight s on how to solve this issue
Adding Arrow3D class in mplot3d, this should be easy :) .
Solving the arrow head problem during visualization, I have no idea how to fix that. Sorry :( .
Hello @soma2000-lang
introducing the penultimate line in the code (if not....) avoids a warning message and drawing the wrong arrowhead as mentioned above. Not sure if this is the right way to fix the bug, but temporarily it might be a solution.
Patrick
class Arrow3D(FancyArrowPatch):
""" Create fancy arrow (artist) for 3d matplotlib visualisation """
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
xarr, yarr, _ = proj3d.proj_transform(xs3d, ys3d, zs3d, self.axes.M)
self.set_positions((xarr[0], yarr[0]), (xarr[1], yarr[1]))
if not (np.allclose(xarr, 0.) and np.allclose(yarr, 0.)):
FancyArrowPatch.draw(self, renderer)
Hi, is anyone working on this ? I know you don't assign issues but I would like to try it !
I believe that maybe @soma2000-lang is not actively working on this, so please give it a go!
I have labeled this a a good first issue because there is ~working code for the implementation, but medium because it involves (limited) API design.
This will need:
This is a good project for someone with library design experience but who is new to Matplotlib.
So I'm just gonna throw out this sketch because the signature is closer to FancyArrowPatch
class FancyArrowPatch3D(mpatches.FancyArrowPatch):
def __init__(self, posA, posB, *args, **kwargs):
mpatches.FancyArrowPatch.__init__(self, (0, 0), (0, 0), *args, **kwargs)
self._verts3d = list(zip(posA, posB))Here is a function based on the solution from @tacaswell which takes an array of arrow start points and endpoints. Additionally, it sets the axes limits so that all start/end points remain visible.
def arrows3d(ends, starts=None, ax=None, label=None, **kwargs):
"""3D plot of multiple arrows
Args:
ends (ndarray): (N, 3) size array of arrow end coordinates
starts (ndarray): (N, 3) size array of arrow start coordinates.
Assume start position of (0, 0, 0) if not given
ax (Axes3DSubplot): existing axes to add to
label (str): legend label to apply to this group of arrows
kwargs (dict): additional arrow properties
"""
if starts is None:
starts = np.zeros_like(ends)
assert starts.shape == ends.shape, "`starts` and `ends` shape must match"
assert len(ends.shape) == 2 and ends.shape[1] == 3, \
"`starts` and `ends` must be shape (N, 3)"
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)
# create new axes if none given
if ax is None:
ax = plt.figure().add_subplot(111, projection='3d')
arrow_prop_dict = dict(mutation_scale=20, arrowstyle='-|>', color='k', shrinkA=0, shrinkB=0)
arrow_prop_dict.update(kwargs)
for ind, (s, e) in enumerate(np.stack((starts, ends), axis=1)):
a = Arrow3D(
[s[0], e[0]], [s[1], e[1]], [s[2], e[2]],
# only give label to first arrow
label=label if ind == 0 else None,
**arrow_prop_dict
)
ax.add_artist(a)
# store starts/ends on the axes for setting the limits
ax.points = np.vstack((starts, ends, getattr(ax, 'points', np.empty((0, 3)))))
ax.set_xlim3d(ax.points[:, 0].min(),ax.points[:, 0].max())
ax.set_ylim3d(ax.points[:, 1].min(),ax.points[:, 1].max())
ax.set_zlim3d(ax.points[:, 2].min(),ax.points[:, 2].max())
return axax = arrows3d(np.random.normal(size=(5, 3)), label='Foo')
ax = arrows3d(np.random.normal(size=(5, 3)), ax=ax, color='r',label='Bar')
plt.legend()
plt.show()heyy @patquem looking to the issue , seems like it can be done.
Let me work on this issue and fix it.
@ShubhamPatel-16 this issue can't be moved forward until decisions are made in #22435 b/c this API should match that one as much as possible.
Removing the good first issue label for now b/c this isn't ready for work yet.
| Back | FazBrowse Home | New Git URL |
Problem
Hello,
FancyArrow can not be used in 3D.
Some proposals (#21688) consists in creating a new class.
Could it be possible:
Thanks,
Patrick
import numpy as np import matplotlib.pyplot as plt from matplotlib.patches import FancyArrowPatch, FancyArrow from mpl_toolkits.mplot3d import proj3d class Arrow3D(FancyArrowPatch): """ Create fancy arrow (artist) for 3d matplotlib visualisation """ 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 xarr, yarr, _ = proj3d.proj_transform(xs3d, ys3d, zs3d, self.axes.M) self.set_positions((xarr[0], yarr[0]), (xarr[1], yarr[1])) FancyArrowPatch.draw(self, renderer) fig, ax = plt.subplots(1, 2, figsize=(12, 5), subplot_kw=dict(projection="3d", proj_type='ortho')) ax[0].voxels(np.ones((1, 1, 1)), facecolors=[0, 0, 0, 0], edgecolors='k') # ax[0].add_artist(FancyArrow(0, 0, 0, 1, 1, 1)) ax[0].add_artist(Arrow3D((0, 1), (0, 1), (0, 1), mutation_scale=50)) ax[1].voxels(np.ones((1, 1, 1)), facecolors=[0, 0, 0, 0], edgecolors='k') ax[1].view_init(elev=28, azim=45) # ax[1].add_artist(FancyArrow(0, 0, 0, 1, 1, 1))) ax[1].add_artist(Arrow3D((0, 1), (0, 1), (0, 1), mutation_scale=50)) plt.show()Proposed solution
No response