forked from xarray-contrib/xarray-spatial
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathanimated_hillshade.py
More file actions
141 lines (98 loc) · 3.7 KB
/
Copy pathanimated_hillshade.py
File metadata and controls
141 lines (98 loc) · 3.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import numpy as np
import datashader as ds
from datashader.transfer_functions import shade
from datashader.transfer_functions import stack
from datashader.colors import Elevation
from xrspatial import generate_terrain
from xrspatial import hillshade
from xrspatial import bump
from xrspatial import mean
from functools import partial
W = 600
H = 400
cvs = ds.Canvas(plot_width=W, plot_height=H,
x_range=(-20e6, 20e6),
y_range=(-20e6, 20e6))
terrain = generate_terrain(canvas=cvs)
def heights(locations, src, src_range, height=20):
num_bumps = locations.shape[0]
out = np.zeros(num_bumps, dtype=np.uint16)
for r in range(0, num_bumps):
loc = locations[r]
x = loc[0]
y = loc[1]
val = src[y, x]
if val >= src_range[0] and val < src_range[1]:
out[r] = height
return out
T = 300000 # Number of trees to add per call
src = terrain.data
trees = bump(W, H, count=T, height_func=partial(heights, src=src,
src_range=(1000, 1300), height=5))
trees += bump(W, H, count=T//2, height_func=partial(
heights, src=src, src_range=(1300, 1700), height=20))
trees += bump(W, H, count=T//3, height_func=partial(
heights, src=src, src_range=(1700, 2000), height=5))
tree_colorize = trees.copy()
tree_colorize.data[tree_colorize.data == 0] = np.nan
LAND_CONSTANT = 50.0
water = terrain.copy()
water.data = np.where(water.data > 0, LAND_CONSTANT, 0)
water = mean(water, passes=50, excludes=[LAND_CONSTANT])
water.data[water.data == LAND_CONSTANT] = np.nan
def create_map(azimuth):
global cvs
global terrain
global water
global trees
img = stack(shade(terrain, cmap=Elevation, how='linear'),
shade(water, cmap=['aqua', 'white']),
shade(hillshade(terrain + trees, azimuth=azimuth),
cmap=['black', 'white'], how='linear', alpha=128),
shade(tree_colorize, cmap='limegreen', how='linear')
)
print('image created')
return img.to_pil()
def create_map2():
global cvs
global terrain
global water
global trees
img = stack(shade(terrain, cmap=['black', 'white'], how='linear'))
yield img.to_pil()
img = stack(shade(terrain, cmap=Elevation, how='linear'))
yield img.to_pil()
img = stack(shade(terrain, cmap=Elevation, how='linear'),
shade(hillshade(terrain, azimuth=210),
cmap=['black', 'white'], how='linear', alpha=128),
)
yield img.to_pil()
img = stack(shade(terrain, cmap=Elevation, how='linear'),
shade(water, cmap=['aqua', 'white']),
shade(hillshade(terrain, azimuth=210),
cmap=['black', 'white'], how='linear', alpha=128),
)
yield img.to_pil()
img = stack(shade(terrain, cmap=Elevation, how='linear'),
shade(water, cmap=['aqua', 'white']),
shade(hillshade(terrain + trees, azimuth=210),
cmap=['black', 'white'], how='linear', alpha=128),
shade(tree_colorize, cmap='limegreen', how='linear')
)
yield img.to_pil()
yield img.to_pil()
yield img.to_pil()
yield img.to_pil()
def gif1():
images = []
for i in np.linspace(0, 360, 6):
images.append(create_map(int(i)))
images[0].save('animated_hillshade.gif',
save_all=True, append_images=images[1:],
optimize=False, duration=5000, loop=0)
def gif2():
images = list(create_map2())
images[0].save('composite_map.gif',
save_all=True, append_images=images[1:],
optimize=False, duration=1000, loop=0)
gif2()