map-machine/roentgen/grid.py
Sergey Vartanov bb70935c19 Change scheme format; support pathlib.
Change name documentation as well.
2021-05-22 01:37:58 +03:00

141 lines
4.6 KiB
Python

"""
Icon grid drawing.
"""
from os.path import join
from pathlib import Path
from typing import Any, Dict, List, Set
import numpy as np
from colour import Color
from svgwrite import Drawing
from roentgen.icon import Icon, ShapeExtractor, ShapeSpecification
from roentgen.scheme import Scheme
__author__ = "Sergey Vartanov"
__email__ = "me@enzet.ru"
def draw_all_icons(
output_file_name: str, output_directory: str, columns: int = 16,
step: float = 24, background_color: Color = Color("white"),
color: Color = Color("black")
) -> None:
"""
Draw all possible icon combinations in grid.
:param output_file_name: output SVG file name for icon grid
:param output_directory: path to the directory to store individual SVG files
for icons
:param columns: the number of columns in grid
:param step: horizontal and vertical distance between icons
:param background_color: background color
:param color: icon color
"""
scheme: Scheme = Scheme(Path("scheme/default.yml"))
icons: List[Icon] = []
icons_file_name: str = "icons/icons.svg"
extractor: ShapeExtractor = ShapeExtractor(
Path(icons_file_name), Path("icons/config.json")
)
def add() -> None:
"""
Construct icon and add it to the list.
"""
specifications = [
ShapeSpecification.from_structure(x, extractor, scheme)
for x in current_set
]
constructed_icon: Icon = Icon(specifications)
constructed_icon.recolor(color, white=background_color)
if constructed_icon not in icons:
icons.append(constructed_icon)
for group in scheme.icons:
for element in group["tags"]: # type: Dict[str, Any]
for key in ["icon", "add_icon"]:
if key in element:
current_set = element[key]
add()
if "over_icon" not in element:
continue
if "under_icon" in element:
for icon_id in element["under_icon"]: # type: str
current_set = set([icon_id] + element["over_icon"])
add()
if not ("under_icon" in element and "with_icon" in element):
continue
for icon_id in element["under_icon"]: # type: str
for icon_2_id in element["with_icon"]: # type: str
current_set: Set[str] = set(
[icon_id] + [icon_2_id] + element["over_icon"])
add()
for icon_2_id in element["with_icon"]: # type: str
for icon_3_id in element["with_icon"]: # type: str
current_set = set(
[icon_id] + [icon_2_id] + [icon_3_id] +
element["over_icon"])
if (icon_2_id != icon_3_id and icon_2_id != icon_id and
icon_3_id != icon_id):
add()
specified_ids: Set[str] = set()
for icon in icons:
specified_ids |= icon.get_shape_ids()
print(
"Icons with no tag specification: \n " +
", ".join(sorted(extractor.shapes.keys() - specified_ids)) + "."
)
for icon in icons: # type: Icon
icon.draw_to_file(join(
output_directory, f"{' + '.join(icon.get_names())}.svg"
))
draw_grid(
output_file_name, icons, columns, step,
background_color=background_color
)
def draw_grid(
file_name: str, icons: List[Icon], columns: int = 16, step: float = 24,
background_color: Color = Color("white")
):
"""
Draw icons in the form of table
:param file_name: output SVG file name
:param icons: list of icons
:param columns: number of columns in grid
:param step: horizontal and vertical distance between icons in grid
:param background_color: background color
"""
point: np.array = np.array((step / 2, step / 2))
width: float = step * columns
height: int = int(int(len(icons) / (width / step) + 1) * step)
svg: Drawing = Drawing(file_name, (width, height))
svg.add(svg.rect((0, 0), (width, height), fill=background_color.hex))
for icon in icons:
icon: Icon
svg.add(svg.rect(
point - np.array((10, 10)), (20, 20),
fill=background_color.hex
))
icon.draw(svg, point)
point += np.array((step, 0))
if point[0] > width - 8:
point[0] = step / 2
point += np.array((0, step))
height += step
print(f"Icons: {len(icons)}.")
with open(file_name, "w") as output_file:
svg.write(output_file)