Reformat with Black.

This commit is contained in:
Sergey Vartanov 2021-07-11 03:12:14 +03:00
parent 9613ec2cd4
commit 070ed05c8c
12 changed files with 157 additions and 117 deletions

View file

@ -32,7 +32,7 @@ class IconCollection:
extractor: ShapeExtractor,
background_color: Color = Color("white"),
color: Color = Color("black"),
add_unused: bool = False
add_unused: bool = False,
) -> "IconCollection":
"""
Collect all possible icon combinations in grid.
@ -89,11 +89,16 @@ class IconCollection:
for icon_2_id in matcher.with_icon:
for icon_3_id in matcher.with_icon:
current_set = (
[icon_id] + [icon_2_id] + [icon_3_id] +
matcher.over_icon
[icon_id]
+ [icon_2_id]
+ [icon_3_id]
+ matcher.over_icon
)
if (icon_2_id != icon_3_id and icon_2_id != icon_id and
icon_3_id != icon_id):
if (
icon_2_id != icon_3_id
and icon_2_id != icon_id
and icon_3_id != icon_id
):
add()
specified_ids: Set[str] = set()
@ -127,10 +132,13 @@ class IconCollection:
:param outline: if true, draw outline beneath the icon
"""
if by_name:
def get_file_name(x) -> str:
"""Generate human-readable file name."""
return f"Röntgen {' + '.join(x.get_names())}.svg"
else:
def get_file_name(x) -> str:
"""Generate file name with unique identifier."""
return f"{'___'.join(x.get_shape_ids())}.svg"
@ -167,8 +175,7 @@ class IconCollection:
for icon in self.icons:
icon: Icon
rectangle = svg.rect(
point - np.array((10, 10)), (20, 20),
fill=background_color.hex
point - np.array((10, 10)), (20, 20), fill=background_color.hex
)
svg.add(rectangle)
icon.draw(svg, point)
@ -189,8 +196,11 @@ class IconCollection:
for selector in self.selectors:
for target in ["node", "area"]:
s += target + selector + " {\n"
s += ' icon-image: "icons/' + "___".join(
self.selectors[selector].get_shape_ids()) + '.svg";\n'
s += (
' icon-image: "icons/'
+ "___".join(self.selectors[selector].get_shape_ids())
+ '.svg";\n'
)
s += " set icon_z17;\n"
s += " icon-width: 16;\n"
s += "}\n"
@ -213,9 +223,7 @@ def draw_icons() -> None:
icons_by_id_path: Path = out_path / "icons_by_id"
icons_by_name_path: Path = out_path / "icons_by_name"
for path in (
out_path, icons_by_id_path, icons_by_name_path
):
for path in (out_path, icons_by_id_path, icons_by_name_path):
path.mkdir(parents=True, exist_ok=True)
scheme: Scheme = Scheme(Path("scheme/default.yml"))
@ -245,9 +253,9 @@ def write_mapcss() -> None:
)
(out_path / "roentgen_icons").mkdir(exist_ok=True)
with Path("data/roentgen_icons_part.mapcss").open() as input_file:
with (
out_path / "roentgen_icons" / "roentgen_icons.mapcss"
).open("w+") as output_file:
with (out_path / "roentgen_icons" / "roentgen_icons.mapcss").open(
"w+"
) as output_file:
for line in input_file.readlines():
if line == "%CONTENT%\n":
output_file.write(collection.get_mapcss_selectors())

View file

@ -254,8 +254,12 @@ class ShapeSpecification:
use_outline = structure["outline"]
return cls(
shape, color, offset, flip_horizontally, flip_vertically,
use_outline
shape,
color,
offset,
flip_horizontally,
flip_vertically,
use_outline,
)
def is_default(self) -> bool:
@ -424,10 +428,9 @@ class Icon:
)
def __lt__(self, other) -> bool:
return (
"".join([x.shape.id_ for x in self.shape_specifications])
< "".join([x.shape.id_ for x in other.shape_specifications])
)
return "".join(
[x.shape.id_ for x in self.shape_specifications]
) < "".join([x.shape.id_ for x in other.shape_specifications])
@dataclass

View file

