diff --git a/roentgen/constructor.py b/roentgen/constructor.py index 9c44c16..ba05b13 100644 --- a/roentgen/constructor.py +++ b/roentgen/constructor.py @@ -237,16 +237,19 @@ class Constructor: and line.get_tag("area") != "no" and self.scheme.is_area(line.tags) ): + processed: Set[str] = set() + priority: int icon_set: IconSet icon_set, priority = self.scheme.get_icon( - self.icon_extractor, line.tags, for_="line" + self.icon_extractor, line.tags, processed, for_="line" ) - labels = self.scheme.construct_text(line.tags, "all") + labels = self.scheme.construct_text(line.tags, "all", processed) point: Point = Point( icon_set, labels, line.tags, + processed, center_point, center_coordinates, is_for_node=False, @@ -266,15 +269,17 @@ class Constructor: ) self.figures.append(figure) + processed: Set[str] = set() + priority: int icon_set: IconSet icon_set, priority = self.scheme.get_icon( - self.icon_extractor, line.tags + self.icon_extractor, line.tags, processed ) - labels = self.scheme.construct_text(line.tags, "all") + labels = self.scheme.construct_text(line.tags, "all", processed) point: Point = Point( - icon_set, labels, line.tags, center_point, center_coordinates, - is_for_node=False, priority=priority, + icon_set, labels, line.tags, processed, center_point, + center_coordinates, is_for_node=False, priority=priority, ) # fmt: skip self.points.append(point) @@ -333,6 +338,8 @@ class Constructor: missing_tags = Counter() for node_id in sorted_node_ids: # type: int + processed: Set[str] = set() + node_number += 1 ui.progress_bar( node_number, len(self.map_.nodes), text="Constructing nodes" @@ -365,12 +372,12 @@ class Constructor: labels = [] else: icon_set, priority = self.scheme.get_icon( - self.icon_extractor, tags + self.icon_extractor, tags, processed ) - labels = self.scheme.construct_text(tags, "all") + labels = self.scheme.construct_text(tags, "all", processed) point: Point = Point( - icon_set, labels, tags, flung, node.coordinates, - priority=priority, draw_outline=draw_outline, + icon_set, labels, tags, processed, flung, node.coordinates, + priority=priority, draw_outline=draw_outline ) # fmt: skip self.points.append(point) diff --git a/roentgen/point.py b/roentgen/point.py index 36ca2e8..7f3e4d9 100644 --- a/roentgen/point.py +++ b/roentgen/point.py @@ -1,7 +1,7 @@ """ Point: node representation on the map. """ -from typing import Dict, List, Optional +from typing import Dict, List, Optional, Set import numpy as np import svgwrite @@ -54,8 +54,8 @@ class Point(Tagged): def __init__( self, icon_set: IconSet, labels: List[Label], tags: Dict[str, str], - point: np.array, coordinates: np.array, priority: float = 0, - is_for_node: bool = True, draw_outline: bool = True + processed: Set[str], point: np.array, coordinates: np.array, + priority: float = 0, is_for_node: bool = True, draw_outline: bool = True ): super().__init__() @@ -64,6 +64,7 @@ class Point(Tagged): self.icon_set: IconSet = icon_set self.labels: List[Label] = labels self.tags: Dict[str, str] = tags + self.processed: Set[str] = processed self.point: np.array = point self.coordinates: np.array = coordinates self.priority: float = priority @@ -80,9 +81,14 @@ class Point(Tagged): """ Draw main shape for one node. """ + keys_left = [ + x for x in self.tags.keys() + if x not in self.processed # and not self.is_no_drawable(x) + ] if ( - self.icon_set.main_icon.is_default() and - not self.icon_set.extra_icons + self.icon_set.main_icon.is_default() + and not self.icon_set.extra_icons + and (not keys_left or not self.is_for_node) ): return @@ -177,7 +183,7 @@ class Point(Tagged): text = text.replace("&", '&') text = text[:26] + ("..." if len(text) > 26 else "") self.draw_text( - svg, text, self.point + np.array((0, self.y)), + svg, text, self.point + np.array((0, self.y + 2)), occupied, label.fill, size=label.size ) @@ -197,8 +203,6 @@ class Point(Tagged): #------# ###### """ - self.y += 2 - length = len(text) * 6 if occupied: @@ -249,5 +253,5 @@ class Point(Tagged): ) height: int = icon_size * (1 + int(len(self.icon_set.extra_icons) / 3)) if len(self.labels): - height += 2 + 11 * len(self.labels) + height += 4 + 11 * len(self.labels) return np.array((width, height)) diff --git a/roentgen/scheme.py b/roentgen/scheme.py index 4004a10..07b3abe 100644 --- a/roentgen/scheme.py +++ b/roentgen/scheme.py @@ -268,6 +268,7 @@ class Scheme: self, icon_extractor: ShapeExtractor, tags: Dict[str, Any], + processed: Set[str], for_: str = "node", ) -> Tuple[IconSet, int]: """ @@ -276,6 +277,7 @@ class Scheme: :param icon_extractor: extractor with icon specifications :param tags: OpenStreetMap element tags dictionary :param for_: target (node, way, area or relation) + :param processed: set of already processed tag keys :return (icon set, icon priority) """ tags_hash: str = ( @@ -286,7 +288,6 @@ class Scheme: main_icon: Optional[Icon] = None extra_icons: List[Icon] = [] - processed: Set[str] = set() priority: int = 0 index: int = 0 @@ -388,7 +389,7 @@ class Scheme: return None def construct_text( - self, tags: Dict[str, str], draw_captions: str + self, tags: Dict[str, str], draw_captions: str, processed: Set[str] ) -> List[Label]: """ Construct labels for not processed tags. @@ -399,24 +400,19 @@ class Scheme: 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: + processed.add("name") + elif "name:en" in tags: if not name: name = tags["name:en"] - tags.pop("name:en", None) - tags.pop("name:en", None) + processed.add("name:en") + processed.add("name:en") if "alt_name" in tags: if alt_name: alt_name += ", " else: alt_name = "" alt_name += tags["alt_name"] - tags.pop("alt_name") + processed.add("alt_name") if "old_name" in tags: if alt_name: alt_name += ", " @@ -424,7 +420,7 @@ class Scheme: alt_name = "" alt_name += "ex " + tags["old_name"] - address: List[str] = get_address(tags, draw_captions) + address: List[str] = get_address(tags, draw_captions, processed) if name: texts.append(Label(name, Color("black"))) @@ -436,15 +432,14 @@ class Scheme: if draw_captions == "main": return texts - processed: Set[str] = set() texts += get_text(tags, processed) if "route_ref" in tags: texts.append(Label(tags["route_ref"].replace(";", " "))) - tags.pop("route_ref", None) + processed.add("route_ref") if "cladr:code" in tags: texts.append(Label(tags["cladr:code"], size=7)) - tags.pop("cladr:code", None) + processed.add("cladr:code") if "website" in tags: link = tags["website"] if link[:7] == "http://": @@ -457,16 +452,16 @@ class Scheme: link = link[:-1] link = link[:25] + ("..." if len(tags["website"]) > 25 else "") texts.append(Label(link, Color("#000088"))) - tags.pop("website", None) + processed.add("website") for key in ["phone"]: if key in tags: texts.append(Label(tags[key], Color("#444444"))) - tags.pop(key) + processed.add(key) if "height" in tags: texts.append(Label(f"↕ {tags['height']} m")) - tags.pop("height") + processed.add("height") for tag in tags: - if self.is_writable(tag): + if self.is_writable(tag) and tag not in processed: texts.append(Label(tags[tag])) return texts diff --git a/roentgen/text.py b/roentgen/text.py index 1e46a44..a40c635 100644 --- a/roentgen/text.py +++ b/roentgen/text.py @@ -22,7 +22,9 @@ class Label: 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, processed: Set[str] +) -> List[str]: """ Construct address text list from the tags. @@ -34,23 +36,23 @@ def get_address(tags: Dict[str, Any], draw_captions_mode: str) -> List[str]: if draw_captions_mode == "address": if "addr:postcode" in tags: address.append(tags["addr:postcode"]) - tags.pop("addr:postcode", None) + processed.add("addr:postcode") if "addr:country" in tags: address.append(tags["addr:country"]) - tags.pop("addr:country", None) + processed.add("addr:country") if "addr:city" in tags: address.append(tags["addr:city"]) - tags.pop("addr:city", None) + processed.add("addr:city") if "addr:street" in tags: street = tags["addr:street"] if street.startswith("улица "): street = "ул. " + street[len("улица "):] address.append(street) - tags.pop("addr:street", None) + processed.add("addr:street") if "addr:housenumber" in tags: address.append(tags["addr:housenumber"]) - tags.pop("addr:housenumber", None) + processed.add("addr:housenumber") return address diff --git a/test/test_icons.py b/test/test_icons.py index a5010d0..1a2fe4c 100644 --- a/test/test_icons.py +++ b/test/test_icons.py @@ -2,7 +2,7 @@ Test icon generation for nodes. """ from pathlib import Path -from typing import Dict, Tuple +from typing import Dict, Tuple, Set import pytest @@ -48,7 +48,8 @@ def get_icon(tags: Dict[str, str]) -> IconSet: """ Construct icon from tags. """ - icon, _ = SCHEME.get_icon(SHAPE_EXTRACTOR, tags) + processed: Set[str] = set() + icon, _ = SCHEME.get_icon(SHAPE_EXTRACTOR, tags, processed) return icon diff --git a/test/test_label.py b/test/test_label.py index f8bb344..041ea84 100644 --- a/test/test_label.py +++ b/test/test_label.py @@ -1,7 +1,7 @@ """ Test label generation for nodes. """ -from typing import List +from typing import List, Set from roentgen.text import Label from test import SCHEME @@ -14,7 +14,8 @@ def construct_labels(tags) -> List[Label]: """ Construct labels from OSM node tags. """ - return SCHEME.construct_text(tags, "all") + processed: Set[str] = set() + return SCHEME.construct_text(tags, "all", processed) def test_1_label() -> None: