0
# 3D Plotting
1
2
Three-dimensional visualization capabilities through the mplot3d toolkit. Matplotlib provides comprehensive 3D plotting functionality including line plots, surface plots, scatter plots, wireframes, and volume rendering.
3
4
## Capabilities
5
6
### 3D Axes
7
8
Enhanced axes class with 3D coordinate system support.
9
10
```python { .api }
11
from mpl_toolkits.mplot3d import Axes3D
12
import mpl_toolkits.mplot3d.axes3d as axes3d
13
14
class Axes3D:
15
def __init__(self, fig, rect=None, *args, azim=-60, elev=30, zscale=None,
16
sharez=None, proj_type='persp', box_aspect=None, **kwargs):
17
"""3D axes with perspective projection."""
18
19
# 3D plotting methods
20
def plot(self, xs, ys, zs=0, *args, zdir='z', **kwargs) -> Line3D:
21
"""Plot lines and/or markers in 3D."""
22
23
def scatter(self, xs, ys, zs=0, c=None, s=20, depthshade=True, *args,
24
zdir='z', **kwargs) -> Path3DCollection:
25
"""Create a 3D scatter plot."""
26
27
def bar(self, left, height, zs=0, zdir='z', *args, **kwargs) -> Poly3DCollection:
28
"""Create a 3D bar plot."""
29
30
def bar3d(self, x, y, z, dx, dy, dz, color=None, zsort='average',
31
shade=True, lightsource=None, *args, **kwargs) -> Poly3DCollection:
32
"""Create a 3D bar plot with rectangular bars."""
33
34
# Surface and mesh plotting
35
def plot_surface(self, X, Y, Z, *args, norm=None, vmin=None, vmax=None,
36
lightsource=None, **kwargs) -> Poly3DCollection:
37
"""Create a 3D surface plot."""
38
39
def plot_wireframe(self, X, Y, Z, *args, rstride=1, cstride=1, **kwargs) -> Line3DCollection:
40
"""Create a 3D wireframe plot."""
41
42
def plot_trisurf(self, *args, color=None, norm=None, vmin=None, vmax=None,
43
lightsource=None, **kwargs) -> Poly3DCollection:
44
"""Create a 3D surface plot from triangulated data."""
45
46
# Contour plotting
47
def contour(self, X, Y, Z, *args, extend3d=False, stride=5, zdir='z',
48
offset=None, **kwargs) -> Path3DCollection:
49
"""Create 3D contour lines."""
50
51
def contourf(self, X, Y, Z, *args, zdir='z', offset=None, **kwargs) -> Path3DCollection:
52
"""Create filled 3D contours."""
53
54
# Text and annotation
55
def text(self, x, y, z, s, zdir=None, **kwargs) -> Text3D:
56
"""Add text in 3D space."""
57
58
def text2D(self, x, y, s, fontdict=None, **kwargs) -> Text:
59
"""Add 2D text to 3D axes."""
60
61
# Axis and view control
62
def set_xlim(self, left=None, right=None, *, emit=True, auto=False) -> tuple:
63
"""Set x-axis limits."""
64
65
def set_ylim(self, bottom=None, top=None, *, emit=True, auto=False) -> tuple:
66
"""Set y-axis limits."""
67
68
def set_zlim(self, bottom=None, top=None, *, emit=True, auto=False) -> tuple:
69
"""Set z-axis limits."""
70
71
def set_xlabel(self, xlabel, fontdict=None, labelpad=None, **kwargs) -> Text:
72
"""Set x-axis label."""
73
74
def set_ylabel(self, ylabel, fontdict=None, labelpad=None, **kwargs) -> Text:
75
"""Set y-axis label."""
76
77
def set_zlabel(self, zlabel, fontdict=None, labelpad=None, **kwargs) -> Text:
78
"""Set z-axis label."""
79
80
def view_init(self, elev=None, azim=None, roll=None) -> None:
81
"""Set the elevation and azimuth of the axes."""
82
83
def set_proj_type(self, proj_type, focal_length=None) -> None:
84
"""Set the projection type ('persp' or 'ortho')."""
85
86
def set_box_aspect(self, aspect, *, zoom=1) -> None:
87
"""Set the aspect ratio of the 3D plot box."""
88
```
89
90
### 3D Collections and Artists
91
92
Specialized collection classes for 3D rendering.
93
94
```python { .api }
95
from mpl_toolkits.mplot3d.art3d import *
96
97
class Line3D:
98
def __init__(self, xs, ys, zs, *args, **kwargs):
99
"""3D line object."""
100
101
def set_data_3d(self, xs, ys, zs) -> None:
102
"""Set 3D line data."""
103
104
class Line3DCollection:
105
def __init__(self, segments, *args, **kwargs):
106
"""Collection of 3D line segments."""
107
108
def set_segments(self, segments) -> None:
109
"""Set line segments."""
110
111
class Poly3DCollection:
112
def __init__(self, verts, *args, zsort='average', **kwargs):
113
"""Collection of 3D polygons."""
114
115
def set_verts(self, verts) -> None:
116
"""Set polygon vertices."""
117
118
def set_zsort(self, zsort) -> None:
119
"""Set z-sorting method."""
120
121
class Path3DCollection:
122
def __init__(self, paths, *args, zs=0, zdir='z', depthshade=True, **kwargs):
123
"""Collection of 3D paths."""
124
125
def set_3d_properties(self, zs=0, zdir='z') -> None:
126
"""Set 3D properties."""
127
128
class Text3D:
129
def __init__(self, x=0, y=0, z=0, text='', zdir='z', **kwargs):
130
"""3D text object."""
131
132
def set_position_3d(self, xyz, zdir=None) -> None:
133
"""Set 3D text position."""
134
```
135
136
### Utility Functions
137
138
Helper functions for 3D plotting setup and data generation.
139
140
```python { .api }
141
from mpl_toolkits.mplot3d import proj3d
142
143
def persp_transformation(xvals, yvals, zvals, M) -> tuple:
144
"""Apply perspective transformation to 3D coordinates."""
145
146
def orthogonal_proj(zfront, zback) -> np.ndarray:
147
"""Return orthographic projection matrix."""
148
149
def world_transformation(xmin, xmax, ymin, ymax, zmin, zmax,
150
pb_aspect) -> np.ndarray:
151
"""Return world transformation matrix."""
152
153
# Axis creation helper
154
def Axes3D(fig=None, rect=None, *args, **kwargs):
155
"""Create a 3D axes in the given figure."""
156
```
157
158
## Usage Examples
159
160
### Basic 3D Line Plot
161
162
```python
163
import matplotlib.pyplot as plt
164
from mpl_toolkits.mplot3d import Axes3D
165
import numpy as np
166
167
# Create 3D plot
168
fig = plt.figure(figsize=(10, 8))
169
ax = fig.add_subplot(111, projection='3d')
170
171
# Generate 3D line data
172
t = np.linspace(0, 4*np.pi, 100)
173
x = np.sin(t)
174
y = np.cos(t)
175
z = t
176
177
# Plot 3D line
178
ax.plot(x, y, z, 'b-', linewidth=2, label='3D Spiral')
179
180
# Customize axes
181
ax.set_xlabel('X')
182
ax.set_ylabel('Y')
183
ax.set_zlabel('Z')
184
ax.set_title('3D Line Plot')
185
ax.legend()
186
187
plt.show()
188
```
189
190
### 3D Scatter Plot
191
192
```python
193
import matplotlib.pyplot as plt
194
from mpl_toolkits.mplot3d import Axes3D
195
import numpy as np
196
197
fig = plt.figure(figsize=(12, 5))
198
199
# First subplot: Basic scatter
200
ax1 = fig.add_subplot(121, projection='3d')
201
202
# Generate random 3D points
203
n = 100
204
x = np.random.standard_normal(n)
205
y = np.random.standard_normal(n)
206
z = np.random.standard_normal(n)
207
colors = np.random.rand(n)
208
sizes = 1000 * np.random.rand(n)
209
210
ax1.scatter(x, y, z, c=colors, s=sizes, alpha=0.6, cmap='viridis')
211
ax1.set_xlabel('X')
212
ax1.set_ylabel('Y')
213
ax1.set_zlabel('Z')
214
ax1.set_title('3D Scatter Plot')
215
216
# Second subplot: Clustered data
217
ax2 = fig.add_subplot(122, projection='3d')
218
219
# Generate clustered data
220
n_clusters = 3
221
n_points = 50
222
223
for i in range(n_clusters):
224
# Random cluster center
225
center = np.random.rand(3) * 10
226
227
# Generate points around center
228
x_cluster = center[0] + np.random.normal(0, 1, n_points)
229
y_cluster = center[1] + np.random.normal(0, 1, n_points)
230
z_cluster = center[2] + np.random.normal(0, 1, n_points)
231
232
ax2.scatter(x_cluster, y_cluster, z_cluster, s=60, alpha=0.8,
233
label=f'Cluster {i+1}')
234
235
ax2.set_xlabel('X')
236
ax2.set_ylabel('Y')
237
ax2.set_zlabel('Z')
238
ax2.set_title('Clustered 3D Data')
239
ax2.legend()
240
241
plt.tight_layout()
242
plt.show()
243
```
244
245
### 3D Surface Plot
246
247
```python
248
import matplotlib.pyplot as plt
249
from mpl_toolkits.mplot3d import Axes3D
250
import numpy as np
251
252
fig = plt.figure(figsize=(15, 5))
253
254
# Create mesh grid
255
x = np.linspace(-5, 5, 50)
256
y = np.linspace(-5, 5, 50)
257
X, Y = np.meshgrid(x, y)
258
259
# First surface: Gaussian
260
ax1 = fig.add_subplot(131, projection='3d')
261
Z1 = np.exp(-(X**2 + Y**2) / 10)
262
surf1 = ax1.plot_surface(X, Y, Z1, cmap='viridis', alpha=0.8)
263
ax1.set_title('Gaussian Surface')
264
ax1.set_xlabel('X')
265
ax1.set_ylabel('Y')
266
ax1.set_zlabel('Z')
267
fig.colorbar(surf1, ax=ax1, shrink=0.5)
268
269
# Second surface: Ripple effect
270
ax2 = fig.add_subplot(132, projection='3d')
271
R = np.sqrt(X**2 + Y**2)
272
Z2 = np.sin(R) / (R + 0.1) # Add small value to avoid division by zero
273
surf2 = ax2.plot_surface(X, Y, Z2, cmap='plasma', alpha=0.8)
274
ax2.set_title('Ripple Surface')
275
ax2.set_xlabel('X')
276
ax2.set_ylabel('Y')
277
ax2.set_zlabel('Z')
278
fig.colorbar(surf2, ax=ax2, shrink=0.5)
279
280
# Third surface: Saddle
281
ax3 = fig.add_subplot(133, projection='3d')
282
Z3 = X**2 - Y**2
283
surf3 = ax3.plot_surface(X, Y, Z3, cmap='coolwarm', alpha=0.8)
284
ax3.set_title('Saddle Surface')
285
ax3.set_xlabel('X')
286
ax3.set_ylabel('Y')
287
ax3.set_zlabel('Z')
288
fig.colorbar(surf3, ax=ax3, shrink=0.5)
289
290
plt.tight_layout()
291
plt.show()
292
```
293
294
### 3D Wireframe and Contour
295
296
```python
297
import matplotlib.pyplot as plt
298
from mpl_toolkits.mplot3d import Axes3D
299
import numpy as np
300
301
fig = plt.figure(figsize=(15, 10))
302
303
# Create data
304
x = np.linspace(-3, 3, 30)
305
y = np.linspace(-3, 3, 30)
306
X, Y = np.meshgrid(x, y)
307
Z = np.sin(np.sqrt(X**2 + Y**2))
308
309
# Wireframe plot
310
ax1 = fig.add_subplot(221, projection='3d')
311
ax1.plot_wireframe(X, Y, Z, color='blue', alpha=0.7)
312
ax1.set_title('3D Wireframe')
313
ax1.set_xlabel('X')
314
ax1.set_ylabel('Y')
315
ax1.set_zlabel('Z')
316
317
# Surface with wireframe overlay
318
ax2 = fig.add_subplot(222, projection='3d')
319
ax2.plot_surface(X, Y, Z, cmap='viridis', alpha=0.6)
320
ax2.plot_wireframe(X, Y, Z, color='black', alpha=0.3, linewidth=0.5)
321
ax2.set_title('Surface + Wireframe')
322
ax2.set_xlabel('X')
323
ax2.set_ylabel('Y')
324
ax2.set_zlabel('Z')
325
326
# 3D contour lines
327
ax3 = fig.add_subplot(223, projection='3d')
328
ax3.contour(X, Y, Z, levels=15, cmap='viridis')
329
ax3.set_title('3D Contour Lines')
330
ax3.set_xlabel('X')
331
ax3.set_ylabel('Y')
332
ax3.set_zlabel('Z')
333
334
# 3D filled contours
335
ax4 = fig.add_subplot(224, projection='3d')
336
ax4.contourf(X, Y, Z, levels=15, cmap='plasma', alpha=0.8)
337
ax4.set_title('3D Filled Contours')
338
ax4.set_xlabel('X')
339
ax4.set_ylabel('Y')
340
ax4.set_zlabel('Z')
341
342
plt.tight_layout()
343
plt.show()
344
```
345
346
### 3D Bar Plot
347
348
```python
349
import matplotlib.pyplot as plt
350
from mpl_toolkits.mplot3d import Axes3D
351
import numpy as np
352
353
fig = plt.figure(figsize=(12, 8))
354
ax = fig.add_subplot(111, projection='3d')
355
356
# Create 3D bar chart data
357
xpos = np.arange(5)
358
ypos = np.arange(4)
359
xpos, ypos = np.meshgrid(xpos, ypos)
360
361
xpos = xpos.ravel()
362
ypos = ypos.ravel()
363
zpos = np.zeros_like(xpos)
364
365
# Bar dimensions
366
dx = dy = 0.8
367
dz = np.random.rand(len(xpos)) * 10
368
369
# Color each bar based on its height
370
colors = plt.cm.viridis(dz / float(dz.max()))
371
372
# Create 3D bars
373
bars = ax.bar3d(xpos, ypos, zpos, dx, dy, dz, color=colors, alpha=0.8)
374
375
# Customize plot
376
ax.set_xlabel('X Position')
377
ax.set_ylabel('Y Position')
378
ax.set_zlabel('Height')
379
ax.set_title('3D Bar Chart')
380
381
# Add colorbar
382
mappable = plt.cm.ScalarMappable(cmap='viridis')
383
mappable.set_array(dz)
384
fig.colorbar(mappable, ax=ax, shrink=0.5, aspect=20)
385
386
plt.show()
387
```
388
389
### Interactive 3D Plot with View Control
390
391
```python
392
import matplotlib.pyplot as plt
393
from mpl_toolkits.mplot3d import Axes3D
394
import numpy as np
395
396
# Create parametric surface
397
u = np.linspace(0, 2 * np.pi, 50)
398
v = np.linspace(0, np.pi, 50)
399
U, V = np.meshgrid(u, v)
400
401
# Torus surface
402
R = 3 # Major radius
403
r = 1 # Minor radius
404
X = (R + r * np.cos(V)) * np.cos(U)
405
Y = (R + r * np.cos(V)) * np.sin(U)
406
Z = r * np.sin(V)
407
408
fig = plt.figure(figsize=(12, 9))
409
410
# Create multiple views
411
views = [(30, 45), (60, 30), (0, 0), (90, 90)]
412
titles = ['Default View', 'Side View', 'Front View', 'Top View']
413
414
for i, (elev, azim) in enumerate(views):
415
ax = fig.add_subplot(2, 2, i+1, projection='3d')
416
417
# Plot torus
418
surf = ax.plot_surface(X, Y, Z, cmap='plasma', alpha=0.8)
419
420
# Set view angle
421
ax.view_init(elev=elev, azim=azim)
422
423
# Customize
424
ax.set_xlabel('X')
425
ax.set_ylabel('Y')
426
ax.set_zlabel('Z')
427
ax.set_title(f'{titles[i]} (elev={elev}°, azim={azim}°)')
428
429
# Equal aspect ratio
430
ax.set_box_aspect([1,1,0.5])
431
432
plt.tight_layout()
433
plt.show()
434
435
# Create interactive plot
436
fig_interactive = plt.figure(figsize=(10, 8))
437
ax_interactive = fig_interactive.add_subplot(111, projection='3d')
438
439
surf = ax_interactive.plot_surface(X, Y, Z, cmap='plasma', alpha=0.8)
440
ax_interactive.set_xlabel('X')
441
ax_interactive.set_ylabel('Y')
442
ax_interactive.set_zlabel('Z')
443
ax_interactive.set_title('Interactive 3D Torus (drag to rotate)')
444
445
# Add colorbar
446
fig_interactive.colorbar(surf, shrink=0.5, aspect=20)
447
448
plt.show()
449
```
450
451
### Advanced 3D Visualization
452
453
```python
454
import matplotlib.pyplot as plt
455
from mpl_toolkits.mplot3d import Axes3D
456
import numpy as np
457
458
# Create complex 3D scene
459
fig = plt.figure(figsize=(14, 10))
460
ax = fig.add_subplot(111, projection='3d')
461
462
# Generate multiple surfaces
463
x = np.linspace(-5, 5, 30)
464
y = np.linspace(-5, 5, 30)
465
X, Y = np.meshgrid(x, y)
466
467
# Bottom surface (terrain-like)
468
Z1 = 2 * np.sin(np.sqrt(X**2 + Y**2)) * np.exp(-0.1 * np.sqrt(X**2 + Y**2))
469
surf1 = ax.plot_surface(X, Y, Z1, cmap='terrain', alpha=0.8)
470
471
# Top surface (canopy-like)
472
Z2 = Z1 + 3 + np.cos(X) * np.cos(Y)
473
surf2 = ax.plot_wireframe(X, Y, Z2, color='green', alpha=0.6, linewidth=0.5)
474
475
# Add some 3D scatter points (trees)
476
n_trees = 20
477
tree_x = np.random.uniform(-4, 4, n_trees)
478
tree_y = np.random.uniform(-4, 4, n_trees)
479
tree_z = np.interp(np.sqrt(tree_x**2 + tree_y**2),
480
np.sqrt(X[0,:]**2 + Y[:,0]**2), Z1[0,:])
481
482
ax.scatter(tree_x, tree_y, tree_z, c='brown', s=100, marker='^',
483
label='Trees', alpha=0.8)
484
485
# Add 3D text labels
486
ax.text(0, 0, 6, 'Peak', fontsize=12, weight='bold')
487
ax.text(-4, -4, -2, 'Valley', fontsize=10)
488
489
# Customize the plot
490
ax.set_xlabel('X Distance')
491
ax.set_ylabel('Y Distance')
492
ax.set_zlabel('Height')
493
ax.set_title('3D Landscape Visualization')
494
ax.legend()
495
496
# Set viewing angle for best perspective
497
ax.view_init(elev=20, azim=45)
498
499
# Add colorbar
500
fig.colorbar(surf1, ax=ax, shrink=0.5, aspect=20, label='Elevation')
501
502
plt.tight_layout()
503
plt.show()
504
```