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

Skip to content

Commit 893c34e

Browse files
committed
Implement arrows3d method in Axes3D
1 parent 553cec1 commit 893c34e

File tree

6 files changed

+135
-1
lines changed

6 files changed

+135
-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, xs, ys, zs, *args, **kwargs):
1675+
"""
1676+
Parameters
1677+
----------
1678+
xs, ys, zs : array-like
1679+
The x, y, and z coordinates of the arrow's start and end points.
1680+
"""
1681+
super().__init__((0,0), (0,0), *args, **kwargs)
1682+
self._verts3d = xs, ys, zs
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: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4057,6 +4057,50 @@ 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+
**kwargs
4074+
All other keyword arguments are passed on to
4075+
`~mpl_toolkits.mplot3d.art3d.Arrow3D`.
4076+
4077+
Returns
4078+
-------
4079+
arrow : `~mpl_toolkits.mplot3d.art3d.Arrow3D`
4080+
4081+
"""
4082+
had_data = self.has_data()
4083+
4084+
if start is None:
4085+
start = np.zeros_like(end)
4086+
if np.shape(end) != (3,):
4087+
raise ValueError("end must be an array of length 3")
4088+
if np.shape(start) != (3,):
4089+
raise ValueError("start must be an array of length 3")
4090+
4091+
# Set default arrow properties and update with any additional keyword args
4092+
arrow_props = dict(
4093+
mutation_scale=20, arrowstyle="-|>", shrinkA=0, shrinkB=0
4094+
)
4095+
arrow_props.update(kwargs)
4096+
4097+
xs, ys, zs = [start[0], end[0]], [start[1], end[1]], [start[2], end[2]]
4098+
arrow = art3d.Arrow3D(xs, ys, zs, **arrow_props)
4099+
self.add_artist(arrow)
4100+
self.auto_scale_xyz(xs, ys, zs, had_data)
4101+
4102+
return arrow
4103+
40604104

40614105
def get_test_data(delta=0.05):
40624106
"""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: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2740,3 +2740,29 @@ 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+
def test_arrow3d_custom_props():
2758+
fig = plt.figure()
2759+
ax = fig.add_subplot(projection='3d')
2760+
2761+
start1 = [1, 2, 3]
2762+
end1 = [4, 5, 6]
2763+
ax.arrow3d(end1, start1,
2764+
arrowstyle="->, head_length=0.6, head_width=0.3", color='red')
2765+
2766+
start2 = [2, 5, 7]
2767+
end2 = [4, 6, -8]
2768+
ax.arrow3d(end2, start2, color='violet', ls='--', lw=2)

0 commit comments

Comments
 (0)