Skip to content

Commit 087e15a

Browse files
committed
Replaced a lot of code related to image-drawing with numpy-code.
1 parent 56e8dba commit 087e15a

5 files changed

Lines changed: 137 additions & 187 deletions

File tree

worldengine/draw.py

Lines changed: 55 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import numpy
33

44
from worldengine.drawing_functions import draw_ancientmap, \
5-
draw_rivers_on_image, gradient
5+
draw_rivers_on_image
66

77
# -------------
88
# Helper values
@@ -167,43 +167,33 @@ def draw_simple_elevation(world, sea_level, target):
167167
""" This function can be used on a generic canvas (either an image to save
168168
on disk or a canvas part of a GUI)
169169
"""
170-
min_elev_sea = None
171-
max_elev_sea = None
172-
min_elev_land = None
173-
max_elev_land = None
174-
for y in range(world.height):
175-
for x in range(world.width):
176-
e = world.elevation['data'][y,x]
177-
if sea_level is None:
178-
if min_elev_land is None or e < min_elev_land:
179-
min_elev_land = e
180-
if max_elev_land is None or e > max_elev_land:
181-
max_elev_land = e
182-
elif world.is_land((x, y)):
183-
if min_elev_land is None or e < min_elev_land:
184-
min_elev_land = e
185-
if max_elev_land is None or e > max_elev_land:
186-
max_elev_land = e
187-
else:
188-
if min_elev_sea is None or e < min_elev_sea:
189-
min_elev_sea = e
190-
if max_elev_sea is None or e > max_elev_sea:
191-
max_elev_sea = e
170+
e = world.elevation['data']
192171

193-
elev_delta_land = (max_elev_land - min_elev_land)/11
194-
if sea_level != None:
172+
c = numpy.empty(e.shape, dtype=numpy.float)
173+
if sea_level is None or world.ocean is None or not world.ocean.any(): # or 'not any ocean'
174+
mask = numpy.ma.array(e, mask = False) # the whole map
175+
min_elev_land = mask.min()
176+
max_elev_land = mask.max()
177+
elev_delta_land = (max_elev_land - min_elev_land) / 11.0
178+
179+
c = ((e - min_elev_land) / elev_delta_land) + 1
180+
else:
181+
mask = numpy.ma.array(e, mask = world.ocean) # only land
182+
min_elev_land = mask.min()
183+
max_elev_land = mask.max()
184+
elev_delta_land = (max_elev_land - min_elev_land) / 11.0
185+
186+
mask = numpy.ma.array(e, mask = numpy.logical_not(world.ocean)) # only ocean
187+
min_elev_sea = mask.min()
188+
max_elev_sea = mask.max()
195189
elev_delta_sea = max_elev_sea - min_elev_sea
196-
190+
191+
c[world.ocean] = ((e[world.ocean] - min_elev_sea) / elev_delta_sea)
192+
c[numpy.invert(world.ocean)] = ((e[numpy.invert(world.ocean)] - min_elev_land) / elev_delta_land) + 1
193+
197194
for y in range(world.height):
198195
for x in range(world.width):
199-
e = world.elevation['data'][y, x]
200-
if sea_level is None:
201-
c = ((e - min_elev_land) / elev_delta_land) + 1
202-
elif world.is_land((x, y)):
203-
c = ((e - min_elev_land) / elev_delta_land) + 1
204-
else:
205-
c = ((e - min_elev_sea) / elev_delta_sea)
206-
r, g, b = elevation_color(c, sea_level)
196+
r, g, b = elevation_color(c[y, x], sea_level)
207197
target.set_pixel(x, y, (int(r * 255), int(g * 255),
208198
int(b * 255), 255))
209199

@@ -212,46 +202,34 @@ def draw_riversmap(world, target):
212202
sea_color = (255, 255, 255, 255)
213203
land_color = (0, 0, 0, 255)
214204

215-
for y in range(world.height):#TODO: numpy
205+
for y in range(world.height):
216206
for x in range(world.width):
217-
if world.ocean[y, x]:
218-
target.set_pixel(x, y, sea_color)
219-
else:
220-
target.set_pixel(x, y, land_color)
207+
target.set_pixel(x, y, sea_color if world.ocean[y, x] else land_color)
221208

222209
draw_rivers_on_image(world, target, factor=1)
223210

224211

225212
def draw_grayscale_heightmap(world, target):
226-
min_elev_sea = None
227-
max_elev_sea = None
228-
min_elev_land = None
229-
max_elev_land = None
230-
for y in range(world.height):
231-
for x in range(world.width):
232-
e = world.elevation['data'][y, x]
233-
if world.is_land((x, y)):
234-
if min_elev_land is None or e < min_elev_land:
235-
min_elev_land = e
236-
if max_elev_land is None or e > max_elev_land:
237-
max_elev_land = e
238-
else:
239-
if min_elev_sea is None or e < min_elev_sea:
240-
min_elev_sea = e
241-
if max_elev_sea is None or e > max_elev_sea:
242-
max_elev_sea = e
213+
e = world.elevation['data']
243214

