diff --git a/map_machine/constructor.py b/map_machine/constructor.py index 38c5792..a858cc6 100644 --- a/map_machine/constructor.py +++ b/map_machine/constructor.py @@ -451,7 +451,10 @@ class Constructor: color = get_time_color(node.timestamp, self.osm_data.time) dot: Shape = self.extractor.get_shape(DEFAULT_SMALL_SHAPE_ID) icon_set: IconSet = IconSet( - Icon([ShapeSpecification(dot, color)]), [], set() + Icon([ShapeSpecification(dot, color)]), + [], + Icon([ShapeSpecification(dot, color)]), + set(), ) point: Point = Point( icon_set, diff --git a/map_machine/pictogram/icon.py b/map_machine/pictogram/icon.py index d45b129..4130953 100644 --- a/map_machine/pictogram/icon.py +++ b/map_machine/pictogram/icon.py @@ -584,6 +584,10 @@ class IconSet: main_icon: Icon extra_icons: list[Icon] + # Icon to use if the point is hidden by overlapped icons but still need to + # be shown. + default_icon: Optional[Icon] + # Tag keys that were processed to create icon set (other tag keys should be # displayed by text or ignored) processed: set[str] diff --git a/map_machine/pictogram/point.py b/map_machine/pictogram/point.py index 942cf9f..2100792 100644 --- a/map_machine/pictogram/point.py +++ b/map_machine/pictogram/point.py @@ -105,7 +105,12 @@ class Point(Tagged): self.tags if self.add_tooltips else None ) self.main_icon_painted: bool = self.draw_point_shape( - svg, self.icon_set.main_icon, position, occupied, tags=tags + svg, + self.icon_set.main_icon, + self.icon_set.default_icon, + position, + occupied, + tags=tags, ) if self.main_icon_painted: self.y += 16.0 @@ -133,7 +138,7 @@ class Point(Tagged): left: float = -(len(self.icon_set.extra_icons) - 1.0) * 8.0 for icon in self.icon_set.extra_icons: point: np.ndarray = self.point + np.array((left, self.y)) - self.draw_point_shape(svg, icon, point, occupied=occupied) + self.draw_point_shape(svg, icon, None, point, occupied=occupied) left += 16.0 if self.icon_set.extra_icons: self.y += 16.0 @@ -142,21 +147,27 @@ class Point(Tagged): self, svg: svgwrite.Drawing, icon: Icon, + default_icon: Optional[Icon], position: np.ndarray, - occupied: Occupied, + occupied: Optional[Occupied], tags: Optional[dict[str, str]] = None, ) -> bool: """Draw one combined icon and its outline.""" # Down-cast floats to integers to make icons pixel-perfect. position: np.ndarray = np.array((int(position[0]), int(position[1]))) + icon_to_draw: Icon = icon + if occupied and occupied.check(position): - return False + if default_icon: + icon_to_draw = default_icon + else: + return False if self.draw_outline: - icon.draw(svg, position, outline=True) + icon_to_draw.draw(svg, position, outline=True) - icon.draw(svg, position, tags=tags) + icon_to_draw.draw(svg, position, tags=tags) if occupied: overlap: int = occupied.overlap diff --git a/map_machine/scheme.py b/map_machine/scheme.py index e7b1be6..e8e03e9 100644 --- a/map_machine/scheme.py +++ b/map_machine/scheme.py @@ -22,6 +22,7 @@ from map_machine.pictogram.icon import ( Shape, ShapeExtractor, ShapeSpecification, + DEFAULT_SMALL_SHAPE_ID, ) from map_machine.text import Label, TextConstructor @@ -559,13 +560,23 @@ class Scheme: if main_icon and color: main_icon.recolor(color) - default_shape = extractor.get_shape(DEFAULT_SHAPE_ID) if not main_icon: - main_icon = Icon( - [ShapeSpecification(default_shape, self.get_color("default"))] + dot_spec: ShapeSpecification = ShapeSpecification( + extractor.get_shape(DEFAULT_SHAPE_ID), self.get_color("default") ) + main_icon: Icon = Icon([dot_spec]) - returned: IconSet = IconSet(main_icon, extra_icons, processed) + default_icon: Optional[Icon] = None + if configuration.show_overlapped: + small_dot_spec: ShapeSpecification = ShapeSpecification( + extractor.get_shape(DEFAULT_SMALL_SHAPE_ID), + self.get_color("default"), + ) + default_icon = Icon([small_dot_spec]) + + returned: IconSet = IconSet( + main_icon, extra_icons, default_icon, processed + ) self.cache[tags_hash] = returned, priority for key in "direction", "camera:direction":