Skip to content

Commit c1e5e0a

Browse files
Code review changes
Make focal_length a private attr linting
1 parent 81f3a23 commit c1e5e0a

File tree

3 files changed

+27
-19
lines changed

3 files changed

+27
-19
lines changed

doc/users/next_whats_new/3d_plot_focal_length.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@ Give the 3D camera a custom focal length
33

44
Users can now better mimic real-world cameras by specifying the focal length of
55
the virtual camera in 3D plots. An increasing focal length between 1 and
6-
+infinity "flattens" the image, while a decreasing focal length between 1 and 0
6+
infinity "flattens" the image, while a decreasing focal length between 1 and 0
77
exaggerates the perspective and gives the image more apparent depth. The
88
default focal length of 1 corresponds to a Field of View (FOV) of 90 deg, and
99
is backwards-compatible with existing 3D plots.
1010

1111
The focal length can be calculated from a desired FOV via the equation:
12-
| ``focal_length = 1/tan(FOV/2)``
12+
13+
.. mathmpl::
14+
15+
focal\_length = 1/tan(FOV/2)
1316

1417
.. plot::
1518
:include-source: true

examples/mplot3d/projections.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,25 @@
77
changing the focal length for a perspective projection. Note that matplotlib
88
corrects for the 'zoom' effect of changing the focal length.
99
10-
An increasing focal length between 1 and +infinity "flattens" the image, while
10+
An increasing focal length between 1 and infinity "flattens" the image, while
1111
a decreasing focal length between 1 and 0 exaggerates the perspective and gives
1212
the image more apparent depth. The default focal length of 1 corresponds to a
1313
Field of View (FOV) of 90 deg. In the limiting case, a focal length of
14-
+infinity corresponds to an orthographic projection after correction of the
14+
infinity corresponds to an orthographic projection after correction of the
1515
zoom effect.
1616
1717
You can calculate focal length from a FOV via the equation:
18-
focal_length = 1/tan(FOV/2)
18+
19+
.. mathmpl::
20+
21+
1 / \tan (FOV / 2)
1922
2023
Or vice versa:
21-
FOV = 2*atan(1/focal_length)
24+
25+
.. mathmpl::
26+
27+
FOV = 2 * \atan (1 / focal length)
28+
2229
"""
2330

2431
from mpl_toolkits.mplot3d import axes3d
@@ -36,7 +43,7 @@
3643

3744
# Set the orthographic projection.
3845
axs[0].set_proj_type('ortho') # FOV = 0 deg
39-
axs[0].set_title("'ortho'\nfocal_length = +∞", fontsize=10)
46+
axs[0].set_title("'ortho'\nfocal_length = ∞", fontsize=10)
4047

4148
# Set the perspective projections
4249
axs[1].set_proj_type('persp') # FOV = 90 deg

lib/mpl_toolkits/mplot3d/axes3d.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,22 +1046,20 @@ def set_proj_type(self, proj_type, focal_length=None):
10461046
The focal length can be computed from a desired Field Of View via
10471047
the equation: focal_length = 1/tan(FOV/2)
10481048
"""
1049+
_api.check_in_list(['persp', 'ortho'], proj_type=proj_type)
10491050
if proj_type == 'persp':
10501051
if focal_length is None:
1051-
self.focal_length = 1
1052+
self._focal_length = 1
10521053
else:
10531054
if focal_length <= 0:
1054-
raise ValueError(f"focal_length = {focal_length} must be" +
1055+
raise ValueError(f"focal_length = {focal_length} must be"
10551056
" greater than 0")
1056-
self.focal_length = focal_length
1057+
self._focal_length = focal_length
10571058
elif proj_type == 'ortho':
10581059
if focal_length not in (None, np.inf):
1059-
raise ValueError(f"focal_length = {focal_length} must be" +
1060+
raise ValueError(f"focal_length = {focal_length} must be"
10601061
f"None for proj_type = {proj_type}")
1061-
self.focal_length = np.inf
1062-
else:
1063-
raise ValueError(f"proj_type = {proj_type} must be in" +
1064-
f"{'persp', 'ortho'}")
1062+
self._focal_length = np.inf
10651063

10661064
def _roll_to_vertical(self, arr):
10671065
"""Roll arrays to match the different vertical axis."""
@@ -1118,18 +1116,18 @@ def get_proj(self):
11181116
V[self._vertical_axis] = -1 if abs(elev_rad) > 0.5 * np.pi else 1
11191117

11201118
# Generate the view and projection transformation matrices
1121-
if self.focal_length == np.inf:
1119+
if self._focal_length == np.inf:
11221120
# Orthographic projection
11231121
viewM = proj3d.view_transformation(eye, R, V, roll_rad)
11241122
projM = proj3d.ortho_transformation(-self.dist, self.dist)
11251123
else:
11261124
# Perspective projection
11271125
# Scale the eye dist to compensate for the focal length zoom effect
1128-
eye_focal = R + self.dist * ps * self.focal_length
1126+
eye_focal = R + self.dist * ps * self._focal_length
11291127
viewM = proj3d.view_transformation(eye_focal, R, V, roll_rad)
11301128
projM = proj3d.persp_transformation(-self.dist,
11311129
self.dist,
1132-
self.focal_length)
1130+
self._focal_length)
11331131

11341132
# Combine all the transformation matrices to get the final projection
11351133
M0 = np.dot(viewM, worldM)
@@ -1194,7 +1192,7 @@ def cla(self):
11941192
pass
11951193

11961194
self._autoscaleZon = True
1197-
if self.focal_length == np.inf:
1195+
if self._focal_length == np.inf:
11981196
self._zmargin = rcParams['axes.zmargin']
11991197
else:
12001198
self._zmargin = 0.

0 commit comments

Comments
 (0)