Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ba9dcd7

Browse files
committed
Implement arrow3d method in Axes3D
1 parent 553cec1 commit ba9dcd7

File tree

6 files changed

+139
-1
lines changed

6 files changed

+139
-1
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
New ``arrow3d`` Method
2+
----------------------
3+
4+
The new ``arrow3d`` method for `~.Axes3D` allows users to plot 3D arrows,
5+
which can be used for representing vectors or directional data.

galleries/examples/mplot3d/arrow3d.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""
2+
=============
3+
3D arrow plot
4+
=============
5+
6+
Demonstrates plotting arrows in a 3D space.
7+
8+
Here we plot two arrows from the same start point to different
9+
end points. The properties of the second arrow is changed by passing
10+
additional parameters other than ``end`` and ``start`` to
11+
`.patches.FancyArrowPatch`.
12+
"""
13+
14+
import matplotlib.pyplot as plt
15+
import numpy as np
16+
17+
fig = plt.figure()
18+
ax = fig.add_subplot(111, projection='3d')
19+
20+
# Define the start and end points of the arrow
21+
start = np.array([0, 0, 0])
22+
end = np.array([1, 1, 1])
23+
24+
# Create the arrow
25+
ax.arrow3d(end, start)
26+
27+
end1 = np.array([1, 2, 3])
28+
# Passing additional keyword arguments to control properties of the arrow.
29+
# If the `start` parameter is not passed, the arrow is drawn from (0, 0, 0).
30+
ax.arrow3d(end1, mutation_scale=20, color='r', arrowstyle='->', linewidth=2)
31+
32+
plt.show()
33+
34+
# %%
35+
# .. tags::
36+
# plot-type: 3D,
37+
# level: beginner

lib/mpl_toolkits/mplot3d/art3d.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
path as mpath, rcParams)
1919
from matplotlib.collections import (
2020
Collection, LineCollection, PolyCollection, PatchCollection, PathCollection)
21-
from matplotlib.patches import Patch
21+
from matplotlib.patches import Patch, FancyArrowPatch
2222
from . import proj3d
2323

2424

@@ -1665,3 +1665,25 @@ def norm(x):
16651665
colors = np.asanyarray(color).copy()
16661666

16671667
return colors
1668+
1669+
1670+
class Arrow3D(FancyArrowPatch):
1671+
"""
1672+
3D FancyArrowPatch object.
1673+
"""
1674+
def __init__(self, posA, posB, *args, **kwargs):
1675+
"""
1676+
Parameters
1677+
----------
1678+
posA, posB : array-like
1679+
The coordinates of the arrow's start and end points.
1680+
"""
1681+
super().__init__((0,0), (0,0), *args, **kwargs)
1682+
self._verts3d = list(zip(posA, posB))
1683+
1684+
def do_3d_projection(self, renderer=None):
1685+
"""Projects the points according to the renderer matrix."""
1686+
xs3d, ys3d, zs3d = self._verts3d
1687+
xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, self.axes.M)
1688+
self.set_positions((xs[0], ys[0]), (xs[1], ys[1]))
1689+
return np.min(zs)

lib/mpl_toolkits/mplot3d/axes3d.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4057,6 +4057,53 @@ def stem(self, x, y, z, *, linefmt='C0-', markerfmt='C0o', basefmt='C3-',
40574057

40584058
stem3D = stem
40594059

4060+
@_preprocess_data()
4061+
def arrow3d(self, end, start=None, **kwargs):
4062+
"""
4063+
3D plot of a single arrow
4064+
4065+
Parameters
4066+
----------
4067+
end : 1D array
4068+
an array of shape (3,).
4069+
4070+
start : 1D array, default: (0,0,0)
4071+
an array of shape (3,).
4072+
4073+
data : indexable object, optional
4074+
DATA_PARAMETER_PLACEHOLDER
4075+
4076+
**kwargs
4077+
All other keyword arguments are passed on to
4078+
`~mpl_toolkits.mplot3d.art3d.Arrow3D`.
4079+
4080+
Returns
4081+
-------
4082+
arrow : `~mpl_toolkits.mplot3d.art3d.Arrow3D`
4083+
4084+
"""
4085+
had_data = self.has_data()
4086+
4087+
if start is None:
4088+
start = np.zeros_like(end)
4089+
if np.shape(end) != (3,):
4090+
raise ValueError("end must be an array of length 3")
4091+
if np.shape(start) != (3,):
4092+
raise ValueError("start must be an array of length 3")
4093+
4094+
# Set default arrow properties and update with any additional keyword args
4095+
arrow_props = dict(
4096+
mutation_scale=20, arrowstyle="-|>", shrinkA=0, shrinkB=0
4097+
)
4098+
arrow_props.update(kwargs)
4099+
4100+
arrow = art3d.Arrow3D(start, end, **arrow_props)
4101+
self.add_artist(arrow)
4102+
xs, ys, zs = list(zip(start, end))
4103+
self.auto_scale_xyz(xs, ys, zs, had_data)
4104+
4105+
return arrow
4106+
40604107

40614108
def get_test_data(delta=0.05):
40624109
"""Return a tuple X, Y, Z with a test data set."""
52.6 KB
Loading

lib/mpl_toolkits/mplot3d/tests/test_axes3d.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2740,3 +2740,30 @@ def test_axes3d_set_aspect_deperecated_params():
27402740

27412741
with pytest.raises(ValueError, match="adjustable"):
27422742
ax.set_aspect('equal', adjustable='invalid_value')
2743+
2744+
2745+
@check_figures_equal()
2746+
def test_arrow3d_default(fig_test, fig_ref):
2747+
ax_ref = fig_ref.add_subplot(projection='3d')
2748+
start = [0, 0, 0]
2749+
end = [1, 2, 3]
2750+
ax_ref.arrow3d(end, start)
2751+
2752+
ax_test = fig_test.add_subplot(projection='3d')
2753+
ax_test.arrow3d(end)
2754+
2755+
2756+
@mpl3d_image_comparison(['arrow3d_custom_props.png'], style='mpl20',
2757+
tol=0.02 if sys.platform == 'darwin' else 0)
2758+
def test_arrow3d_custom_props():
2759+
fig = plt.figure()
2760+
ax = fig.add_subplot(projection='3d')
2761+
2762+
start1 = [1, 2, 3]
2763+
end1 = [4, 5, 6]
2764+
ax.arrow3d(end1, start1,
2765+
arrowstyle="->, head_length=0.6, head_width=0.3", color='red')
2766+
2767+
start2 = [2, 5, 7]
2768+
end2 = [4, 6, -8]
2769+
ax.arrow3d(end2, start2, color='violet', ls='--', lw=2)

0 commit comments

Comments
 (0)