@ -47,7 +47,7 @@ class Painter:
show_missing_tags: bool = False,
overlap: int = 12,
mode: str = "normal",
label_mode: str = "main"
label_mode: str = "main",
):
self.show_missing_tags: bool = show_missing_tags
self.overlap: int = overlap
@ -100,15 +100,16 @@ class Painter:
occupied = None
else:
occupied = Occupied(
self.flinger.size[0], self.flinger.size[1], self.overlap)
self.flinger.size[0], self.flinger.size[1], self.overlap
)
nodes = sorted(constructor.points, key=lambda x: -x.priority)
steps: int = len(nodes)
for index, node in enumerate(nodes): # type: int, Point
if (node.get_tag("natural") == "tree" and
("diameter_crown" in node.tags or
"circumference" in node.tags)):
if node.get_tag("natural") == "tree" and (
"diameter_crown" in node.tags or "circumference" in node.tags
):
continue
ui.progress_bar(
index, steps * 3, step=10, text="Drawing main icons"
@ -142,6 +143,9 @@ class Painter:
("diameter_crown" in node.tags or
"circumference" in node.tags)):
continue
scale: float = self.flinger.get_scale(node.coordinates)
if "circumference" in node.tags:
if "diameter_crown" in node.tags:
opacity = 0.7
@ -149,16 +153,18 @@ class Painter:
else:
opacity = 0.3
radius = 2
self.svg.add(self.svg.circle(
self.svg.add(
self.svg.circle(
node.point,
radius * self.flinger.get_scale(node.coordinates),
radius * scale,
fill=self.scheme.get_color("evergreen_color"),
opacity=opacity))
self.svg.add(self.svg.circle(
node.point,
float(node.tags["circumference"]) / 2 / np.pi *
self.flinger.get_scale(node.coordinates),
fill="#B89A74"))
opacity=opacity,
)
)
radius = float(node.tags["circumference"]) / 2 / np.pi
self.svg.add(
self.svg.circle(node.point, radius * scale, fill="#B89A74")
)
def draw_buildings(self, constructor: Constructor) -> None:
"""
@ -311,7 +317,7 @@ class Painter:
"stroke": color.hex,
"stroke-linecap": "round",
"stroke-linejoin": "round",
"stroke-width": scale * width + extra_width
"stroke-width": scale * width + extra_width,
}
path.update(style)
self.svg.add(path)

View file

@ -31,9 +31,9 @@ def get_osm(
return result_file_name.open().read()
matcher = re.match(
"(?P<left>[0-9.-]*),(?P<bottom>[0-9.-]*)," +
"(?P<right>[0-9.-]*),(?P<top>[0-9.-]*)",
boundary_box
"(?P<left>[0-9.-]*),(?P<bottom>[0-9.-]*),"
+ "(?P<right>[0-9.-]*),(?P<top>[0-9.-]*)",
boundary_box,
)
if not matcher:
@ -61,7 +61,9 @@ def get_osm(
content = get_data(
"api.openstreetmap.org/api/0.6/map",
{"bbox": boundary_box}, is_secure=True)
{"bbox": boundary_box},
is_secure=True,
)
result_file_name.open("w+").write(content.decode("utf-8"))
@ -69,8 +71,8 @@ def get_osm(
def get_data(
address: str, parameters: Dict[str, str], is_secure: bool = False) \
-> bytes:
address: str, parameters: Dict[str, str], is_secure: bool = False
) -> bytes:
"""
Construct Internet page URL and get its descriptor.

View file

