map-machine/tests/test_icons.py
2022-10-03 19:32:16 +04:00

211 lines
6.4 KiB
Python

"""
Test icon generation for nodes.
Tests check that for the given node described by tags, Map Machine generates
expected icons with expected colors.
"""
from pathlib import Path
from typing import Optional
from colour import Color
from map_machine.map_configuration import MapConfiguration
from map_machine.osm.osm_reader import Tags
from map_machine.pictogram.icon import IconSet, ShapeSpecification, Icon
from map_machine.pictogram.icon_collection import IconCollection
from tests import SCHEME, SHAPE_EXTRACTOR, workspace
__author__ = "Sergey Vartanov"
__email__ = "me@enzet.ru"
CONFIGURATION: MapConfiguration = MapConfiguration(SCHEME)
COLLECTION: IconCollection = IconCollection.from_scheme(SCHEME, SHAPE_EXTRACTOR)
DEFAULT_COLOR: Color = SCHEME.get_default_color()
EXTRA_COLOR: Color = SCHEME.get_extra_color()
WHITE: Color = Color("white")
def test_grid() -> None:
"""Test grid drawing."""
COLLECTION.draw_grid(workspace.output_path / "grid.svg")
def test_icons_by_id() -> None:
"""Test individual icons drawing."""
path: Path = workspace.get_icons_by_id_path()
COLLECTION.draw_icons(path, workspace.ICONS_LICENSE_PATH)
assert (path / "tree.svg").is_file()
assert (path / "LICENSE").is_file()
def test_icons_by_name() -> None:
"""Test drawing individual icons that have names."""
path: Path = workspace.get_icons_by_name_path()
COLLECTION.draw_icons(path, workspace.ICONS_LICENSE_PATH, by_name=True)
assert (path / "Röntgen tree.svg").is_file()
assert (path / "LICENSE").is_file()
def get_icon(tags: Tags) -> IconSet:
"""Construct icon from tags."""
processed: set[str] = set()
icon, _ = CONFIGURATION.get_icon(SHAPE_EXTRACTOR, tags, processed)
return icon
def test_no_icons() -> None:
"""
Test icon creation for tags not described in the scheme.
Tags that has no description in the scheme and should be visualized with
default shape.
"""
icon: IconSet = get_icon({"aaa": "bbb"})
assert icon.main_icon.is_default()
assert icon.main_icon.shape_specifications[0].color == DEFAULT_COLOR
def test_no_icons_but_color() -> None:
"""
Test icon creation for tags not described in the scheme and `colour` tag.
Tags that has no description in scheme, but have `colour` tag and should be
visualized with default shape with the given color.
"""
icon: IconSet = get_icon({"aaa": "bbb", "colour": "#424242"})
assert icon.main_icon.is_default()
assert icon.main_icon.shape_specifications[0].color == Color("#424242")
def check_icon_set(
tags: Tags,
main_specification: list[tuple[str, Optional[Color]]],
extra_specifications: list[list[tuple[str, Optional[Color]]]] = None,
) -> None:
"""Check icon set using simple specification."""
icon: IconSet = get_icon(tags)
if extra_specifications is None:
extra_specifications = []
if not main_specification:
assert icon.main_icon.is_default()
else:
assert not icon.main_icon.is_default()
assert len(main_specification) == len(
icon.main_icon.shape_specifications
)
for index, shape in enumerate(main_specification):
shape_specification: ShapeSpecification = (
icon.main_icon.shape_specifications[index]
)
assert shape_specification.shape.id_ == shape[0]
assert shape_specification.color == Color(shape[1])
assert len(extra_specifications) == len(icon.extra_icons)
for i, extra_specification in enumerate(extra_specifications):
extra_icon: Icon = icon.extra_icons[i]
assert len(extra_specification) == len(extra_icon.shape_specifications)
for j, shape in enumerate(extra_specification):
assert extra_icon.shape_specifications[j].shape.id_ == shape[0]
assert extra_icon.shape_specifications[j].color == Color(shape[1])
def test_icon() -> None:
"""
Tags that should be visualized with single main icon and without extra
icons.
"""
check_icon_set({"natural": "tree"}, [("tree", Color("#98AC64"))])
def test_icon_1_extra() -> None:
"""
Tags that should be visualized with single main icon and single extra icon.
"""
check_icon_set(
{"barrier": "gate", "access": "private"},
[("gate", DEFAULT_COLOR)],
[[("lock_with_keyhole", EXTRA_COLOR)]],
)
def test_icon_2_extra() -> None:
"""
Tags that should be visualized with single main icon and two extra icons.
"""
check_icon_set(
{"barrier": "gate", "access": "private", "bicycle": "yes"},
[("gate", DEFAULT_COLOR)],
[
[("bicycle", EXTRA_COLOR)],
[("lock_with_keyhole", EXTRA_COLOR)],
],
)
def test_no_icon_1_extra() -> None:
"""
Tags that should be visualized without main icon and with single extra icon.
"""
check_icon_set(
{"access": "private"}, [], [[("lock_with_keyhole", EXTRA_COLOR)]]
)
def test_no_icon_2_extra() -> None:
"""
Tags that should be visualized with default main icon and two extra icons.
"""
check_icon_set(
{"access": "private", "bicycle": "yes"},
[],
[[("bicycle", EXTRA_COLOR)], [("lock_with_keyhole", EXTRA_COLOR)]],
)
def test_icon_regex() -> None:
"""Check that simple regular expressions work properly."""
check_icon_set(
{"traffic_sign": "maxspeed", "maxspeed": "42"},
[("circle_11", DEFAULT_COLOR), ("digit_4", WHITE), ("digit_2", WHITE)],
)
def test_vending_machine() -> None:
"""
Check that specific vending machines aren't rendered with generic icon.
See https://github.com/enzet/map-machine/issues/132
"""
check_icon_set(
{"amenity": "vending_machine"},
[("vending_machine", DEFAULT_COLOR)],
)
check_icon_set(
{"amenity": "vending_machine", "vending": "drinks"},
[("vending_bottle", DEFAULT_COLOR)],
)
check_icon_set(
{"vending": "drinks"},
[("vending_bottle", DEFAULT_COLOR)],
)
def test_diving_tower() -> None:
"""
Check that diving towers are rendered as diving towers, not just
freestanding towers.
See https://github.com/enzet/map-machine/issues/138
"""
check_icon_set(
{
"man_made": "tower",
"tower:type": "diving",
"tower:construction": "freestanding",
"tower:platforms": "4",
},
[("diving_4_platforms", DEFAULT_COLOR)],
)