diff --git a/roentgen/constructor.py b/roentgen/constructor.py index fa3b884..b59b3f1 100644 --- a/roentgen/constructor.py +++ b/roentgen/constructor.py @@ -51,14 +51,16 @@ def make_counter_clockwise(polygon: List[OSMNode]) -> List[OSMNode]: return list(reversed(polygon)) -class Node(Tagged): +class Point(Tagged): """ - Node in Röntgen terms. + Object on the map with no dimensional attributes. """ def __init__( - self, icon_set: IconSet, tags: Dict[str, str], - point: np.array, coordinates: np.array, - priority: float = 0, is_for_node: bool = True): + self, icon_set: IconSet, tags: Dict[str, str], point: np.array, + coordinates: np.array, priority: float = 0, + is_for_node: bool = True): + super().__init__() + assert point is not None self.icon_set: IconSet = icon_set @@ -75,18 +77,21 @@ class Node(Tagged): return None -class Way: +class Figure(Tagged): """ - Way in Röntgen terms. + Some figure on the map: way or area. """ def __init__( - self, inners, outers, style: Dict[str, Any], - layer: float = 0.0, levels=None): + self, tags: Dict[str, str], inners, outers, style: Dict[str, Any], + layer: float = 0.0): + + super().__init__() + + self.tags: Dict[str, str] = tags self.inners = [] self.outers = [] self.style: Dict[str, Any] = style self.layer = layer - self.levels = levels for inner_nodes in inners: self.inners.append(make_clockwise(inner_nodes)) @@ -110,6 +115,20 @@ class Way: return path + +class Building(Figure): + def __init__( + self, tags: Dict[str, str], inners, outers, style: Dict[str, Any], + layer: float): + super().__init__(tags, inners, outers, style, layer) + + def get_levels(self): + try: + return float(self.get_tag("building:levels")) + except (ValueError, TypeError): + return 1 + + class TextStruct: def __init__( self, text: str, fill: Color = Color("#444444"), size: float = 10): @@ -219,9 +238,9 @@ class Constructor: self.flinger: Flinger = flinger self.scheme: Scheme = scheme - self.nodes: List[Node] = [] - self.ways: List[Way] = [] - self.buildings: List[Way] = [] + self.nodes: List[Point] = [] + self.figures: List[Figure] = [] + self.buildings: List[Figure] = [] def construct_ways(self): """ @@ -263,8 +282,6 @@ class Constructor: # layer = 100 * level + 0.01 * layer - nodes = None - center_point, center_coordinates = None, None if way: @@ -276,8 +293,9 @@ class Constructor: if not way: return user_color = get_user_color(way.user, self.seed) - self.ways.append( - Way(inners, outers, + self.figures.append( + Figure( + way.tags, inners, outers, {"fill": "none", "stroke": user_color.hex, "stroke-width": 1})) return @@ -286,8 +304,9 @@ class Constructor: if not way: return time_color = get_time_color(way.timestamp, self.map_.time) - self.ways.append( - Way(inners, outers, + self.figures.append( + Figure( + way.tags, inners, outers, {"fill": "none", "stroke": time_color.hex, "stroke-width": 1})) return @@ -296,16 +315,6 @@ class Constructor: return appended: bool = False - kind: str = "way" - levels = None - - if "building" in tags: # or "building:part" in tags: - kind = "building" - if "building:levels" in tags: - try: - levels = float(tags["building:levels"]) - except ValueError: - levels = None for element in self.scheme.ways: # type: Dict[str, Any] matched: bool = True @@ -329,7 +338,9 @@ class Constructor: if "priority" in element: layer = element["priority"] for key in element: # type: str - if key not in ["tags", "no_tags", "priority", "level", "icon", "r", "r2"]: + if key not in [ + "tags", "no_tags", "priority", "level", "icon", + "r", "r2"]: value = element[key] if isinstance(value, str) and value.endswith("_color"): value = self.scheme.get_color(value) @@ -343,15 +354,16 @@ class Constructor: style["stroke-width"] = \ element["r2"] * \ self.flinger.get_scale(center_coordinates) + 2 - w = Way(inners, outers, style, layer, levels) - if kind == "way": - self.ways.append(w) - elif kind == "building": - self.buildings.append(w) + if "building" in tags: + self.buildings.append( + Building(tags, inners, outers, style, layer)) + else: + self.figures.append( + Figure(tags, inners, outers, style, layer)) if center_point is not None and \ (way.is_cycle() and "area" in tags and tags["area"]): icon_set: IconSet = self.scheme.get_icon(tags) - self.nodes.append(Node( + self.nodes.append(Point( icon_set, tags, center_point, center_coordinates, is_for_node=False)) appended = True @@ -361,12 +373,12 @@ class Constructor: style: Dict[str, Any] = { "fill": "none", "stroke": Color("red").hex, "stroke-width": 1} - self.ways.append(Way( - kind, inners, outers, style, layer, levels)) + self.figures.append(Figure( + tags, inners, outers, style, layer)) if center_point is not None and (way.is_cycle() or "area" in tags and tags["area"]): icon_set: IconSet = self.scheme.get_icon(tags) - self.nodes.append(Node( + self.nodes.append(Point( icon_set, tags, center_point, center_coordinates, is_for_node=False)) @@ -428,6 +440,6 @@ class Constructor: if self.mode == "time": icon_set.color = get_time_color(node.timestamp) - self.nodes.append(Node(icon_set, tags, flung, node.position)) + self.nodes.append(Point(icon_set, tags, flung, node.position)) ui.progress_bar(-1, len(self.map_.node_map), text="Constructing nodes") diff --git a/roentgen/mapper.py b/roentgen/mapper.py index 4b5f52c..7bac1b3 100644 --- a/roentgen/mapper.py +++ b/roentgen/mapper.py @@ -17,7 +17,7 @@ from typing import Any, Dict, List, Optional from roentgen import ui from roentgen.address import get_address -from roentgen.constructor import Constructor, Node, Way, TextStruct +from roentgen.constructor import Constructor, Point, Figure, TextStruct, Building from roentgen.flinger import Flinger from roentgen.grid import draw_grid from roentgen.extract_icon import Icon, IconExtractor @@ -61,7 +61,7 @@ class Painter: self.icon_extractor = icon_extractor self.scheme: Scheme = scheme - def draw_shapes(self, node: Node, points: List[List[float]]): + def draw_shapes(self, node: Point, points: List[List[float]]): """ Draw shapes for one node. """ @@ -93,7 +93,7 @@ class Painter: node.icon_set.color, tags=node.tags) left += 16 - def draw_texts(self, node: Node): + def draw_texts(self, node: Point): """ Draw all labels. """ @@ -229,7 +229,7 @@ class Painter: """ Draw area between way and way shifted by the vector. """ - for way in ways: + for way in ways: # type: Building if stage == 1: shift_1 = [0, 0] shift_2 = [0, -1] @@ -238,10 +238,7 @@ class Painter: shift_2 = [0, -2] else: shift_1 = [0, -2] - if way.levels: - shift_2 = [0, min(-3, -1 * way.levels)] - else: - shift_2 = [0, -3] + shift_2 = [0, min(-3, -1 * way.get_levels())] for nodes in way.inners + way.outers: for i in range(len(nodes) - 1): @@ -252,15 +249,15 @@ class Painter: d=("M", np.add(flung_1, shift_1), "L", np.add(flung_2, shift_1), np.add(flung_2, shift_2), np.add(flung_1, shift_2), "Z"), - fill=color.hex, stroke=color.hex, stroke_width=1)) + fill=color.hex, stroke="#CCCCCC", stroke_width=1)) def draw(self, constructor: Constructor, points): """ Draw map. """ - ways = sorted(constructor.ways, key=lambda x: x.layer) + ways = sorted(constructor.figures, key=lambda x: x.layer) ways_length: int = len(ways) - for index, way in enumerate(ways): # type: Way + for index, way in enumerate(ways): # type: Figure ui.progress_bar(index, ways_length, step=10, text="Drawing ways") path: str = way.get_path(self.flinger) if path: @@ -273,10 +270,9 @@ class Painter: building_shade = Group(opacity=0.1) - for way in constructor.buildings: # type: Way + for way in constructor.buildings: # type: Building shift = [-5, 5] - if way.levels: - shift = [-5 * way.levels, 5 * way.levels] + shift = [-5 * way.get_levels(), 5 * way.get_levels()] for nodes11 in way.inners + way.outers: for i in range(len(nodes11) - 1): flung_1 = self.flinger.fling(nodes11[i].position) @@ -298,10 +294,10 @@ class Painter: building_paths: List[(str, Dict)] = [] - for way in constructor.buildings: # type: Way + for way in constructor.buildings: # type: Building shift = [0, -3] - if way.levels: - shift = np.array([0 * way.levels, min(-3, -1 * way.levels)]) + shift = np.array([ + 0 * way.get_levels(), min(-3, -1 * way.get_levels())]) path: str = way.get_path(self.flinger, shift) if path: building_paths.append((path, way.style)) @@ -339,7 +335,7 @@ class Painter: # Directions - for node in constructor.nodes: # type: Node + for node in constructor.nodes: # type: Point angle = None is_revert_gradient: bool = False @@ -396,7 +392,7 @@ class Painter: # All other nodes nodes = sorted(constructor.nodes, key=lambda x: x.layer) - for index, node in enumerate(nodes): # type: int, Node + for index, node in enumerate(nodes): # type: int, Point if node.get_tag("natural") == "tree" and \ ("diameter_crown" in node.tags or "circumference" in node.tags): @@ -408,7 +404,7 @@ class Painter: if self.draw_captions == "no": return - for node in nodes: # type: Node + for node in nodes: # type: Point if self.mode not in [CREATION_TIME_MODE, AUTHOR_MODE]: self.draw_texts(node)