Skip to content

Commit e1770bc

Browse files
3D plot roll angle flake8, tests, and whats new
1 parent fd8f239 commit e1770bc

File tree

6 files changed

+37
-11
lines changed

6 files changed

+37
-11
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
3D plots have now have a 3rd "roll" viewing angle
2+
-------------------------------------------------
3+
4+
3D plots can now be viewed from any orientation with the addition of a 3rd roll
5+
angle, which rotates the plot about the viewing axis. Interactive rotation
6+
using the mouse still only controls elevation and azimuth, meaning that this
7+
feature is only really relevant to users who want to create more complex camera
8+
angles programmatically. The default roll angle of 0 is backwards-compatible
9+
with existing 3D plots.
10+
11+
.. plot::
12+
:include-source: true
13+
14+
from mpl_toolkits.mplot3d import axes3d
15+
import matplotlib.pyplot as plt
16+
fig = plt.figure()
17+
ax = fig.add_subplot(projection='3d')
18+
X, Y, Z = axes3d.get_test_data(0.05)
19+
ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)
20+
ax.view_init(elev=0, azim=0, roll=30)
21+
plt.show()

lib/mpl_toolkits/mplot3d/axes3d.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1270,7 +1270,7 @@ def _on_move(self, event):
12701270
roll = np.deg2rad(self.roll)
12711271
if dx == 0 and dy == 0:
12721272
return
1273-
delev = (dy/h)*180*np.cos(roll) + (dx/w)*180*np.sin(roll)
1273+
delev = +(dy/h)*180*np.cos(roll) + (dx/w)*180*np.sin(roll)
12741274
dazim = -(dy/h)*180*np.sin(roll) + (dx/w)*180*np.cos(roll)
12751275
self.elev = art3d._norm_angle(self.elev - delev)
12761276
self.azim = art3d._norm_angle(self.azim - dazim)

lib/mpl_toolkits/mplot3d/proj3d.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ def world_transformation(xmin, xmax,
5252

5353

5454
def rotation_about_vector(v, angle):
55-
'''Produce a rotation matrix for an angle in radians about a vector.'''
55+
"""
56+
Produce a rotation matrix for an angle in radians about a vector.
57+
"""
5658
v /= np.linalg.norm(v)
5759
s = np.sin(angle)
5860
c = np.cos(angle)
@@ -61,26 +63,27 @@ def rotation_about_vector(v, angle):
6163
R = np.array([
6264
[t*v[0]*v[0] + c, t*v[0]*v[1] - v[2]*s, t*v[0]*v[2] + v[1]*s],
6365
[t*v[1]*v[0] + v[2]*s, t*v[1]*v[1] + c, t*v[1]*v[2] - v[0]*s],
64-
[t*v[2]*v[0] - v[1]*s, t*v[2]*v[1] + v[0]*s, t*v[2]*v[2] + c ]])
66+
[t*v[2]*v[0] - v[1]*s, t*v[2]*v[1] + v[0]*s, t*v[2]*v[2] + c]])
6567

6668
return R
6769

6870

6971
def view_transformation(E, R, V, roll):
7072
n = (E - R)
71-
n /= np.linalg.norm(n)
73+
n = n/np.linalg.norm(n)
7274
u = np.cross(V, n)
73-
u /= np.linalg.norm(u)
75+
u = u/np.linalg.norm(u)
7476
v = np.cross(n, u)
77+
v = v/np.linalg.norm(v)
7578

7679
Rroll = rotation_about_vector(n, roll)
7780
u = np.dot(Rroll, u)
7881
v = np.dot(Rroll, v)
7982

8083
Mr = np.diag([1.] * 4)
8184
Mt = np.diag([1.] * 4)
82-
Mr[:3,:3] = u, v, n
83-
Mt[:3,-1] = -E
85+
Mr[:3, :3] = [u, v, n]
86+
Mt[:3, -1] = -E
8487

8588
return np.dot(Mr, Mt)
8689

lib/mpl_toolkits/tests/test_mplot3d.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def test_bar3d_shaded():
6262
x2d, y2d = x2d.ravel(), y2d.ravel()
6363
z = x2d + y2d + 1 # Avoid triggering bug with zero-depth boxes.
6464

65-
views = [(-60, 30, 0), (30, 30, 0), (30, -30, 0), (120, -30, 0)]
65+
views = [(-60, 30, 0), (30, 30, 30), (30, -30, -90), (120, -30, 0)]
6666
fig = plt.figure(figsize=plt.figaspect(1 / len(views)))
6767
axs = fig.subplots(
6868
1, len(views),
@@ -414,7 +414,7 @@ def test_marker_draw_order_view_rotated(fig_test, fig_ref):
414414
ax = fig_ref.add_subplot(projection='3d')
415415
ax.set_axis_off()
416416
ax.scatter(x, y, z, s=3500, c=color[::-1]) # color reversed
417-
ax.view_init(elev=0, azim=azim - 180, roll=0) # view rotated by 180 degrees
417+
ax.view_init(elev=0, azim=azim - 180, roll=0) # view rotated by 180 deg
418418

419419

420420
@mpl3d_image_comparison(['plot_3d_from_2d.png'], tol=0.015)
@@ -860,7 +860,8 @@ def _test_proj_make_M():
860860
E = np.array([1000, -1000, 2000])
861861
R = np.array([100, 100, 100])
862862
V = np.array([0, 0, 1])
863-
viewM = proj3d.view_transformation(E, R, V)
863+
roll = 0
864+
viewM = proj3d.view_transformation(E, R, V, roll)
864865
perspM = proj3d.persp_transformation(100, -100)
865866
M = np.dot(perspM, viewM)
866867
return M
@@ -925,7 +926,8 @@ def test_proj_axes_cube_ortho():
925926
E = np.array([200, 100, 100])
926927
R = np.array([0, 0, 0])
927928
V = np.array([0, 0, 1])
928-
viewM = proj3d.view_transformation(E, R, V)
929+
roll = 0
930+
viewM = proj3d.view_transformation(E, R, V, roll)
929931
orthoM = proj3d.ortho_transformation(-1, 1)
930932
M = np.dot(orthoM, viewM)
931933

0 commit comments

Comments
 (0)