Issue #63: support ways, areas, and relations.

This commit is contained in:
Sergey Vartanov 2021-07-29 23:38:11 +03:00
parent 6635a5de4a
commit 0748bab9a5
9 changed files with 73 additions and 37 deletions

View file

@ -107,10 +107,6 @@ def main(options) -> None:
Path(ICONS_FILE_NAME), Path("icons/config.json") Path(ICONS_FILE_NAME), Path("icons/config.json")
) )
def check_level(x) -> bool:
"""Draw objects on all levels."""
return True
if options.level: if options.level:
if options.level == "overground": if options.level == "overground":
check_level = check_level_overground check_level = check_level_overground

View file

@ -1,7 +1,6 @@
""" """
Construct Röntgen nodes and ways. Construct Röntgen nodes and ways.
""" """
from collections import Counter
from datetime import datetime from datetime import datetime
from hashlib import sha256 from hashlib import sha256
from typing import Any, Dict, Iterator, List, Optional, Set from typing import Any, Dict, Iterator, List, Optional, Set

View file

@ -1,9 +1,9 @@
""" """
Icon grid drawing. Icon grid drawing.
""" """
from dataclasses import dataclass, field from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from typing import Dict, List, Optional, Set from typing import List, Optional, Set
import logging import logging
import numpy as np import numpy as np

View file

@ -2,7 +2,7 @@
MapCSS scheme creation. MapCSS scheme creation.
""" """
from pathlib import Path from pathlib import Path
from typing import Dict, List, Optional from typing import List, Optional, Dict
import logging import logging
from colour import Color from colour import Color
@ -23,13 +23,8 @@ class MapCSSWriter:
self.add_icons_for_lifecycle = add_icons_for_lifecycle self.add_icons_for_lifecycle = add_icons_for_lifecycle
self.icon_directory_name = icon_directory_name self.icon_directory_name = icon_directory_name
self.matchers: Dict[Matcher, List[str]] = {} self.point_matchers: List[Matcher] = scheme.node_matchers
for matcher in scheme.node_matchers: self.line_matchers: List[Matcher] = scheme.way_matchers
if matcher.shapes and not matcher.location_restrictions:
self.matchers[matcher] = [
(x if isinstance(x, str) else x["shape"])
for x in matcher.shapes
]
def add_selector( def add_selector(
self, self,
@ -38,15 +33,40 @@ class MapCSSWriter:
prefix: str = "", prefix: str = "",
opacity: Optional[float] = None, opacity: Optional[float] = None,
) -> str: ) -> str:
selector = ( elements: Dict[str, str] = {}
target + matcher.get_mapcss_selector(prefix) + " {\n"
f' icon-image: "{self.icon_directory_name}/' clean_shapes = matcher.get_clean_shapes()
+ "___".join(self.matchers[matcher]) if clean_shapes:
+ '.svg";\n' elements["icon-image"] = (
f'"{self.icon_directory_name}/'
+ "___".join(clean_shapes) + '.svg"'
) )
if opacity is not None: if opacity is not None:
selector += f" icon-opacity: {opacity:.2f};\n" elements["icon-opacity"] = f"{opacity:.2f}"
style = matcher.get_style()
if style:
if "fill" in style:
elements["fill-color"] = style["fill"]
if "stroke" in style:
elements["color"] = style["stroke"]
if "stroke-width" in style:
elements["width"] = style["stroke-width"]
if "stroke-dasharray" in style:
elements["dashes"] = style["stroke-dasharray"]
if "opacity" in style:
elements["fill-opacity"] = style["opacity"]
elements["opacity"] = style["opacity"]
if not elements:
return ""
selector: str = target + matcher.get_mapcss_selector(prefix) + " {\n"
for element in elements:
selector += f" {element}: {elements[element]};\n"
selector += "}\n" selector += "}\n"
return selector return selector
def write(self, output_file) -> None: def write(self, output_file) -> None:
@ -58,7 +78,11 @@ class MapCSSWriter:
output_file.write("\n") output_file.write("\n")
for matcher in self.matchers: for line_matcher in self.line_matchers:
for target in ["way", "relation"]:
output_file.write(self.add_selector(target, line_matcher))
for matcher in self.point_matchers:
for target in ["node", "area"]: for target in ["node", "area"]:
output_file.write(self.add_selector(target, matcher)) output_file.write(self.add_selector(target, matcher))
@ -67,7 +91,7 @@ class MapCSSWriter:
for index, stage_of_decay in enumerate(STAGES_OF_DECAY): for index, stage_of_decay in enumerate(STAGES_OF_DECAY):
opacity: float = 0.6 - 0.4 * index / (len(STAGES_OF_DECAY) - 1) opacity: float = 0.6 - 0.4 * index / (len(STAGES_OF_DECAY) - 1)
for matcher in self.matchers: for matcher in self.point_matchers:
if len(matcher.tags) > 1: if len(matcher.tags) > 1:
continue continue
for target in ["node", "area"]: for target in ["node", "area"]:

View file

@ -51,9 +51,13 @@ class ArgumentParser(argparse.ArgumentParser):
if "help" in option: if "help" in option:
help_value: List = [option["help"]] help_value: List = [option["help"]]
if "default" in option and option["default"] and option["default"] != "==SUPPRESS==": if (
"default" in option
and option["default"]
and option["default"] != "==SUPPRESS=="
):
help_value += [ help_value += [
f", default value: ", Tag("tt", [str(option['default'])]) ", default value: ", Tag("tt", [str(option['default'])])
] ]
row.append(help_value) row.append(help_value)
else: else:

View file

@ -137,7 +137,15 @@ class Matcher:
See https://wiki.openstreetmap.org/wiki/MapCSS/0.2 See https://wiki.openstreetmap.org/wiki/MapCSS/0.2
""" """
return "".join([get_selector(x, y, prefix) for (x, y) in self.tags.items()]) return "".join(
[get_selector(x, y, prefix) for (x, y) in self.tags.items()]
)
def get_clean_shapes(self):
return None
def get_style(self):
return None
class NodeMatcher(Matcher): class NodeMatcher(Matcher):
@ -177,6 +185,11 @@ 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):
if not self.shapes:
return
return [(x if isinstance(x, str) else x["shape"]) for x in self.shapes]
class WayMatcher(Matcher): class WayMatcher(Matcher):
""" """
@ -197,6 +210,9 @@ class WayMatcher(Matcher):
if "priority" in structure: if "priority" in structure:
self.priority = structure["priority"] self.priority = structure["priority"]
def get_style(self):
return self.style
class RoadMatcher(Matcher): class RoadMatcher(Matcher):
""" """
@ -391,11 +407,11 @@ class Scheme:
if main_icon and color: if main_icon and color:
main_icon.recolor(color) main_icon.recolor(color)
keys_left = [ # keys_left = [
x # x
for x in tags.keys() # for x in tags.keys()
if x not in processed and not self.is_no_drawable(x) # if x not in processed and not self.is_no_drawable(x)
] # ]
default_shape = icon_extractor.get_shape(DEFAULT_SHAPE_ID) default_shape = icon_extractor.get_shape(DEFAULT_SHAPE_ID)
if not main_icon: if not main_icon:

View file

@ -6,7 +6,7 @@ See https://wiki.openstreetmap.org/wiki/Taginfo/Projects
import json import json
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Dict, List from typing import List
import logging import logging

View file

@ -3,7 +3,6 @@ Tile generation.
See https://wiki.openstreetmap.org/wiki/Tiles See https://wiki.openstreetmap.org/wiki/Tiles
""" """
import argparse
import sys import sys
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path from pathlib import Path

View file

@ -13,5 +13,3 @@ SCHEME: Scheme = Scheme(Path("scheme/default.yml"))
SHAPE_EXTRACTOR: ShapeExtractor = ShapeExtractor( SHAPE_EXTRACTOR: ShapeExtractor = ShapeExtractor(
Path("icons/icons.svg"), Path("icons/config.json") Path("icons/icons.svg"), Path("icons/config.json")
) )