|
| 1 | +""" |
| 2 | +Demonstrates the visual effect of varying blend mode and vertical exaggeration |
| 3 | +on "hillshaded" plots. |
| 4 | +
|
| 5 | +Note that the "overlay" and "soft" blend modes work well for complex surfaces |
| 6 | +such as this example, while the default "hsv" blend mode works best for smooth |
| 7 | +surfaces such as many mathematical functions. |
| 8 | +
|
| 9 | +In most cases, hillshading is used purely for visual purposes, and *dx*/*dy* |
| 10 | +can be safely ignored. In that case, you can tweak *vert_exag* (vertical |
| 11 | +exaggeration) by trial and error to give the desired visual effect. However, |
| 12 | +this example demonstrates how to use the *dx* and *dy* kwargs to ensure that |
| 13 | +the *vert_exag* parameter is the true vertical exaggeration. |
| 14 | +""" |
| 15 | +import numpy as np |
| 16 | +import matplotlib.pyplot as plt |
| 17 | +from matplotlib.cbook import get_sample_data |
| 18 | +from matplotlib.colors import LightSource |
| 19 | + |
| 20 | +dem = np.load(get_sample_data('jacksboro_fault_dem.npz')) |
| 21 | +z = dem['elevation'] |
| 22 | + |
| 23 | +#-- Optional dx and dy for accurate vertical exaggeration -------------------- |
| 24 | +# If you need topographically accurate vertical exaggeration, or you don't want |
| 25 | +# to guess at what *vert_exag* should be, you'll need to specify the cellsize |
| 26 | +# of the grid (i.e. the *dx* and *dy* parameters). Otherwise, any *vert_exag* |
| 27 | +# value you specify will be realitive to the grid spacing of your input data |
| 28 | +# (in other words, *dx* and *dy* default to 1.0, and *vert_exag* is calculated |
| 29 | +# relative to those parameters). Similarly, *dx* and *dy* are assumed to be in |
| 30 | +# the same units as your input z-values. Therefore, we'll need to convert the |
| 31 | +# given dx and dy from decimal degrees to meters. |
| 32 | +dx, dy = dem['dx'], dem['dy'] |
| 33 | +dy = 111200 * dy |
| 34 | +dx = 111200 * dx * np.cos(np.radians(dem['ymin'])) |
| 35 | +#----------------------------------------------------------------------------- |
| 36 | + |
| 37 | +# Shade from the northwest, with the sun 45 degrees from horizontal |
| 38 | +ls = LightSource(azdeg=315, altdeg=45) |
| 39 | +cmap = plt.cm.gist_earth |
| 40 | + |
| 41 | +fig, axes = plt.subplots(nrows=4, ncols=3, figsize=(8, 9)) |
| 42 | +plt.setp(axes.flat, xticks=[], yticks=[]) |
| 43 | + |
| 44 | +# Vary vertical exaggeration and blend mode and plot all combinations |
| 45 | +for col, ve in zip(axes.T, [0.1, 1, 10]): |
| 46 | + # Show the hillshade intensity image in the first row |
| 47 | + col[0].imshow(ls.hillshade(z, vert_exag=ve, dx=dx, dy=dy), cmap='gray') |
| 48 | + |
| 49 | + # Place hillshaded plots with different blend modes in the rest of the rows |
| 50 | + for ax, mode in zip(col[1:], ['hsv', 'overlay', 'soft']): |
| 51 | + rgb = ls.shade(z, cmap=cmap, blend_mode=mode, |
| 52 | + vert_exag=ve, dx=dx, dy=dy) |
| 53 | + ax.imshow(rgb) |
| 54 | + |
| 55 | +# Label rows and columns |
| 56 | +for ax, ve in zip(axes[0], [0.1, 1, 10]): |
| 57 | + ax.set_title('{}'.format(ve), size=18) |
| 58 | +for ax, mode in zip(axes[:,0], ['Hillshade', 'hsv', 'overlay', 'soft']): |
| 59 | + ax.set_ylabel(mode, size=18) |
| 60 | + |
| 61 | +# Group labels... |
| 62 | +axes[0,1].annotate('Vertical Exaggeration', (0.5, 1), xytext=(0, 30), |
| 63 | + textcoords='offset points', xycoords='axes fraction', |
| 64 | + ha='center', va='bottom', size=20) |
| 65 | +axes[2,0].annotate('Blend Mode', (0, 0.5), xytext=(-30, 0), |
| 66 | + textcoords='offset points', xycoords='axes fraction', |
| 67 | + ha='right', va='center', size=20, rotation=90) |
| 68 | +fig.subplots_adjust(bottom=0.05, right=0.95) |
| 69 | + |
| 70 | +plt.show() |
0 commit comments