Reputation: 123
How to draw a curved arrow in 3d, please? I mean something similar to the case in 2d:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
fig, ax = plt.subplots()
plt.rcParams["figure.figsize"] = [10, 3]
plt.xlim(-50,150)
plt.ylim(-60,165)
style="Simple,tail_width=0.5,head_width=4,head_length=8"
kw = dict(arrowstyle=style)
a3 = patches.FancyArrowPatch((0, 0), (99, 100),connectionstyle="arc3,rad=-0.3", **kw)
for a in [a3]:
plt.gca().add_patch(a)
plt.show()
Upvotes: 3
Views: 1769
Reputation: 29982
You need to extend FancyArrowPatch. The idea is to intercept the 3D coordinates parameters. Other parameters are directly passed to the FancyArrowPatch artist.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import FancyArrowPatch
fig = plt.figure()
ax1 = fig.add_subplot(121)
ax1.set_xlim(-50,150)
ax1.set_ylim(-60,165)
style="Simple,tail_width=0.5,head_width=4,head_length=8"
kw = dict(arrowstyle=style)
a1 = FancyArrowPatch((0, 0), (99, 100),connectionstyle="arc3,rad=-0.3", **kw)
ax1.add_patch(a1)
from mpl_toolkits.mplot3d import proj3d
class Arrow3D(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, renderer.M)
self.set_positions((xs[0], ys[0]), (xs[1], ys[1]))
FancyArrowPatch.draw(self, renderer)
ax2 = fig.add_subplot(122, projection="3d")
a2 = Arrow3D([0, 1], [0, 1], [0, 1], mutation_scale=20,
lw=1, arrowstyle="-|>", color="k", connectionstyle="arc3,rad=-0.3")
ax2.add_artist(a2)
plt.show()
xs[0], ys[0], zs[0]
is the starting point coordinates, xs[1], ys[1], zs[1]
is the ending point coordinates.
Reference:
Plotting a 3d cube, a sphere and a vector in Matplotlib
Upvotes: 4