Support path drawing.

This commit is contained in:
Sergey Vartanov 2021-08-18 23:00:12 +03:00
parent 737e434260
commit ade9d3b034
7 changed files with 55 additions and 13 deletions

View file

@ -234,7 +234,7 @@ class Constructor:
priority: int priority: int
icon_set: IconSet icon_set: IconSet
icon_set, priority = self.scheme.get_icon( icon_set, priority = self.scheme.get_icon(
self.icon_extractor, line.tags, processed, for_="line" self.icon_extractor, line.tags, processed
) )
labels = self.scheme.construct_text(line.tags, "all", processed) labels = self.scheme.construct_text(line.tags, "all", processed)
point: Point = Point( point: Point = Point(

View file

@ -1,16 +1,16 @@
""" """
Direction tag support. Direction tag support.
""" """
from typing import Iterator, Optional, Union from typing import Iterator, Optional
import numpy as np import numpy as np
from portolan import middle from portolan import middle
from roentgen.drawing import PathCommand
__author__ = "Sergey Vartanov" __author__ = "Sergey Vartanov"
__email__ = "me@enzet.ru" __email__ = "me@enzet.ru"
SVGPath = Union[float, str, np.array]
SHIFT: float = -np.pi / 2 SHIFT: float = -np.pi / 2
SMALLEST_ANGLE: float = np.pi / 15 SMALLEST_ANGLE: float = np.pi / 15
DEFAULT_ANGLE: float = np.pi / 30 DEFAULT_ANGLE: float = np.pi / 30
@ -90,7 +90,7 @@ class Sector:
self.start = np.dot(rotation_matrix(result_angle), vector) self.start = np.dot(rotation_matrix(result_angle), vector)
self.end = np.dot(rotation_matrix(-result_angle), vector) self.end = np.dot(rotation_matrix(-result_angle), vector)
def draw(self, center: np.array, radius: float) -> Optional[list[SVGPath]]: def draw(self, center: np.array, radius: float) -> Optional[PathCommand]:
""" """
Construct SVG path commands for arc element. Construct SVG path commands for arc element.
@ -139,7 +139,7 @@ class DirectionSet:
def __str__(self) -> str: def __str__(self) -> str:
return ", ".join(map(str, self.sectors)) return ", ".join(map(str, self.sectors))
def draw(self, center: np.array, radius: float) -> Iterator[list[SVGPath]]: def draw(self, center: np.array, radius: float) -> Iterator[PathCommand]:
""" """
Construct SVG "d" for arc elements. Construct SVG "d" for arc elements.

View file

@ -3,7 +3,7 @@ Drawing utility.
""" """
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from typing import Optional, List from typing import Optional, List, Union
import cairo import cairo
import numpy as np import numpy as np
@ -16,6 +16,8 @@ from svgwrite.text import Text
__author__ = "Sergey Vartanov" __author__ = "Sergey Vartanov"
__email__ = "me@enzet.ru" __email__ = "me@enzet.ru"
PathCommand = list[Union[float, str, np.array]]
@dataclass @dataclass
class Style: class Style:
@ -75,6 +77,10 @@ class Drawing:
"""Draw line.""" """Draw line."""
raise NotImplementedError raise NotImplementedError
def path(self, command: PathCommand, style: Style) -> None:
"""Draw path."""
raise NotImplementedError
def text(self, text: str, point: np.array, color: Color = Color("black")): def text(self, text: str, point: np.array, color: Color = Color("black")):
"""Draw text.""" """Draw text."""
raise NotImplementedError raise NotImplementedError
@ -107,10 +113,14 @@ class SVGDrawing(Drawing):
def line(self, points: List[np.array], style: Style) -> None: def line(self, points: List[np.array], style: Style) -> None:
"""Draw line.""" """Draw line."""
commands: str = "M " command: PathCommand = ["M"]
for point in points: for point in points:
commands += f"{point[0]},{point[1]} L " command += [point, "L"]
path = SVGPath(d=commands[:-3]) self.path(command[:-1], style)
def path(self, command: PathCommand, style: Style) -> None:
"""Draw path."""
path = SVGPath(d=command)
style.update_svg_element(path) style.update_svg_element(path)
self.image.add(path) self.image.add(path)
@ -162,6 +172,36 @@ class PNGDrawing(Drawing):
self.context.line_to(float(point[0]), float(point[1])) self.context.line_to(float(point[0]), float(point[1]))
style.draw_png_stroke(self.context) style.draw_png_stroke(self.context)
def _do_path(self, command) -> None:
"""Draw path."""
for index in range(len(command)):
element = command[index]
if isinstance(element, str):
next_element: np.array = command[index + 1]
if element == 5:
self.context.move_to(next_element[0], next_element[1])
if element == 5:
self.context.line_to(next_element[0], next_element[1])
if element == 5:
self.context.curve_to(
next_element[0],
next_element[1],
command[index + 2][0],
command[index + 2][1],
command[index + 3][0],
command[index + 3][1],
)
index += 1
def path(self, command: PathCommand, style: Style) -> None:
"""Draw path."""
if style.fill is not None:
self._do_path(command)
style.draw_png_fill(self.context)
if style.stroke is not None:
self._do_path(command)
style.draw_png_stroke(self.context)
def text(self, text: str, point: np.array, color: Color = Color("black")): def text(self, text: str, point: np.array, color: Color = Color("black")):
"""Draw text.""" """Draw text."""
self.context.set_source_rgb( self.context.set_source_rgb(

View file

@ -178,6 +178,7 @@ class RoentgenHTML(RoentgenMoire, DefaultHTML):
""" """
def __init__(self) -> None: def __init__(self) -> None:
super().__init__()
self.images: dict = {} self.images: dict = {}
def color(self, args: Arguments) -> str: def color(self, args: Arguments) -> str:
@ -204,6 +205,7 @@ class RoentgenOSMWiki(RoentgenMoire, DefaultWiki):
""" """
def __init__(self) -> None: def __init__(self) -> None:
super().__init__()
self.images: dict = {} self.images: dict = {}
self.extractor: ShapeExtractor = ShapeExtractor( self.extractor: ShapeExtractor = ShapeExtractor(
workspace.ICONS_PATH, workspace.ICONS_CONFIG_PATH workspace.ICONS_PATH, workspace.ICONS_CONFIG_PATH

View file

@ -30,6 +30,7 @@ class Lane:
destination: Optional[str] = None # Lane destination destination: Optional[str] = None # Lane destination
def set_forward(self, is_forward: bool) -> None: def set_forward(self, is_forward: bool) -> None:
"""If true, lane is forward, otherwise it's backward."""
self.is_forward = is_forward self.is_forward = is_forward
def get_width(self, scale: float): def get_width(self, scale: float):
@ -339,7 +340,7 @@ class Intersection:
part_2.update() part_2.update()
def draw( def draw(
self, drawing: svgwrite.Drawing, scale: float, is_debug: bool = False self, drawing: svgwrite.Drawing, is_debug: bool = False
) -> None: ) -> None:
""" """
Draw all road parts and intersection. Draw all road parts and intersection.

View file

@ -333,14 +333,12 @@ class Scheme:
extractor: ShapeExtractor, extractor: ShapeExtractor,
tags: dict[str, Any], tags: dict[str, Any],
processed: set[str], processed: set[str],
for_: str = "node",
) -> tuple[IconSet, int]: ) -> tuple[IconSet, int]:
""" """
Construct icon set. Construct icon set.
:param extractor: extractor with icon specifications :param extractor: extractor with icon specifications
:param tags: OpenStreetMap element tags dictionary :param tags: OpenStreetMap element tags dictionary
:param for_: target (node, way, area or relation)
:param processed: set of already processed tag keys :param processed: set of already processed tag keys
:return (icon set, icon priority) :return (icon set, icon priority)
""" """

View file

@ -31,6 +31,7 @@ def get_address(
:param tags: OSM node, way or relation tags :param tags: OSM node, way or relation tags
:param draw_captions_mode: captions mode ("all", "main", or "no") :param draw_captions_mode: captions mode ("all", "main", or "no")
:param processed: set of processed tag keys
""" """
address: list[str] = [] address: list[str] = []