mirror of
https://github.com/enzet/map-machine.git
synced 2025-05-23 14:06:23 +02:00
Add documentation.
This commit is contained in:
parent
3bcf026862
commit
b20006f6ae
7 changed files with 40 additions and 37 deletions
|
@ -197,7 +197,7 @@ def draw_element(options):
|
||||||
|
|
||||||
output_file_path: Path = workspace.output_path / "element.svg"
|
output_file_path: Path = workspace.output_path / "element.svg"
|
||||||
svg = svgwrite.Drawing(str(output_file_path), size.astype(float))
|
svg = svgwrite.Drawing(str(output_file_path), size.astype(float))
|
||||||
for style in scheme.get_style(tags, 18):
|
for style in scheme.get_style(tags):
|
||||||
style: LineStyle
|
style: LineStyle
|
||||||
path = svg.path(d="M 0,0 L 64,0 L 64,64 L 0,64 L 0,0 Z")
|
path = svg.path(d="M 0,0 L 64,0 L 64,64 L 0,64 L 0,0 Z")
|
||||||
path.update(style.style)
|
path.update(style.style)
|
||||||
|
|
|
@ -217,8 +217,7 @@ class Constructor:
|
||||||
self.roads.append(Road(line.tags, inners, outers, road_matcher))
|
self.roads.append(Road(line.tags, inners, outers, road_matcher))
|
||||||
return
|
return
|
||||||
|
|
||||||
scale: float = self.flinger.get_scale(center_coordinates)
|
line_styles: list[LineStyle] = self.scheme.get_style(line.tags)
|
||||||
line_styles: list[LineStyle] = self.scheme.get_style(line.tags, scale)
|
|
||||||
|
|
||||||
for line_style in line_styles:
|
for line_style in line_styles:
|
||||||
self.figures.append(
|
self.figures.append(
|
||||||
|
@ -318,9 +317,7 @@ class Constructor:
|
||||||
self.construct_line(relation, inners_path, outers_path)
|
self.construct_line(relation, inners_path, outers_path)
|
||||||
|
|
||||||
def construct_nodes(self) -> None:
|
def construct_nodes(self) -> None:
|
||||||
"""
|
"""Draw nodes."""
|
||||||
Draw nodes.
|
|
||||||
"""
|
|
||||||
sorted_node_ids: Iterator[int] = sorted(
|
sorted_node_ids: Iterator[int] = sorted(
|
||||||
self.osm_data.nodes.keys(),
|
self.osm_data.nodes.keys(),
|
||||||
key=lambda x: -self.osm_data.nodes[x].coordinates[0],
|
key=lambda x: -self.osm_data.nodes[x].coordinates[0],
|
||||||
|
@ -334,6 +331,7 @@ class Constructor:
|
||||||
ui.progress_bar(-1, len(self.osm_data.nodes), text="Constructing nodes")
|
ui.progress_bar(-1, len(self.osm_data.nodes), text="Constructing nodes")
|
||||||
|
|
||||||
def construct_node(self, node: OSMNode) -> None:
|
def construct_node(self, node: OSMNode) -> None:
|
||||||
|
"""Draw one node."""
|
||||||
tags = node.tags
|
tags = node.tags
|
||||||
if not self.check_level(tags):
|
if not self.check_level(tags):
|
||||||
return
|
return
|
||||||
|
@ -360,7 +358,7 @@ class Constructor:
|
||||||
)
|
)
|
||||||
point: Point = Point(
|
point: Point = Point(
|
||||||
icon_set, [], tags, processed, flung, node.coordinates,
|
icon_set, [], tags, processed, flung, node.coordinates,
|
||||||
priority=0, draw_outline=False
|
draw_outline=False
|
||||||
) # fmt: skip
|
) # fmt: skip
|
||||||
self.points.append(point)
|
self.points.append(point)
|
||||||
return
|
return
|
||||||
|
|
|
@ -4,7 +4,7 @@ Röntgen drawing scheme.
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Optional, Tuple, Union
|
from typing import Any, Optional, Union
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
from colour import Color
|
from colour import Color
|
||||||
|
@ -145,11 +145,13 @@ class Matcher:
|
||||||
[get_selector(x, y, prefix) for (x, y) in self.tags.items()]
|
[get_selector(x, y, prefix) for (x, y) in self.tags.items()]
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_clean_shapes(self):
|
def get_clean_shapes(self) -> Optional[list[str]]:
|
||||||
|
"""Get list of shape identifiers for shapes."""
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_style(self):
|
def get_style(self) -> dict[str, Any]:
|
||||||
return None
|
"""Return way SVG style."""
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
class NodeMatcher(Matcher):
|
class NodeMatcher(Matcher):
|
||||||
|
@ -189,9 +191,10 @@ class NodeMatcher(Matcher):
|
||||||
if "with_icon" in structure:
|
if "with_icon" in structure:
|
||||||
self.with_icon = structure["with_icon"]
|
self.with_icon = structure["with_icon"]
|
||||||
|
|
||||||
def get_clean_shapes(self):
|
def get_clean_shapes(self) -> Optional[list[str]]:
|
||||||
|
"""Get list of shape identifiers for shapes."""
|
||||||
if not self.shapes:
|
if not self.shapes:
|
||||||
return
|
return None
|
||||||
return [(x if isinstance(x, str) else x["shape"]) for x in self.shapes]
|
return [(x if isinstance(x, str) else x["shape"]) for x in self.shapes]
|
||||||
|
|
||||||
|
|
||||||
|
@ -210,11 +213,12 @@ class WayMatcher(Matcher):
|
||||||
self.style[key] = scheme.get_color(style[key]).hex.upper()
|
self.style[key] = scheme.get_color(style[key]).hex.upper()
|
||||||
else:
|
else:
|
||||||
self.style[key] = style[key]
|
self.style[key] = style[key]
|
||||||
self.priority = 0
|
self.priority: int = 0
|
||||||
if "priority" in structure:
|
if "priority" in structure:
|
||||||
self.priority = structure["priority"]
|
self.priority = structure["priority"]
|
||||||
|
|
||||||
def get_style(self):
|
def get_style(self) -> dict[str, Any]:
|
||||||
|
"""Return way SVG style."""
|
||||||
return self.style
|
return self.style
|
||||||
|
|
||||||
|
|
||||||
|
@ -276,7 +280,7 @@ class Scheme:
|
||||||
self.prefix_to_skip: list[str] = content["prefix_to_skip"]
|
self.prefix_to_skip: list[str] = content["prefix_to_skip"]
|
||||||
|
|
||||||
# Storage for created icon sets.
|
# Storage for created icon sets.
|
||||||
self.cache: dict[str, Tuple[IconSet, int]] = {}
|
self.cache: dict[str, tuple[IconSet, int]] = {}
|
||||||
|
|
||||||
def get_color(self, color: str) -> Color:
|
def get_color(self, color: str) -> Color:
|
||||||
"""
|
"""
|
||||||
|
@ -330,7 +334,7 @@ class Scheme:
|
||||||
tags: dict[str, Any],
|
tags: dict[str, Any],
|
||||||
processed: set[str],
|
processed: set[str],
|
||||||
for_: str = "node",
|
for_: str = "node",
|
||||||
) -> Tuple[IconSet, int]:
|
) -> tuple[IconSet, int]:
|
||||||
"""
|
"""
|
||||||
Construct icon set.
|
Construct icon set.
|
||||||
|
|
||||||
|
@ -437,10 +441,8 @@ class Scheme:
|
||||||
|
|
||||||
return returned, priority
|
return returned, priority
|
||||||
|
|
||||||
def get_style(self, tags: dict[str, Any], scale):
|
def get_style(self, tags: dict[str, Any]):
|
||||||
"""
|
"""Get line style based on tags and scale."""
|
||||||
Get line style based on tags and scale.
|
|
||||||
"""
|
|
||||||
line_styles = []
|
line_styles = []
|
||||||
|
|
||||||
for matcher in self.way_matchers:
|
for matcher in self.way_matchers:
|
||||||
|
@ -452,6 +454,7 @@ class Scheme:
|
||||||
return line_styles
|
return line_styles
|
||||||
|
|
||||||
def get_road(self, tags: dict[str, Any]) -> Optional[RoadMatcher]:
|
def get_road(self, tags: dict[str, Any]) -> Optional[RoadMatcher]:
|
||||||
|
"""Get road matcher if tags are matched."""
|
||||||
for matcher in self.road_matchers:
|
for matcher in self.road_matchers:
|
||||||
if not matcher.is_matched(tags):
|
if not matcher.is_matched(tags):
|
||||||
continue
|
continue
|
||||||
|
@ -461,9 +464,7 @@ class Scheme:
|
||||||
def construct_text(
|
def construct_text(
|
||||||
self, tags: dict[str, str], draw_captions: str, processed: set[str]
|
self, tags: dict[str, str], draw_captions: str, processed: set[str]
|
||||||
) -> list[Label]:
|
) -> list[Label]:
|
||||||
"""
|
"""Construct labels for not processed tags."""
|
||||||
Construct labels for not processed tags.
|
|
||||||
"""
|
|
||||||
texts: list[Label] = []
|
texts: list[Label] = []
|
||||||
|
|
||||||
name = None
|
name = None
|
||||||
|
@ -536,9 +537,7 @@ class Scheme:
|
||||||
return texts
|
return texts
|
||||||
|
|
||||||
def is_area(self, tags: dict[str, str]) -> bool:
|
def is_area(self, tags: dict[str, str]) -> bool:
|
||||||
"""
|
"""Check whether way described by tags is area."""
|
||||||
Check whether way described by tags is area.
|
|
||||||
"""
|
|
||||||
for matcher in self.area_matchers:
|
for matcher in self.area_matchers:
|
||||||
if matcher.is_matched(tags):
|
if matcher.is_matched(tags):
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
"""
|
||||||
|
Röntgen tile server for sloppy maps.
|
||||||
|
"""
|
||||||
import logging
|
import logging
|
||||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
@ -16,7 +19,9 @@ class Handler(BaseHTTPRequestHandler):
|
||||||
HTTP request handler that process sloppy map tile requests.
|
HTTP request handler that process sloppy map tile requests.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, request, client_address, server):
|
def __init__(
|
||||||
|
self, request: bytes, client_address: tuple[str, int], server
|
||||||
|
):
|
||||||
super().__init__(request, client_address, server)
|
super().__init__(request, client_address, server)
|
||||||
self.cache: Path = Path("cache")
|
self.cache: Path = Path("cache")
|
||||||
self.update_cache: bool = False
|
self.update_cache: bool = False
|
||||||
|
@ -49,7 +54,8 @@ class Handler(BaseHTTPRequestHandler):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
def ui(options):
|
def ui(options) -> None:
|
||||||
|
"""Command-line interface for tile server."""
|
||||||
server: Optional[HTTPServer] = None
|
server: Optional[HTTPServer] = None
|
||||||
try:
|
try:
|
||||||
port: int = 8080
|
port: int = 8080
|
||||||
|
|
|
@ -72,11 +72,13 @@ class TaginfoProjectFile:
|
||||||
tags.append(tag)
|
tags.append(tag)
|
||||||
|
|
||||||
def write(self) -> None:
|
def write(self) -> None:
|
||||||
|
"""Write Taginfo JSON file."""
|
||||||
with self.path.open("w+") as output_file:
|
with self.path.open("w+") as output_file:
|
||||||
json.dump(self.structure, output_file, indent=4, sort_keys=True)
|
json.dump(self.structure, output_file, indent=4, sort_keys=True)
|
||||||
|
|
||||||
|
|
||||||
def write_taginfo_project_file(scheme: Scheme) -> None:
|
def write_taginfo_project_file(scheme: Scheme) -> None:
|
||||||
|
"""Write Taginfo JSON file."""
|
||||||
out_file: Path = workspace.get_taginfo_file_path()
|
out_file: Path = workspace.get_taginfo_file_path()
|
||||||
logging.info(f"Write Röntgen project file for Taginfo to {out_file}...")
|
logging.info(f"Write Röntgen project file for Taginfo to {out_file}...")
|
||||||
taginfo_project_file: TaginfoProjectFile = TaginfoProjectFile(
|
taginfo_project_file: TaginfoProjectFile = TaginfoProjectFile(
|
||||||
|
|
|
@ -7,7 +7,7 @@ import logging
|
||||||
import sys
|
import sys
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional, Tuple
|
from typing import Optional
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import svgwrite
|
import svgwrite
|
||||||
|
@ -174,7 +174,7 @@ class Tile:
|
||||||
lat_deg: np.ndarray = np.degrees(lat_rad)
|
lat_deg: np.ndarray = np.degrees(lat_rad)
|
||||||
return np.array((lat_deg, lon_deg))
|
return np.array((lat_deg, lon_deg))
|
||||||
|
|
||||||
def get_boundary_box(self) -> Tuple[np.array, np.array]:
|
def get_boundary_box(self) -> tuple[np.array, np.array]:
|
||||||
"""
|
"""
|
||||||
Get geographical boundary box of the tile: north-west and south-east
|
Get geographical boundary box of the tile: north-west and south-east
|
||||||
points.
|
points.
|
||||||
|
@ -272,9 +272,7 @@ class Tile:
|
||||||
|
|
||||||
|
|
||||||
def ui(options) -> None:
|
def ui(options) -> None:
|
||||||
"""
|
"""Simple user interface for tile generation."""
|
||||||
Simple user interface for tile generation.
|
|
||||||
"""
|
|
||||||
directory: Path = workspace.get_tile_path()
|
directory: Path = workspace.get_tile_path()
|
||||||
|
|
||||||
if options.coordinates:
|
if options.coordinates:
|
||||||
|
|
|
@ -9,16 +9,16 @@ __email__ = "me@enzet.ru"
|
||||||
|
|
||||||
def test_style_empty() -> None:
|
def test_style_empty() -> None:
|
||||||
"""Test constructing style of empty tags."""
|
"""Test constructing style of empty tags."""
|
||||||
assert SCHEME.get_style({}, 18) == []
|
assert SCHEME.get_style({}) == []
|
||||||
|
|
||||||
|
|
||||||
def test_style_unknown() -> None:
|
def test_style_unknown() -> None:
|
||||||
"""Test constructing style of unknown tags."""
|
"""Test constructing style of unknown tags."""
|
||||||
assert SCHEME.get_style({"aaa": "bbb"}, 18) == []
|
assert SCHEME.get_style({"aaa": "bbb"}) == []
|
||||||
|
|
||||||
|
|
||||||
def test_style_area() -> None:
|
def test_style_area() -> None:
|
||||||
"""Test constructing style of landuse=grass."""
|
"""Test constructing style of landuse=grass."""
|
||||||
style = SCHEME.get_style({"landuse": "grass"}, 18)
|
style = SCHEME.get_style({"landuse": "grass"})
|
||||||
assert len(style) == 1
|
assert len(style) == 1
|
||||||
assert style[0].style == {"fill": "#CFE0A8", "stroke": "#BFD098"}
|
assert style[0].style == {"fill": "#CFE0A8", "stroke": "#BFD098"}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue