From 592e36762a99a30744ed2c79a097f13b7b987b3e Mon Sep 17 00:00:00 2001 From: Sergey Vartanov Date: Sat, 27 Nov 2021 21:01:59 +0300 Subject: [PATCH] Get use of JSON icon collections; refactor. --- map_machine/doc/collections.py | 395 ++++++++++++--------------------- 1 file changed, 145 insertions(+), 250 deletions(-) diff --git a/map_machine/doc/collections.py b/map_machine/doc/collections.py index fe2d41c..2c34a93 100644 --- a/map_machine/doc/collections.py +++ b/map_machine/doc/collections.py @@ -1,6 +1,7 @@ """ Special icon collections for documentation. """ +import json from dataclasses import dataclass, field from pathlib import Path from typing import Optional @@ -26,23 +27,92 @@ EXTRACTOR: ShapeExtractor = ShapeExtractor( @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.""" def __init__( self, svg: svgwrite.Drawing, - row_key: Optional[str], - row_values: list[str], - column_key: Optional[str], - column_values: list[str], + page_name: str, + tags: Tags, + row_key: Optional[str] = None, + 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.row_values: list[str] = row_values - self.column_key: Optional[str] = column_key - self.column_values: list[str] = column_values + self.svg: svgwrite.Drawing = svg self.border: np.ndarray = np.array((16.0, 16.0)) self.step: float = 48.0 @@ -84,13 +154,49 @@ class SVGTable: 2 * self.border + np.array(self.size) + self.half_step ) - def draw(self) -> None: - """Draw rows and columns.""" + def draw_table(self) -> None: + """Draw SVG table.""" self.draw_rows() self.draw_columns() self.draw_delimiter() 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: """Draw row texts.""" point: np.ndarray = np.array(self.start_point) - np.array( @@ -209,246 +315,35 @@ 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: """Draw SVG tables of icon collections.""" - with html_file_path.open("w+") as html_file: - for collection in collections: - path: Path = output_path / f"{collection.page_name}.svg" - svg: svgwrite = svgwrite.Drawing(path.name) - width, height = collection.draw_table(svg) - svg.update({"width": width, "height": height}) - with path.open("w+") as output_file: - svg.write(output_file) - html_file.write(f'\n') + + 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: + for collection in collections: + path: Path = output_path / f"{collection[0]}.svg" + svg: Drawing = svgwrite.Drawing(path.name) + + 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: + svg.write(output_file) + html_file.write(f'\n') if __name__ == "__main__":