Add icon collection class.

This commit is contained in:
Sergey Vartanov 2021-06-10 00:07:52 +03:00
parent 9fd2d869ff
commit 3bb6439d7b
4 changed files with 138 additions and 121 deletions

View file

@ -14,7 +14,7 @@ import svgwrite
from roentgen.constructor import Constructor
from roentgen.flinger import Flinger
from roentgen.grid import draw_all_icons
from roentgen.grid import IconCollection
from roentgen.icon import ShapeExtractor
from roentgen.mapper import (
AUTHOR_MODE, CREATION_TIME_MODE, ICONS_FILE_NAME, Painter, TAGS_FILE_NAME,
@ -158,22 +158,25 @@ def draw_element(target: str, tags_description: str):
svg.write(open("test_icon.svg", "w+"))
def draw_grid() -> None:
def draw_icons() -> None:
"""
Draw all possible icon shapes combinations as grid.
Draw all possible icon shapes combinations as grid in one SVG file and as
individual SVG files.
"""
os.makedirs("icon_set", exist_ok=True)
scheme: Scheme = Scheme(Path("scheme/default.yml"))
extractor: ShapeExtractor = ShapeExtractor(
Path("icons/icons.svg"), Path("icons/config.json")
)
draw_all_icons(scheme, extractor, "icon_grid.svg", "icon_set")
collection: IconCollection = IconCollection.from_scheme(scheme, extractor)
collection.draw_grid(Path("icon_grid.svg"))
collection.draw_icons(Path("icon_set"))
if __name__ == "__main__":
if len(sys.argv) == 3 and sys.argv[1] in ["node", "way", "area"]:
draw_element(sys.argv[1], sys.argv[2])
elif len(sys.argv) == 2 and sys.argv[1] == "grid":
draw_grid()
elif len(sys.argv) == 2 and sys.argv[1] == "icons":
draw_icons()
else:
main(sys.argv)

View file

@ -1,7 +1,7 @@
"""
Icon grid drawing.
"""
from os.path import join
from pathlib import Path
from typing import List, Set
import numpy as np
@ -15,125 +15,130 @@ __author__ = "Sergey Vartanov"
__email__ = "me@enzet.ru"
def draw_all_icons(
scheme: Scheme, extractor: ShapeExtractor,
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.
class IconCollection:
def __init__(self, icons):
self.icons: List[Icon] = icons
:param scheme: tag specification
:param extractor: shape extractor for icon creation
: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
"""
icons: List[Icon] = []
def add() -> None:
@classmethod
def from_scheme(
cls,
scheme: Scheme,
extractor: ShapeExtractor,
background_color: Color = Color("white"),
color: Color = Color("black")
) -> "IconCollection":
"""
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)
Draw all possible icon combinations in grid.
for matcher in scheme.node_matchers:
if matcher.shapes:
current_set = matcher.shapes
add()
if matcher.add_shapes:
current_set = matcher.add_shapes
add()
if not matcher.over_icon:
continue
if matcher.under_icon:
:param scheme: tag specification
:param extractor: shape extractor for icon creation
:param background_color: background color
:param color: icon color
"""
icons: List[Icon] = []
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 matcher in scheme.node_matchers:
if matcher.shapes:
current_set = matcher.shapes
add()
if matcher.add_shapes:
current_set = matcher.add_shapes
add()
if not matcher.over_icon:
continue
if matcher.under_icon:
for icon_id in matcher.under_icon:
current_set = [icon_id] + matcher.over_icon
add()
if not (matcher.under_icon and matcher.with_icon):
continue
for icon_id in matcher.under_icon:
current_set = [icon_id] + matcher.over_icon
add()
if not (matcher.under_icon and matcher.with_icon):
continue
for icon_id in matcher.under_icon:
for icon_2_id in matcher.with_icon:
current_set: List[str] = (
[icon_id] + [icon_2_id] + matcher.over_icon
)
add()
for icon_2_id in matcher.with_icon:
for icon_3_id in matcher.with_icon:
current_set = (
[icon_id] + [icon_2_id] + [icon_3_id] +
matcher.over_icon
for icon_2_id in matcher.with_icon:
current_set: List[str] = (
[icon_id] + [icon_2_id] + matcher.over_icon
)
if (icon_2_id != icon_3_id and icon_2_id != icon_id and
icon_3_id != icon_id):
add()
add()
for icon_2_id in matcher.with_icon:
for icon_3_id in matcher.with_icon:
current_set = (
[icon_id] + [icon_2_id] + [icon_3_id] +
matcher.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()
specified_ids: Set[str] = set()
for icon in icons:
specified_ids |= set(icon.get_shape_ids())
print(
"Icons with no tag specification: \n " +
", ".join(sorted(extractor.shapes.keys() - specified_ids)) + "."
)
for icon in icons:
specified_ids |= set(icon.get_shape_ids())
print(
"Icons with no tag specification: \n " +
", ".join(sorted(extractor.shapes.keys() - specified_ids)) + "."
)
return cls(icons)
for icon in icons:
icon.draw_to_file(join(
output_directory, f"{' + '.join(icon.get_names())}.svg"
))
def draw_icons(self, output_directory: Path):
"""
:param output_directory: path to the directory to store individual SVG files
for icons
"""
for icon in self.icons:
icon.draw_to_file(
output_directory / f"{'___'.join(icon.get_shape_ids())}.svg"
)
draw_grid(
output_file_name, sorted(icons), columns, step,
background_color=background_color
)
def draw_grid(
self,
file_name: Path,
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 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
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
height: int = int(int(len(self.icons) / (width / step) + 1) * step)
svg: Drawing = Drawing(str(file_name), (width, height))
svg.add(svg.rect((0, 0), (width, height), fill=background_color.hex))
: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
for icon in self.icons:
icon: Icon
rectangle = svg.rect(
point - np.array((10, 10)), (20, 20),
fill=background_color.hex
)
svg.add(rectangle)
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
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))
with open(file_name, "w") as output_file:
svg.write(output_file)
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)
def __len__(self) -> int:
return len(self.icons)

View file

@ -323,13 +323,13 @@ class Icon:
for shape_specification in self.shape_specifications:
shape_specification.draw(svg, point, tags, outline)
def draw_to_file(self, file_name: str):
def draw_to_file(self, file_name: Path):
"""
Draw icon to the SVG file.
:param file_name: output SVG file name
"""
svg: Drawing = Drawing(file_name, (16, 16))
svg: Drawing = Drawing(str(file_name), (16, 16))
for shape_specification in self.shape_specifications:
shape_specification.draw(svg, (8, 8))

View file

@ -1,11 +1,11 @@
"""
Test icon generation for nodes.
"""
from os import makedirs
from pathlib import Path
from typing import Dict
from roentgen.icon import IconSet
from roentgen.grid import draw_all_icons
from roentgen.grid import IconCollection
from test import SCHEME, SHAPE_EXTRACTOR
__author__ = "Sergey Vartanov"
@ -16,8 +16,17 @@ def test_icons() -> None:
"""
Test grid drawing.
"""
makedirs("icon_set", exist_ok=True)
draw_all_icons(SCHEME, SHAPE_EXTRACTOR, "temp.svg", "icon_set")
temp_directory: Path = Path("temp")
temp_directory.mkdir(exist_ok=True)
set_directory: Path = temp_directory / "icon_set"
set_directory.mkdir(exist_ok=True)
collection: IconCollection = IconCollection.from_scheme(
SCHEME, SHAPE_EXTRACTOR
)
collection.draw_grid(temp_directory / "grid.svg")
collection.draw_icons(set_directory)
def get_icon(tags: Dict[str, str]) -> IconSet: