mirror of
https://github.com/enzet/map-machine.git
synced 2025-05-21 13:06:25 +02:00
Support path drawing.
This commit is contained in:
parent
737e434260
commit
ade9d3b034
7 changed files with 55 additions and 13 deletions
|
@ -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(
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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] = []
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue