mirror of
https://github.com/enzet/map-machine.git
synced 2025-05-21 21:16:24 +02:00
Refactor text generation.
This commit is contained in:
parent
f317eba64b
commit
958a85fe0a
13 changed files with 129 additions and 126 deletions
Binary file not shown.
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 86 KiB |
BIN
doc/power.png
BIN
doc/power.png
Binary file not shown.
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 115 KiB |
|
@ -19,7 +19,7 @@ To get SVG map, just run
|
||||||
|
|
||||||
\code {python roentgen.py -b <lon1>,<lat1>,<lon2>,<lat2>} {bash}
|
\code {python roentgen.py -b <lon1>,<lat1>,<lon2>,<lat2>} {bash}
|
||||||
|
|
||||||
(e.g. \tt {python roentgen.py -b 2.284,48.86,2.29,48.865}). It will automatically download OSM data and write output map to \tt {map.svg}. For more options see \href {#map-generation} {Map Generation section}.
|
(e.g. \tt {python roentgen.py -b 2.284,48.86,2.29,48.865}). It will automatically download OSM data and write output map to \tt {map.svg}. For more options see \href {#map-generation} {Map Generation}.
|
||||||
|
|
||||||
\2 {Map features} {features}
|
\2 {Map features} {features}
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ Every way and node displayed with the random color picked for each author with \
|
||||||
|
|
||||||
\image {doc/user.png} {Author mode}
|
\image {doc/user.png} {Author mode}
|
||||||
|
|
||||||
\2 {Map generation} {map_generation}
|
\2 {Map generation} {map-generation}
|
||||||
|
|
||||||
\b {Requirements}\: Python (at least 3.8) and Python libraries (install everything using \tt {pip install -r requirements.txt}).
|
\b {Requirements}\: Python (at least 3.8) and Python libraries (install everything using \tt {pip install -r requirements.txt}).
|
||||||
|
|
||||||
|
|
BIN
doc/trees.png
BIN
doc/trees.png
Binary file not shown.
Before Width: | Height: | Size: 166 KiB After Width: | Height: | Size: 167 KiB |
|
@ -21,7 +21,7 @@ To get SVG map, just run
|
||||||
python roentgen.py -b <lon1>,<lat1>,<lon2>,<lat2>
|
python roentgen.py -b <lon1>,<lat1>,<lon2>,<lat2>
|
||||||
```
|
```
|
||||||
|
|
||||||
(e.g. `python roentgen.py -b 2.284,48.86,2.29,48.865`). It will automatically download OSM data and write output map to `map.svg`. For more options see [Map Generation section](#map-generation).
|
(e.g. `python roentgen.py -b 2.284,48.86,2.29,48.865`). It will automatically download OSM data and write output map to `map.svg`. For more options see [Map Generation](#map-generation).
|
||||||
|
|
||||||
Map features
|
Map features
|
||||||
------------
|
------------
|
||||||
|
|
|
@ -128,10 +128,11 @@ def draw_element(target: str, tags_description: str):
|
||||||
tags = dict([x.split("=") for x in tags_description.split(",")])
|
tags = dict([x.split("=") for x in tags_description.split(",")])
|
||||||
scheme = Scheme("data/tags.yml")
|
scheme = Scheme("data/tags.yml")
|
||||||
icon_extractor = IconExtractor("icons/icons.svg")
|
icon_extractor = IconExtractor("icons/icons.svg")
|
||||||
icon_set, priority = scheme.get_icon(icon_extractor, tags)
|
icon, priority = scheme.get_icon(icon_extractor, tags)
|
||||||
is_for_node: bool = target == "node"
|
is_for_node: bool = target == "node"
|
||||||
|
labels = scheme.construct_text(tags, True)
|
||||||
point = Point(
|
point = Point(
|
||||||
icon_set, tags, np.array((32, 32)), None, is_for_node=is_for_node,
|
icon, labels, tags, np.array((32, 32)), None, is_for_node=is_for_node,
|
||||||
draw_outline=is_for_node
|
draw_outline=is_for_node
|
||||||
)
|
)
|
||||||
print(point.is_for_node)
|
print(point.is_for_node)
|
||||||
|
@ -143,7 +144,7 @@ def draw_element(target: str, tags_description: str):
|
||||||
svg.add(path)
|
svg.add(path)
|
||||||
point.draw_main_shapes(svg)
|
point.draw_main_shapes(svg)
|
||||||
point.draw_extra_shapes(svg)
|
point.draw_extra_shapes(svg)
|
||||||
point.draw_texts(svg, scheme, None, True)
|
point.draw_texts(svg, None)
|
||||||
svg.write(open("test_icon.svg", "w+"))
|
svg.write(open("test_icon.svg", "w+"))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -360,8 +360,10 @@ class Constructor:
|
||||||
icon, priority = self.scheme.get_icon(
|
icon, priority = self.scheme.get_icon(
|
||||||
self.icon_extractor, line.tags, for_="line"
|
self.icon_extractor, line.tags, for_="line"
|
||||||
)
|
)
|
||||||
|
labels = self.scheme.construct_text(line.tags, True)
|
||||||
|
|
||||||
self.nodes.append(Point(
|
self.nodes.append(Point(
|
||||||
icon, line.tags, center_point, center_coordinates,
|
icon, labels, line.tags, center_point, center_coordinates,
|
||||||
is_for_node=False, priority=priority
|
is_for_node=False, priority=priority
|
||||||
))
|
))
|
||||||
|
|
||||||
|
@ -377,9 +379,10 @@ class Constructor:
|
||||||
icon_set: Icon
|
icon_set: Icon
|
||||||
icon_set, priority = self.scheme.get_icon(
|
icon_set, priority = self.scheme.get_icon(
|
||||||
self.icon_extractor, line.tags)
|
self.icon_extractor, line.tags)
|
||||||
|
labels = self.scheme.construct_text(line.tags, True)
|
||||||
|
|
||||||
self.nodes.append(Point(
|
self.nodes.append(Point(
|
||||||
icon_set, line.tags, center_point, center_coordinates,
|
icon_set, labels, line.tags, center_point, center_coordinates,
|
||||||
is_for_node=False, priority=priority))
|
is_for_node=False, priority=priority))
|
||||||
|
|
||||||
def construct_relations(self) -> None:
|
def construct_relations(self) -> None:
|
||||||
|
@ -448,14 +451,16 @@ class Constructor:
|
||||||
icon_set = Icon([dot], [], color, set(), True)
|
icon_set = Icon([dot], [], color, set(), True)
|
||||||
priority = 0
|
priority = 0
|
||||||
draw_outline = False
|
draw_outline = False
|
||||||
|
labels = []
|
||||||
else:
|
else:
|
||||||
icon_set, priority = self.scheme.get_icon(
|
icon_set, priority = self.scheme.get_icon(
|
||||||
self.icon_extractor, tags
|
self.icon_extractor, tags
|
||||||
)
|
)
|
||||||
|
labels = self.scheme.construct_text(tags, True)
|
||||||
|
|
||||||
self.nodes.append(Point(
|
self.nodes.append(Point(
|
||||||
icon_set, tags, flung, node.coordinates, priority=priority,
|
icon_set, labels, tags, flung, node.coordinates,
|
||||||
draw_outline=draw_outline
|
priority=priority, draw_outline=draw_outline
|
||||||
))
|
))
|
||||||
|
|
||||||
missing_tags.update(
|
missing_tags.update(
|
||||||
|
|
|
@ -71,7 +71,8 @@ def draw_all_icons(
|
||||||
specified_ids |= icons_to_draw
|
specified_ids |= icons_to_draw
|
||||||
print(
|
print(
|
||||||
"Icons with no tag specification: \n " +
|
"Icons with no tag specification: \n " +
|
||||||
", ".join(sorted(extractor.icons.keys() - specified_ids)) + ".")
|
", ".join(sorted(extractor.icons.keys() - specified_ids)) + "."
|
||||||
|
)
|
||||||
|
|
||||||
draw_grid(
|
draw_grid(
|
||||||
output_file_name, to_draw, extractor, output_directory, columns, step
|
output_file_name, to_draw, extractor, output_directory, columns, step
|
||||||
|
@ -79,10 +80,10 @@ def draw_all_icons(
|
||||||
|
|
||||||
|
|
||||||
def draw_grid(
|
def draw_grid(
|
||||||
file_name: str, combined_icon_ids: List[Set[str]],
|
file_name: str, combined_icon_ids: List[Set[str]],
|
||||||
extractor: IconExtractor, output_directory: str, columns: int = 16,
|
extractor: IconExtractor, output_directory: str, columns: int = 16,
|
||||||
step: float = 24, color=Color("#444444")
|
step: float = 24, color=Color("#444444")
|
||||||
) -> List[List[Shape]]:
|
) -> List[List[Shape]]:
|
||||||
"""
|
"""
|
||||||
Draw icons in the form of table
|
Draw icons in the form of table
|
||||||
|
|
||||||
|
|
|
@ -244,20 +244,19 @@ class Painter:
|
||||||
)
|
)
|
||||||
node.draw_main_shapes(self.svg, occupied)
|
node.draw_main_shapes(self.svg, occupied)
|
||||||
|
|
||||||
for index, node in enumerate(nodes): # type: int, Point
|
for index, point in enumerate(nodes): # type: int, Point
|
||||||
ui.progress_bar(
|
ui.progress_bar(
|
||||||
steps + index, steps * 3, step=10, text="Drawing extra icons"
|
steps + index, steps * 3, step=10, text="Drawing extra icons"
|
||||||
)
|
)
|
||||||
node.draw_extra_shapes(self.svg, occupied)
|
point.draw_extra_shapes(self.svg, occupied)
|
||||||
|
|
||||||
for index, node in enumerate(nodes): # type: int, Point
|
for index, point in enumerate(nodes): # type: int, Point
|
||||||
ui.progress_bar(
|
ui.progress_bar(
|
||||||
steps * 2 + index, steps * 3, step=10, text="Drawing texts"
|
steps * 2 + index, steps * 3, step=10, text="Drawing texts"
|
||||||
)
|
)
|
||||||
if (self.mode not in [CREATION_TIME_MODE, AUTHOR_MODE] and
|
if (self.mode not in [CREATION_TIME_MODE, AUTHOR_MODE] and
|
||||||
self.draw_captions != "no"):
|
self.draw_captions != "no"):
|
||||||
node.draw_texts(
|
point.draw_texts(self.svg, occupied)
|
||||||
self.svg, self.scheme, occupied, self.draw_captions)
|
|
||||||
|
|
||||||
ui.progress_bar(-1, len(nodes), step=10, text="Drawing nodes")
|
ui.progress_bar(-1, len(nodes), step=10, text="Drawing nodes")
|
||||||
|
|
||||||
|
|
|
@ -8,22 +8,10 @@ from colour import Color
|
||||||
from roentgen.color import is_bright
|
from roentgen.color import is_bright
|
||||||
from roentgen.icon import Shape
|
from roentgen.icon import Shape
|
||||||
from roentgen.osm_reader import Tagged
|
from roentgen.osm_reader import Tagged
|
||||||
from roentgen.scheme import Icon, Scheme
|
from roentgen.scheme import Icon
|
||||||
from roentgen.text import get_address, get_text
|
from roentgen.text import Label
|
||||||
|
|
||||||
DEFAULT_FONT: str = "Roboto"
|
DEFAULT_FONT: str = "Roboto"
|
||||||
DEFAULT_COLOR: Color = Color("#444444")
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class TextStruct:
|
|
||||||
"""
|
|
||||||
Some label on the map with attributes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
text: str
|
|
||||||
fill: Color = DEFAULT_COLOR
|
|
||||||
size: float = 10.0
|
|
||||||
|
|
||||||
|
|
||||||
class Occupied:
|
class Occupied:
|
||||||
|
@ -44,87 +32,6 @@ class Occupied:
|
||||||
assert self.matrix[point[0], point[1]] == True
|
assert self.matrix[point[0], point[1]] == True
|
||||||
|
|
||||||
|
|
||||||
def construct_text(
|
|
||||||
tags, processed, scheme, draw_captions) -> List["TextStruct"]:
|
|
||||||
"""
|
|
||||||
Construct labels for not processed tags.
|
|
||||||
"""
|
|
||||||
texts: List[TextStruct] = []
|
|
||||||
|
|
||||||
name = None
|
|
||||||
alt_name = None
|
|
||||||
if "name" in tags:
|
|
||||||
name = tags["name"]
|
|
||||||
tags.pop("name", None)
|
|
||||||
if "name:ru" in tags:
|
|
||||||
if not name:
|
|
||||||
name = tags["name:ru"]
|
|
||||||
tags.pop("name:ru", None)
|
|
||||||
tags.pop("name:ru", None)
|
|
||||||
if "name:en" in tags:
|
|
||||||
if not name:
|
|
||||||
name = tags["name:en"]
|
|
||||||
tags.pop("name:en", None)
|
|
||||||
tags.pop("name:en", None)
|
|
||||||
if "alt_name" in tags:
|
|
||||||
if alt_name:
|
|
||||||
alt_name += ", "
|
|
||||||
else:
|
|
||||||
alt_name = ""
|
|
||||||
alt_name += tags["alt_name"]
|
|
||||||
tags.pop("alt_name")
|
|
||||||
if "old_name" in tags:
|
|
||||||
if alt_name:
|
|
||||||
alt_name += ", "
|
|
||||||
else:
|
|
||||||
alt_name = ""
|
|
||||||
alt_name += "ex " + tags["old_name"]
|
|
||||||
|
|
||||||
address: List[str] = get_address(tags, draw_captions)
|
|
||||||
|
|
||||||
if name:
|
|
||||||
texts.append(TextStruct(name, Color("black")))
|
|
||||||
if alt_name:
|
|
||||||
texts.append(TextStruct(f"({alt_name})"))
|
|
||||||
if address:
|
|
||||||
texts.append(TextStruct(", ".join(address)))
|
|
||||||
|
|
||||||
if draw_captions == "main":
|
|
||||||
return texts
|
|
||||||
|
|
||||||
for text in get_text(tags): # type: str
|
|
||||||
if text:
|
|
||||||
texts.append(TextStruct(text))
|
|
||||||
|
|
||||||
if "route_ref" in tags:
|
|
||||||
texts.append(TextStruct(tags["route_ref"].replace(";", " ")))
|
|
||||||
tags.pop("route_ref", None)
|
|
||||||
if "cladr:code" in tags:
|
|
||||||
texts.append(TextStruct(tags["cladr:code"], size=7))
|
|
||||||
tags.pop("cladr:code", None)
|
|
||||||
if "website" in tags:
|
|
||||||
link = tags["website"]
|
|
||||||
if link[:7] == "http://":
|
|
||||||
link = link[7:]
|
|
||||||
if link[:8] == "https://":
|
|
||||||
link = link[8:]
|
|
||||||
if link[:4] == "www.":
|
|
||||||
link = link[4:]
|
|
||||||
if link[-1] == "/":
|
|
||||||
link = link[:-1]
|
|
||||||
link = link[:25] + ("..." if len(tags["website"]) > 25 else "")
|
|
||||||
texts.append(TextStruct(link, Color("#000088")))
|
|
||||||
tags.pop("website", None)
|
|
||||||
for k in ["phone"]:
|
|
||||||
if k in tags:
|
|
||||||
texts.append(TextStruct(tags[k], Color("#444444")))
|
|
||||||
tags.pop(k)
|
|
||||||
for tag in tags:
|
|
||||||
if scheme.is_writable(tag) and not (tag in processed):
|
|
||||||
texts.append(TextStruct(tags[tag]))
|
|
||||||
return texts
|
|
||||||
|
|
||||||
|
|
||||||
def in_range(position, points) -> bool:
|
def in_range(position, points) -> bool:
|
||||||
return 0 <= position[0] < len(points) and 0 <= position[1] < len(points[0])
|
return 0 <= position[0] < len(points) and 0 <= position[1] < len(points[0])
|
||||||
|
|
||||||
|
@ -137,8 +44,8 @@ class Point(Tagged):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, icon: Icon, tags: Dict[str, str], point: np.array,
|
self, icon: Icon, labels: List[Label], tags: Dict[str, str],
|
||||||
coordinates: np.array, priority: float = 0,
|
point: np.array, coordinates: np.array, priority: float = 0,
|
||||||
is_for_node: bool = True, draw_outline: bool = True
|
is_for_node: bool = True, draw_outline: bool = True
|
||||||
):
|
):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
@ -146,6 +53,7 @@ class Point(Tagged):
|
||||||
assert point is not None
|
assert point is not None
|
||||||
|
|
||||||
self.icon: Icon = icon
|
self.icon: Icon = icon
|
||||||
|
self.labels: List[Label] = labels
|
||||||
self.tags: Dict[str, str] = tags
|
self.tags: Dict[str, str] = tags
|
||||||
self.point: np.array = point
|
self.point: np.array = point
|
||||||
self.coordinates: np.array = coordinates
|
self.coordinates: np.array = coordinates
|
||||||
|
@ -241,16 +149,11 @@ class Point(Tagged):
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def draw_texts(
|
def draw_texts(self, svg: svgwrite.Drawing, occupied: Occupied) -> None:
|
||||||
self, svg: svgwrite.Drawing, scheme: Scheme, occupied: Occupied,
|
|
||||||
draw_captions):
|
|
||||||
"""
|
"""
|
||||||
Draw all labels.
|
Draw all labels.
|
||||||
"""
|
"""
|
||||||
text_structures: List[TextStruct] = construct_text(
|
for text_struct in self.labels: # type: Label
|
||||||
self.tags, self.icon.processed, scheme, draw_captions)
|
|
||||||
|
|
||||||
for text_struct in text_structures: # type: TextStruct
|
|
||||||
text = text_struct.text
|
text = text_struct.text
|
||||||
text = text.replace(""", '"')
|
text = text.replace(""", '"')
|
||||||
text = text.replace("&", '&')
|
text = text.replace("&", '&')
|
||||||
|
|
|
@ -12,6 +12,7 @@ import yaml
|
||||||
from colour import Color
|
from colour import Color
|
||||||
|
|
||||||
from roentgen.icon import DEFAULT_SHAPE_ID, Shape, IconExtractor
|
from roentgen.icon import DEFAULT_SHAPE_ID, Shape, IconExtractor
|
||||||
|
from roentgen.text import Label, get_address, get_text
|
||||||
|
|
||||||
DEFAULT_COLOR: Color = Color("#444444")
|
DEFAULT_COLOR: Color = Color("#444444")
|
||||||
|
|
||||||
|
@ -299,6 +300,85 @@ class Scheme:
|
||||||
|
|
||||||
return line_styles
|
return line_styles
|
||||||
|
|
||||||
|
def construct_text(self, tags, draw_captions) -> List[Label]:
|
||||||
|
"""
|
||||||
|
Construct labels for not processed tags.
|
||||||
|
"""
|
||||||
|
texts: List[Label] = []
|
||||||
|
|
||||||
|
name = None
|
||||||
|
alt_name = None
|
||||||
|
if "name" in tags:
|
||||||
|
name = tags["name"]
|
||||||
|
tags.pop("name", None)
|
||||||
|
if "name:ru" in tags:
|
||||||
|
if not name:
|
||||||
|
name = tags["name:ru"]
|
||||||
|
tags.pop("name:ru", None)
|
||||||
|
tags.pop("name:ru", None)
|
||||||
|
if "name:en" in tags:
|
||||||
|
if not name:
|
||||||
|
name = tags["name:en"]
|
||||||
|
tags.pop("name:en", None)
|
||||||
|
tags.pop("name:en", None)
|
||||||
|
if "alt_name" in tags:
|
||||||
|
if alt_name:
|
||||||
|
alt_name += ", "
|
||||||
|
else:
|
||||||
|
alt_name = ""
|
||||||
|
alt_name += tags["alt_name"]
|
||||||
|
tags.pop("alt_name")
|
||||||
|
if "old_name" in tags:
|
||||||
|
if alt_name:
|
||||||
|
alt_name += ", "
|
||||||
|
else:
|
||||||
|
alt_name = ""
|
||||||
|
alt_name += "ex " + tags["old_name"]
|
||||||
|
|
||||||
|
address: List[str] = get_address(tags, draw_captions)
|
||||||
|
|
||||||
|
if name:
|
||||||
|
texts.append(Label(name, Color("black")))
|
||||||
|
if alt_name:
|
||||||
|
texts.append(Label(f"({alt_name})"))
|
||||||
|
if address:
|
||||||
|
texts.append(Label(", ".join(address)))
|
||||||
|
|
||||||
|
if draw_captions == "main":
|
||||||
|
return texts
|
||||||
|
|
||||||
|
for text in get_text(tags): # type: str
|
||||||
|
if text:
|
||||||
|
texts.append(Label(text))
|
||||||
|
|
||||||
|
if "route_ref" in tags:
|
||||||
|
texts.append(Label(tags["route_ref"].replace(";", " ")))
|
||||||
|
tags.pop("route_ref", None)
|
||||||
|
if "cladr:code" in tags:
|
||||||
|
texts.append(Label(tags["cladr:code"], size=7))
|
||||||
|
tags.pop("cladr:code", None)
|
||||||
|
if "website" in tags:
|
||||||
|
link = tags["website"]
|
||||||
|
if link[:7] == "http://":
|
||||||
|
link = link[7:]
|
||||||
|
if link[:8] == "https://":
|
||||||
|
link = link[8:]
|
||||||
|
if link[:4] == "www.":
|
||||||
|
link = link[4:]
|
||||||
|
if link[-1] == "/":
|
||||||
|
link = link[:-1]
|
||||||
|
link = link[:25] + ("..." if len(tags["website"]) > 25 else "")
|
||||||
|
texts.append(Label(link, Color("#000088")))
|
||||||
|
tags.pop("website", None)
|
||||||
|
for k in ["phone"]:
|
||||||
|
if k in tags:
|
||||||
|
texts.append(Label(tags[k], Color("#444444")))
|
||||||
|
tags.pop(k)
|
||||||
|
for tag in tags:
|
||||||
|
if self.is_writable(tag):
|
||||||
|
texts.append(Label(tags[tag]))
|
||||||
|
return texts
|
||||||
|
|
||||||
def is_area(self, tags: Dict[str, str]) -> bool:
|
def is_area(self, tags: Dict[str, str]) -> bool:
|
||||||
for matcher in self.area_tags:
|
for matcher in self.area_tags:
|
||||||
if is_matched(matcher, tags):
|
if is_matched(matcher, tags):
|
||||||
|
|
|
@ -3,8 +3,22 @@ OSM address tag processing.
|
||||||
|
|
||||||
Author: Sergey Vartanov (me@enzet.ru).
|
Author: Sergey Vartanov (me@enzet.ru).
|
||||||
"""
|
"""
|
||||||
|
from dataclasses import dataclass
|
||||||
from typing import Any, Dict, List
|
from typing import Any, Dict, List
|
||||||
|
|
||||||
|
from colour import Color
|
||||||
|
DEFAULT_COLOR: Color = Color("#444444")
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Label:
|
||||||
|
"""
|
||||||
|
Text label.
|
||||||
|
"""
|
||||||
|
text: str
|
||||||
|
fill: Color = DEFAULT_COLOR
|
||||||
|
size: float = 10.0
|
||||||
|
|
||||||
|
|
||||||
def get_address(tags: Dict[str, Any], draw_captions_mode: str) -> List[str]:
|
def get_address(tags: Dict[str, Any], draw_captions_mode: str) -> List[str]:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -61,7 +61,7 @@ def test_icon_2_extra() -> None:
|
||||||
|
|
||||||
def __test_no_icon_1_extra() -> None:
|
def __test_no_icon_1_extra() -> None:
|
||||||
"""
|
"""
|
||||||
Tags that should be visualized with defult main icon and single extra icon.
|
Tags that should be visualized with default main icon and single extra icon.
|
||||||
"""
|
"""
|
||||||
icon = get_icon({"access": "private"})
|
icon = get_icon({"access": "private"})
|
||||||
assert icon.main_icon[0].is_default()
|
assert icon.main_icon[0].is_default()
|
||||||
|
@ -70,7 +70,7 @@ def __test_no_icon_1_extra() -> None:
|
||||||
|
|
||||||
def __test_no_icon_2_extra() -> None:
|
def __test_no_icon_2_extra() -> None:
|
||||||
"""
|
"""
|
||||||
Tags that should be visualized with defult main icon and two extra icons.
|
Tags that should be visualized with default main icon and two extra icons.
|
||||||
"""
|
"""
|
||||||
icon = get_icon({"access": "private", "bicycle": "yes"})
|
icon = get_icon({"access": "private", "bicycle": "yes"})
|
||||||
assert icon.main_icon[0].is_default()
|
assert icon.main_icon[0].is_default()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue