#!/usr/bin/env python3 import argparse import cv2 import pathlib import numpy import os from typing import MutableMapping import yaml MAP_ROOT = pathlib.Path(os.getcwd()) TILES_DIR = MAP_ROOT / '../assets/tiles' SHOW_MAP = False def get_tile_path(tile: str) -> pathlib.Path: """Return the corresponding image file name for a tile""" return TILES_DIR / f'{tile.lower().replace(" ", "_")}.png' def generate_img(map_path: pathlib.Path): """Generate a image from a map file""" with open(map_path, 'r') as map_file: map_definition = yaml.full_load(map_file) # remove the trailing new line map_string = map_definition['map'][:-1] # ensure that all keys are actually strings symbols = {str(k): v for k, v in map_definition['symbols'].items()} # build up tiles tiles = [] for line in map_string.splitlines(): row = [] for symbol in line: tile = "neutral" if symbol != ' ': if symbol not in symbols: print(f'WARNING unknown symbol "{symbol}"') else: tile = symbols[symbol] row.append(tile) tiles.append(row) rows_imgs = [] for i, row in enumerate(tiles): tile_imgs = [] for j, tile in enumerate(row): # find the right street and rotation if tile == 'street': # check continuations left = j > 1 and row[j - 1] == 'street' right = j < len(row) - 1 and row[j + 1] == 'street' above = i > 1 and tiles[i - 1][j] == 'street' below = i < len(tiles) - 1 and tiles[i + 1][j] == 'street' connections = len( [b for b in [left, right, above, below] if b == True]) # straight lines if connections == 1 or (connections == 2 and ((left and right) or (above and below))): tile_img = cv2.imread(str(get_tile_path('street'))) if above or below: tile_img = numpy.rot90(tile_img) # elbow elif connections == 2: # normal orientation above and right tile_img = cv2.imread(str(get_tile_path('street_2'))) if right and below: tile_img = numpy.rot90(tile_img, 3) elif left and below: tile_img = numpy.rot90(tile_img, 2) elif above and left: tile_img = numpy.rot90(tile_img) elif connections == 3: # normal orientation left above right tile_img = cv2.imread(str(get_tile_path('street_3'))) if above and right and below: tile_img = numpy.rot90(tile_img, 3) elif left and below and right: tile_img = numpy.rot90(tile_img, 2) elif below and left and above: tile_img = numpy.rot90(tile_img) elif connections == 4: tile_img = cv2.imread(str(get_tile_path('street_4'))) else: tile_img = cv2.imread(str(get_tile_path(tile))) tile_imgs.append(tile_img) row_img = cv2.hconcat(tile_imgs) rows_imgs.append(row_img) map_img = cv2.vconcat(rows_imgs) if SHOW_MAP: cv2.imshow(f'{map_path.stem}.png', map_img) cv2.waitKey(0) cv2.imwrite(f'{map_path.stem}.png', map_img) def main(): """Generate map images from map files""" parser = argparse.ArgumentParser( description='generate latex standalone cards') parser.add_argument('map_input', help='map file or directory containing map files') parser.add_argument('--map-root', help='path to the map root directory') parser.add_argument('--show-map', help='show the generated map', action='store_true') args = parser.parse_args() if args.map_root: global MAP_ROOT MAP_ROOT = pathlib.Path(args.latex_root) global TILES_DIR TILES_DIR = MAP_ROOT / '../assets/tiles' if args.show_map: global SHOW_MAP SHOW_MAP = True map_path = pathlib.Path(args.map_input) map_files = [map_path] if map_path.is_dir(): map_files = map_path.glob('*.yml') for m in map_files: generate_img(m) if __name__ == '__main__': main()