@ -450,6 +450,10 @@ class OSMReader:
"""
attributes = element.attrib
self.map_.view_box = MinMax(
np.array((float(attributes["minlat"]), float(attributes["minlon"]))),
np.array((float(attributes["maxlat"]), float(attributes["maxlon"])))
np.array(
(float(attributes["minlat"]), float(attributes["minlon"]))
),
np.array(
(float(attributes["maxlat"]), float(attributes["maxlon"]))
),
)

View file

@ -22,6 +22,7 @@ class Occupied:
Structure that remembers places of the canvas occupied by elements (icons,
texts, shapes).
"""
def __init__(self, width: int, height: int, overlap: float):
self.matrix = np.full((int(width), int(height)), False, dtype=bool)
self.width: float = width
@ -53,9 +54,16 @@ class Point(Tagged):
"""
def __init__(
self, icon_set: IconSet, labels: List[Label], tags: Dict[str, str],
processed: Set[str], point: np.array, coordinates: np.array,
priority: float = 0, is_for_node: bool = True, draw_outline: bool = True
self,
icon_set: IconSet,
labels: List[Label],
tags: Dict[str, str],
processed: Set[str],
point: np.array,
coordinates: np.array,
priority: float = 0,
is_for_node: bool = True,
draw_outline: bool = True,
):
super().__init__()
@ -81,10 +89,7 @@ class Point(Tagged):
"""
Draw main shape for one node.
"""
keys_left = [
x for x in self.tags.keys()
if x not in self.processed # and not self.is_no_drawable(x)
]
keys_left = [x for x in self.tags.keys() if x not in self.processed]
if (
self.icon_set.main_icon.is_default()
and not self.icon_set.extra_icons
@ -124,14 +129,19 @@ class Point(Tagged):
for icon in self.icon_set.extra_icons:
self.draw_point_shape(
svg, icon, self.point + np.array((left, self.y)),
occupied=occupied)
occupied=occupied
)
left += 16
if self.icon_set.extra_icons:
self.y += 16
def draw_point_shape(
self, svg: svgwrite.Drawing, icon: Icon, position,
occupied, tags: Optional[Dict[str, str]] = None
self,
svg: svgwrite.Drawing,
icon: Icon,
position,
occupied,
tags: Optional[Dict[str, str]] = None,
) -> bool:
"""
Draw one combined icon and its outline.
@ -180,7 +190,7 @@ class Point(Tagged):
for label in labels:
text = label.text
text = text.replace("&quot;", '"')
text = text.replace("&amp;", '&')
text = text.replace("&amp;", "&")
text = text[:26] + ("..." if len(text) > 26 else "")
self.draw_text(
svg, text, self.point + np.array((0, self.y + 2)),
@ -188,11 +198,18 @@ class Point(Tagged):
)
def draw_text(
self, svg: svgwrite.Drawing, text: str, point,
occupied: Optional[Occupied], fill: Color, size: float = 10.0,
out_fill=Color("white"), out_opacity: float = 0.5,
out_fill_2: Optional[Color] = None, out_opacity_2: float = 1.0,
is_debug: bool = False
self,
svg: svgwrite.Drawing,
text: str,
point,
occupied: Optional[Occupied],
fill: Color,
size: float = 10.0,
out_fill=Color("white"),
out_opacity: float = 0.5,
out_fill_2: Optional[Color] = None,
out_opacity_2: float = 1.0,
is_debug: bool = False,
) -> None:
"""
Drawing text.

View file

@ -4,9 +4,7 @@ from pathlib import Path
from typing import List
def rasterize(
from_: Path, to_: Path, area: str = "", dpi: float = 90
) -> None:
def rasterize(from_: Path, to_: Path, area: str = "", dpi: float = 90) -> None:
"""
Make PNG image out of SVG using Inkscape.
"""

View file

@ -25,6 +25,7 @@ class LineStyle:
"""
SVG line style and its priority.
"""
style: Dict[str, Union[int, float, str]]
priority: float = 0.0
@ -33,6 +34,7 @@ class MatchingType(Enum):
"""
Description on how tag was matched.
"""
NOT_MATCHED = 0
MATCHED_BY_SET = 1
MATCHED_BY_WILDCARD = 2
@ -55,13 +57,13 @@ def is_matched_tag(
if matcher_tag_value == "*":
return MatchingType.MATCHED_BY_WILDCARD
if (
isinstance(matcher_tag_value, str) and
tags[matcher_tag_key] == matcher_tag_value
isinstance(matcher_tag_value, str)
and tags[matcher_tag_key] == matcher_tag_value
):
return MatchingType.MATCHED
if (
isinstance(matcher_tag_value, list) and
tags[matcher_tag_key] in matcher_tag_value
isinstance(matcher_tag_value, list)
and tags[matcher_tag_key] in matcher_tag_value
):
return MatchingType.MATCHED_BY_SET
return MatchingType.NOT_MATCHED
@ -71,6 +73,7 @@ class Matcher:
"""
Tag matching.
"""
def __init__(self, structure: Dict[str, Any]):
self.tags: Dict[str, str] = structure["tags"]
@ -98,8 +101,8 @@ class Matcher:
config_tag_key: str
tag_matcher = self.tags[config_tag_key]
if (
is_matched_tag(config_tag_key, tag_matcher, tags) ==
MatchingType.NOT_MATCHED
is_matched_tag(config_tag_key, tag_matcher, tags)
== MatchingType.NOT_MATCHED
):
matched = False
break
@ -109,8 +112,8 @@ class Matcher:
config_tag_key: str
tag_matcher = self.exception[config_tag_key]
if (
is_matched_tag(config_tag_key, tag_matcher, tags) !=
MatchingType.NOT_MATCHED
is_matched_tag(config_tag_key, tag_matcher, tags)
!= MatchingType.NOT_MATCHED
):
matched = False
break
@ -122,6 +125,7 @@ class NodeMatcher(Matcher):
"""
Tag specification matcher.
"""
def __init__(self, structure: Dict[str, Any]):
# Dictionary with tag keys and values, value lists, or "*"
super().__init__(structure)
@ -167,6 +171,7 @@ class WayMatcher(Matcher):
"""
Special tag matcher for ways.
"""
def __init__(self, structure: Dict[str, Any], scheme: "Scheme"):
super().__init__(structure)
self.style: Dict[str, Any] = {"fill": "none"}
@ -186,6 +191,7 @@ class RoadMatcher(Matcher):
"""
Special tag matcher for highways.
"""
def __init__(self, structure: Dict[str, Any], scheme: "Scheme"):
super().__init__(structure)
self.border_color: Color = Color(
@ -206,6 +212,7 @@ class Scheme:
Specifies map colors and rules to draw icons for OpenStreetMap tags.
"""
def __init__(self, file_name: Path):
"""
:param file_name: name of the scheme file with tags, colors, and tag key
@ -266,7 +273,7 @@ class Scheme:
if key in self.tags_to_write or key in self.tags_to_skip:
return True
for prefix in self.prefix_to_write + self.prefix_to_skip: # type: str
if key[:len(prefix) + 1] == f"{prefix}:":
if key[: len(prefix) + 1] == f"{prefix}:":
return True
return False
@ -282,7 +289,7 @@ class Scheme:
if key in self.tags_to_write:
return True
for prefix in self.prefix_to_write: # type: str
if key[:len(prefix) + 1] == f"{prefix}:":
if key[: len(prefix) + 1] == f"{prefix}:":
return True
return False
@ -361,8 +368,7 @@ class Scheme:
processed.add("material")
for tag_key in tags: # type: str
if (tag_key.endswith(":color") or
tag_key.endswith(":colour")):
if tag_key.endswith(":color") or tag_key.endswith(":colour"):
color = self.get_color(tags[tag_key])
processed.add(tag_key)
@ -375,7 +381,8 @@ class Scheme:
main_icon.recolor(color)
keys_left = [
x for x in tags.keys()
x
for x in tags.keys()
if x not in processed and not self.is_no_drawable(x)
]

View file

@ -11,9 +11,7 @@ class Handler(BaseHTTPRequestHandler):
update_cache: bool = False
def __init__(
self, request, client_address, server
):
def __init__(self, request, client_address, server):
super().__init__(request, client_address, server)
def write(self, message):

View file

@ -17,6 +17,7 @@ class Label:
"""
Text label.
"""
text: str
fill: Color = DEFAULT_COLOR
size: float = 10.0
@ -46,7 +47,7 @@ def get_address(
if "addr:street" in tags:
street = tags["addr:street"]
if street.startswith("улица "):
street = "ул. " + street[len("улица "):]
street = "ул. " + street[len("улица ") :]
address.append(street)
processed.add("addr:street")

View file

@ -23,62 +23,57 @@ def parse_options(args) -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument(
"-i", "--input",
"-i",
"--input",
dest="input_file_name",
metavar="<path>",
nargs="*",
help="input XML file name (if not specified, file will be downloaded "
"using OpenStreetMap API)")
"using OpenStreetMap API)",
)
parser.add_argument(
"-o", "--output",
"-o",
"--output",
dest="output_file_name",
metavar="<path>",
default="map.svg",
help="output SVG file name (map.svg by default)")
help="output SVG file name (map.svg by default)",
)
parser.add_argument(
"-b", "--boundary-box",
"-b",
"--boundary-box",
dest="boundary_box",
metavar="<lon1>,<lat1>,<lon2>,<lat2>",
help="geo boundary box, use space before \"-\" for negative values")
help='geo boundary box, use space before "-" for negative values',
)
parser.add_argument(
"-s", "--scale",
"-s",
"--scale",
metavar="<float>",
help="OSM zoom level (may not be integer, default is 18)",
default=18,
dest="scale",
type=float)
type=float,
)
parser.add_argument(
"--cache",
help="path for temporary OSM files",
default="cache"
"--cache", help="path for temporary OSM files", default="cache"
)
parser.add_argument(
"--labels",
help="label drawing mode: `no`, `main`, or `all`",
dest="label_mode",
default="main")
default="main",
)
parser.add_argument(
"--show-missing-tags",
dest="show_missing_tags",
action="store_true")
"--show-missing-tags", dest="show_missing_tags", action="store_true"
)
parser.add_argument(
"--no-show-missing-tags",
dest="show_missing_tags",
action="store_false")
parser.add_argument(
"--overlap",
dest="overlap",
default=12,
type=int)
parser.add_argument(
"--mode",
default="normal")
parser.add_argument(
"--seed",
default="")
parser.add_argument(
"--level",
default=None)
"--no-show-missing-tags", dest="show_missing_tags", action="store_false"
)
parser.add_argument("--overlap", dest="overlap", default=12, type=int)
parser.add_argument("--mode", default="normal")
parser.add_argument("--seed", default="")
parser.add_argument("--level", default=None)
arguments: argparse.Namespace = parser.parse_args(args[1:])

View file

@ -13,6 +13,7 @@ class MinMax:
"""
Minimum and maximum.
"""
min_: Any = None
max_: Any = None