Get use of JSON icon collections; refactor.

This commit is contained in:
Sergey Vartanov 2021-11-27 21:01:59 +03:00
parent 6cc840a0d9
commit 592e36762a

View file

@ -1,6 +1,7 @@
""" """
Special icon collections for documentation. Special icon collections for documentation.
""" """
import json
from dataclasses import dataclass, field from dataclasses import dataclass, field
from pathlib import Path from pathlib import Path
from typing import Optional from typing import Optional
@ -26,23 +27,92 @@ EXTRACTOR: ShapeExtractor = ShapeExtractor(
@dataclass @dataclass
class SVGTable: class Collection:
"""Icon collection."""
page_name: str
# Core tags
tags: Tags
# Tag key to be used in rows
row_key: Optional[str] = None
# List of tag values to be used in rows
row_values: list[str] = field(default_factory=list)
# Tag key to be used in columns
column_key: Optional[str] = None
# List of tag values to be used in columns
column_values: list[str] = field(default_factory=list)
def generate_wiki_table(self) -> tuple[str, list[Icon]]:
"""
Generate Röntgen icon table for the OpenStreetMap wiki page.
"""
icons: list[Icon] = []
text: str = '{| class="wikitable"\n'
if self.column_key is not None:
text += f"! {{{{Key|{self.column_key}}}}}"
else:
text += "! Tag || Icon"
if not self.column_values:
self.column_values = [""]
else:
for column_value in self.column_values:
text += " ||"
if column_value:
text += (
" {{vert header|"
f"{{{{TagValue|{self.column_key}|{column_value}}}}}"
"}}"
)
text += "\n"
processed: set[str] = set()
for row_value in self.row_values:
text += "|-\n"
if row_value:
text += f"| {{{{Tag|{self.row_key}|{row_value}}}}}\n"
else:
text += "|\n"
for column_value in self.column_values:
current_tags: Tags = dict(self.tags) | {self.row_key: row_value}
if column_value:
current_tags |= {self.column_key: column_value}
icon, _ = SCHEME.get_icon(
EXTRACTOR, current_tags, processed, MapConfiguration()
)
if not icon:
print("Icon was not constructed.")
text += (
"| "
f"[[Image:Röntgen {icon.main_icon.get_name()}.svg|32px]]\n"
)
icons.append(icon.main_icon)
text += "|}\n"
return text, icons
class SVGTable(Collection):
"""SVG table with icon combinations.""" """SVG table with icon combinations."""
def __init__( def __init__(
self, self,
svg: svgwrite.Drawing, svg: svgwrite.Drawing,
row_key: Optional[str], page_name: str,
row_values: list[str], tags: Tags,
column_key: Optional[str], row_key: Optional[str] = None,
column_values: list[str], row_values: list[str] = field(default_factory=list),
column_key: Optional[str] = None,
column_values: list[str] = field(default_factory=list),
): ):
self.svg: svgwrite.Drawing = svg super().__init__(
page_name, tags, row_key, row_values, column_key, column_values
)
self.row_key: Optional[str] = row_key self.svg: svgwrite.Drawing = svg
self.row_values: list[str] = row_values
self.column_key: Optional[str] = column_key
self.column_values: list[str] = column_values
self.border: np.ndarray = np.array((16.0, 16.0)) self.border: np.ndarray = np.array((16.0, 16.0))
self.step: float = 48.0 self.step: float = 48.0
@ -84,13 +154,49 @@ class SVGTable:
2 * self.border + np.array(self.size) + self.half_step 2 * self.border + np.array(self.size) + self.half_step
) )
def draw(self) -> None: def draw_table(self) -> None:
"""Draw rows and columns.""" """Draw SVG table."""
self.draw_rows() self.draw_rows()
self.draw_columns() self.draw_columns()
self.draw_delimiter() self.draw_delimiter()
self.draw_rectangle() self.draw_rectangle()
for i, row_value in enumerate(self.row_values):
for j, column_value in enumerate(
(self.column_values if self.column_values else [""])
):
current_tags: Tags = dict(self.tags) | {self.row_key: row_value}
if column_value:
current_tags |= {self.column_key: column_value}
processed: set[str] = set()
icon, _ = SCHEME.get_icon(
EXTRACTOR, current_tags, processed, MapConfiguration()
)
processed = icon.processed
if not icon:
print("Icon was not constructed.")
if (
icon.main_icon
and not icon.main_icon.is_default()
and (
not self.column_key
or not column_value
or (self.column_key in processed)
)
and (
not self.row_key
or not row_value
or (self.row_key in processed)
)
):
self.draw_icon(np.array((j, i)), icon)
else:
self.draw_cross(np.array((j, i)))
width, height = self.get_size()
self.svg.update({"width": width, "height": height})
def draw_rows(self) -> None: def draw_rows(self) -> None:
"""Draw row texts.""" """Draw row texts."""
point: np.ndarray = np.array(self.start_point) - np.array( point: np.ndarray = np.array(self.start_point) - np.array(
@ -209,243 +315,32 @@ class SVGTable:
) )
@dataclass
class Collection:
"""Icon collection."""
page_name: str
# Core tags
tags: Tags
# Tag key to be used in rows
row_key: Optional[str] = None
# List of tag values to be used in rows
row_values: list[str] = field(default_factory=list)
# Tag key to be used in columns
column_key: Optional[str] = None
# List of tag values to be used in columns
column_values: list[str] = field(default_factory=list)
def generate_wiki_table(self) -> tuple[str, list[Icon]]:
"""
Generate Röntgen icon table for the OpenStreetMap wiki page.
"""
icons: list[Icon] = []
text: str = '{| class="wikitable"\n'
if self.column_key is not None:
text += f"! {{{{Key|{self.column_key}}}}}"
else:
text += "! Tag || Icon"
if not self.column_values:
self.column_values = [""]
else:
for column_value in self.column_values:
text += " ||"
if column_value:
text += (
" {{vert header|"
f"{{{{TagValue|{self.column_key}|{column_value}}}}}"
"}}"
)
text += "\n"
processed: set[str] = set()
for row_value in self.row_values:
text += "|-\n"
if row_value:
text += f"| {{{{Tag|{self.row_key}|{row_value}}}}}\n"
else:
text += "|\n"
for column_value in self.column_values:
current_tags: Tags = dict(self.tags) | {self.row_key: row_value}
if column_value:
current_tags |= {self.column_key: column_value}
icon, _ = SCHEME.get_icon(
EXTRACTOR, current_tags, processed, MapConfiguration()
)
if not icon:
print("Icon was not constructed.")
text += (
"| "
f"[[Image:Röntgen {icon.main_icon.get_name()}.svg|32px]]\n"
)
icons.append(icon.main_icon)
text += "|}\n"
return text, icons
def draw_table(self, svg: Drawing) -> np.ndarray:
"""Draw SVG table."""
table: SVGTable = SVGTable(
svg,
self.row_key + "=*" if self.row_key else None,
self.row_values,
self.column_key + "=*" if self.column_key else None,
self.column_values,
)
table.draw()
for i, row_value in enumerate(self.row_values):
for j, column_value in enumerate(
(self.column_values if self.column_values else [""])
):
current_tags: Tags = dict(self.tags) | {self.row_key: row_value}
if column_value:
current_tags |= {self.column_key: column_value}
processed: set[str] = set()
icon, _ = SCHEME.get_icon(
EXTRACTOR, current_tags, processed, MapConfiguration()
)
processed = icon.processed
if not icon:
print("Icon was not constructed.")
if (
icon.main_icon
and not icon.main_icon.is_default()
and (
not self.column_key
or not column_value
or (self.column_key in processed)
)
and (
not self.row_key
or not row_value
or (self.row_key in processed)
)
):
table.draw_icon(np.array((j, i)), icon)
else:
table.draw_cross(np.array((j, i)))
return table.get_size()
tower_type_values: list[str] = [
"communication",
"lighting",
"monitoring",
"siren",
]
collections = [
Collection(
"Tag:man_made=mast",
{"man_made": "mast"},
"tower:construction",
["freestanding", "lattice", "guyed_tube", "guyed_lattice"],
"tower:type",
[""] + tower_type_values,
),
Collection(
"Tag:natural=volcano",
{"natural": "volcano"},
"volcano:type",
["stratovolcano", "shield", "scoria"],
"volcano:status",
["", "active", "dormant", "extinct"],
),
Collection(
"Tag:tower:construction=guyed_tube",
{"man_made": "mast", "tower:construction": "guyed_tube"},
"tower:type",
[""] + tower_type_values,
),
Collection(
"Tag:tower:construction=guyed_lattice",
{"man_made": "mast", "tower:construction": "guyed_lattice"},
"tower:type",
[""] + tower_type_values,
),
Collection(
"Key:communication:mobile_phone",
{"communication:mobile_phone": "yes"},
),
Collection(
"Key:traffic_calming",
{},
"traffic_calming",
[
"bump",
"mini_bumps",
"hump",
"table",
"cushion",
"rumble_strip",
"dip",
"double_dip",
# "dynamic_bump", "chicane",
# "choker", "island", "chocked_island", "chocked_table",
],
),
Collection(
"Key:crane:type",
{"man_made": "crane"},
"crane:type",
[
"gantry_crane",
"floor-mounted_crane",
"portal_crane",
"travel_lift",
"tower_crane",
],
),
Collection(
"Tag:tower:type=diving",
{"man_made": "tower", "tower:type": "diving"},
),
Collection(
"Key:design",
{},
"power",
["tower", "pole"],
"design",
[
"one-level",
"two-level",
"three-level",
"four-level",
"asymmetric",
"triangle",
"flag",
"delta",
"delta_two-level",
"delta_three-level",
],
),
Collection(
"Key:design_2",
{},
"power",
["tower"],
"design",
[
"donau",
"donau_inverse",
"barrel",
"y-frame",
"x-frame",
"h-frame",
"guyed_h-frame",
"portal",
"portal_two-level",
"portal_three-level",
],
),
]
def draw_svg_tables(output_path: Path, html_file_path: Path) -> None: def draw_svg_tables(output_path: Path, html_file_path: Path) -> None:
"""Draw SVG tables of icon collections.""" """Draw SVG tables of icon collections."""
with Path("data/collections.json").open() as input_file:
collections: list[list] = json.load(input_file)
with html_file_path.open("w+") as html_file: with html_file_path.open("w+") as html_file:
for collection in collections: for collection in collections:
path: Path = output_path / f"{collection.page_name}.svg" path: Path = output_path / f"{collection[0]}.svg"
svg: svgwrite = svgwrite.Drawing(path.name) svg: Drawing = svgwrite.Drawing(path.name)
width, height = collection.draw_table(svg)
svg.update({"width": width, "height": height}) row_key = collection[2] if len(collection) > 2 else None
row_values = collection[3] if len(collection) > 3 else []
column_key = collection[4] if len(collection) > 4 else None
column_values = collection[5] if len(collection) > 5 else []
table: SVGTable = SVGTable(
svg,
collection[0],
collection[1],
row_key,
row_values,
column_key,
column_values,
)
table.draw_table()
with path.open("w+") as output_file: with path.open("w+") as output_file:
svg.write(output_file) svg.write(output_file)
html_file.write(f'<img src="{path}" />\n') html_file.write(f'<img src="{path}" />\n')