You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

219 lines
5.3 KiB

#!/usr/bin/env python3
import libicmmts
import sys
import xml.etree.ElementTree as ET
pack = libicmmts.get_pack()
params = libicmmts.get_params()
nations = libicmmts.get_nations()
MIN_HEIGHT = -990
MAX_HEIGHT = (100 - 18) ** params['height_exponent']
def correct_height(h):
nh = MIN_HEIGHT
if h >= 20:
nh = (h - 18) ** params['height_exponent']
elif h > 0:
nh = (h - 20) / h * 50
return round(nh)
BIOME_COLORS = [
(0x46, 0x6E, 0xAB),
(0xFB, 0xE7, 0x9F),
(0xB5, 0xB8, 0x87),
(0xD2, 0xD0, 0x82),
(0xC8, 0xD6, 0x8F),
(0xB6, 0xD9, 0x5D),
(0x29, 0xBC, 0x56),
(0x7D, 0xCB, 0x35),
(0x40, 0x9C, 0x43),
(0x4B, 0x6B, 0x32),
(0x96, 0x78, 0x4B),
(0xD5, 0xE7, 0xEB),
(0x0B, 0x91, 0x31),
]
COLOR_LOW = (0x6E, 0xAA, 0x46)
COLOR_HIGH = (0x82, 0x46, 0xAA)
BIOME_NAMES = [
"Marine",
"Hot desert",
"Cold desert",
"Savanna",
"Grassland",
"Tropical seasonal forest",
"Temperate deciduous forest",
"Tropical rainforest",
"Temperate rainforest",
"Taiga",
"Tundra",
"Glacier",
"Wetland",
]
def lerp(x, y, i):
return x * (1 - i) + y * i
def color_height(i):
f = str(pack['cells']['feature'][i])
h = pack['cells']['height'][i]
if f and not pack['features'][f]['land']:
i = h / 19
return 'rgb(%d, %d, %d)' % (
BIOME_COLORS[0][0] * i,
BIOME_COLORS[0][1] * i,
BIOME_COLORS[0][2] * i)
else:
i = (h - 20) / 80
return 'rgb(%d, %d, %d)' % (
lerp(COLOR_LOW[0], COLOR_HIGH[0], i),
lerp(COLOR_LOW[1], COLOR_HIGH[1], i),
lerp(COLOR_LOW[2], COLOR_HIGH[2], i))
def color_biome(i):
return 'rgb(%d, %d, %d)' % BIOME_COLORS[pack['cells']['biome'][i]]
NATION_AVG = {}
nats = list(nations.items())
for i, x in enumerate(nats):
k, v = x
lx = []
ly = []
n = 0
for y in v[1]:
lx.append(pack['cells']['coords'][y][0])
ly.append(pack['cells']['coords'][y][1])
n += 1
tx = sum(lx) / n
ty = sum(ly) / n
NATION_AVG[k] = (tx, ty)
def color_nation(i):
if pack['cells']['biome'][i] == 0:
return 'rgb(%d, %d, %d)' % BIOME_COLORS[0]
for k, v in nations.items():
if i in v[1]:
return v[0]['colour']
return 'rgb(128, 128, 128)'
def select_all():
return range(pack['cells']['num'])
COLOR = {
'height': color_height,
'biome': color_biome,
'nation': color_nation,
}
SELECT = {
'all': select_all,
}
opts = {
'color': 'height',
'select': 'all',
'width': '1000',
'height': '500',
'rivers': '1',
'legend': '1',
'show_id': '',
'nation_legends': '',
}
for x in sys.argv[1:]:
i = x.index('=')
a, b = x[:i], x[i + 1:]
opts[a] = b
svg = ET.Element(
'svg',
xmlns='http://www.w3.org/2000/svg',
width=opts['width'],
height=opts['height'])
renderer = ET.SubElement(
svg, 'svg',
preserveAspectRatio='xMinYMin meet')
min_x = min_y = max_x = max_y = None
map_elm = ET.SubElement(renderer, 'g')
id_elm = ET.Element('g')
for i in SELECT[opts['select']]():
points = []
for v in pack['cells']['vertices'][i]:
x, y = (*pack['vertices'][v],)
min_x = x if min_x is None else min(min_x, x)
min_y = y if min_y is None else min(min_y, y)
max_x = x if max_x is None else max(max_x, x)
max_y = y if max_y is None else max(max_y, y)
points.append('%s,%s' % (x, y))
ET.SubElement(
map_elm, 'polygon',
fill=COLOR[opts['color']](i),
points=' '.join(points))
if opts['show_id']:
x, y = (*pack['cells']['coords'][i],)
l = ET.SubElement(
id_elm, 'text',
x=str(x), y=str(y))
l.text = str(i)
l.set('font-size', '0.4em')
l.set('text-anchor', 'middle')
mm_x = max_x - min_x
mm_y = max_y - min_y
if opts['rivers']:
rivers_elm = ET.SubElement(renderer, 'g')
for k, river in pack['rivers'].items():
points = []
for i in river['cells']:
c = 'L' if points else 'M'
x, y = (*pack['cells']['coords'][i],)
points.append('%c%d,%d' % (c, x, y))
path = ET.SubElement(
rivers_elm, 'path',
d=' '.join(points),
stroke='rgb(%d, %d, %d)' % BIOME_COLORS[0],
fill='transparent')
path.set('stroke-width', str(river['width'] / params['pixel_size']))
if opts['show_id']:
renderer.append(id_elm)
RULER_SIZES = [1, 2, 5, 10, 50, 100, 1000]
if opts['legend']:
for x in reversed(RULER_SIZES):
ruler_size = x
if ruler_size / params['pixel_size'] < mm_x:
break
ET.SubElement(
renderer, 'rect',
x=str(min_x + 20), y=str(min_y + 20),
width=str(ruler_size / params['pixel_size']),
height='20',
stroke='white', fill='black')
ET.SubElement(
renderer, 'text',
x=str(min_x + 20), y=str(min_y + 60)) \
.text = '%d km' % ruler_size
if opts['nation_legends']:
for k, v in NATION_AVG.items():
l = ET.SubElement(
renderer, 'text',
x=str(v[0]), y=str(v[1]))
l.set('text-anchor', 'middle')
l.text = nations[k][0]['name']
renderer.set('viewBox', '%d %d %d %d' % (min_x, min_y, mm_x, mm_y))
sys.stdout.write(ET.tostring(svg, 'unicode'))