215+
mask = numpy.ma.array(e, mask = world.ocean) # only land
216+
min_elev_land = mask.min()
217+
max_elev_land = mask.max()
244218
elev_delta_land = max_elev_land - min_elev_land
219+
220+
mask = numpy.ma.array(e, mask = numpy.logical_not(world.ocean)) # only ocean
221+
min_elev_sea = mask.min()
222+
max_elev_sea = mask.max()
245223
elev_delta_sea = max_elev_sea - min_elev_sea
246224

225+
c = numpy.empty(e.shape, dtype=numpy.float)
226+
c[numpy.invert(world.ocean)] = (e[numpy.invert(world.ocean)] - min_elev_land) * 127 / elev_delta_land + 128
227+
c[world.ocean] = (e[world.ocean] - min_elev_sea) * 127 / elev_delta_sea
228+
c = numpy.rint(c).astype(dtype=numpy.int32) # proper rounding
229+
247230
for y in range(world.height):
248231
for x in range(world.width):
249-
e = world.elevation['data'][y, x]
250-
if world.is_land((x, y)):
251-
c = int(((e - min_elev_land) * 127) / elev_delta_land)+128
252-
else:
253-
c = int(((e - min_elev_sea) * 127) / elev_delta_sea)
254-
target.set_pixel(x, y, (c, c, c, 255))
232+
target.set_pixel(x, y, (c[y, x], c[y, x], c[y, x], 255))
255233

256234

257235
def draw_elevation(world, shadow, target):
@@ -267,7 +245,7 @@ def draw_elevation(world, shadow, target):
267245
max_elev = mask.max()
268246
elev_delta = max_elev - min_elev
269247

270-
for y in range(height):#TODO: numpy optimisation for the code below
248+
for y in range(height):
271249
for x in range(width):
272250
if ocean[y, x]:
273251
target.set_pixel(x, y, (0, 0, 255, 255))
@@ -306,24 +284,16 @@ def draw_precipitation(world, target, black_and_white=False):
306284
height = world.height
307285

308286
if black_and_white:
309-
low = None
310-
high = None
311-
for y in range(height):
312-
for x in range(width):
313-
p = world.precipitations_at((x, y))
314-
if low is None or p < low:
315-
low = p
316-
if high is None or p > high:
317-
high = p
287+
low = world.precipitation['data'].min()
288+
high = world.precipitation['data'].max()
289+
floor = 0
290+
ceiling = 255
291+
292+
colors = numpy.interp(world.precipitation['data'], [low, high], [floor, ceiling])
293+
colors = numpy.rint(colors).astype(dtype=numpy.int32) # proper rounding
318294
for y in range(height):
319295
for x in range(width):
320-
p = world.precipitations_at((x, y))
321-
if p <= low:
322-
target.set_pixel(x, y, (0, 0, 0, 255))
323-
elif p >= high:
324-
target.set_pixel(x, y, (255, 255, 255, 255))
325-
else:
326-
target.set_pixel(x, y, gradient(p, low, high, (0, 0, 0), (255, 255, 255)))
296+
target.set_pixel(x, y, (colors[y, x], colors[y, x], colors[y, x], 255))
327297
else:
328298
for y in range(height):
329299
for x in range(width):
@@ -366,15 +336,14 @@ def draw_temperature_levels(world, target, black_and_white=False):
366336
if black_and_white:
367337
low = world.temperature_thresholds()[0][1]
368338
high = world.temperature_thresholds()[5][1]
339+
floor = 0
340+
ceiling = 255
341+
342+
colors = numpy.interp(world.temperature['data'], [low, high], [floor, ceiling])
343+
colors = numpy.rint(colors).astype(dtype=numpy.int32) # proper rounding
369344
for y in range(height):
370345
for x in range(width):
371-
t = world.temperature_at((x, y))
372-
if t <= low:
373-
target.set_pixel(x, y, (0, 0, 0, 255))
374-
elif t >= high:
375-
target.set_pixel(x, y, (255, 255, 255, 255))
376-
else:
377-
target.set_pixel(x, y, gradient(t, low, high, (0, 0, 0), (255, 255, 255)))
346+
target.set_pixel(x, y, (colors[y, x], colors[y, x], colors[y, x], 255))
378347

379348
else:
380349
for y in range(height):

0 commit comments

Comments
 (0)