Refactor constructor; change code style.

This commit is contained in:
Sergey Vartanov 2020-09-05 19:44:28 +03:00
parent 8509e3c0e2
commit 21be74a8a2
18 changed files with 759 additions and 683 deletions

View file

@ -5,10 +5,11 @@ from hashlib import sha256
from datetime import datetime
from typing import Any, Dict, List, Optional, Set
from roentgen import process, ui
from roentgen import ui
from roentgen.extract_icon import DEFAULT_SMALL_SHAPE_ID
from roentgen.flinger import Geo, GeoFlinger
from roentgen.osm_reader import OSMMember, OSMRelation, OSMWay
from roentgen.scheme import Scheme
from roentgen.scheme import IconSet, Scheme
class Node:
@ -16,17 +17,16 @@ class Node:
Node in Röntgen terms.
"""
def __init__(
self, shapes, tags: Dict[str, str], x: float, y: float, color: str,
path: Optional[str], processed, priority: int = 0):
self.shapes = shapes
self, icon_set: IconSet, tags: Dict[str, str],
point: (float, float), path: Optional[str],
priority: int = 0, is_for_node: bool = True):
self.icon_set: IconSet = icon_set
self.tags = tags
self.x = x
self.y = y
self.color = color
self.point = point
self.path = path
self.processed = processed
self.priority = priority
self.layer = 0
self.is_for_node = is_for_node
class Way:
@ -34,12 +34,12 @@ class Way:
Way in Röntgen terms.
"""
def __init__(
self, kind: str, nodes, path, style, layer: float = 0.0,
priority: float = 0, levels=None):
self, kind: str, nodes, path, style: Dict[str, Any],
layer: float = 0.0, priority: float = 0, levels=None):
self.kind = kind
self.nodes = nodes
self.path = path
self.style = style
self.style: Dict[str, Any] = style
self.layer = layer
self.priority = priority
self.levels = levels
@ -219,8 +219,10 @@ class Constructor:
nodes = None
center_point = None
if way:
c = line_center(
center_point = line_center(
map(lambda x: self.map_.node_map[x], way.nodes), self.flinger)
nodes = way.nodes
@ -230,8 +232,8 @@ class Constructor:
user_color = get_user_color(way.user, self.seed)
self.ways.append(
Way("way", nodes, path,
f"fill:none;stroke:#{user_color};"
f"stroke-width:1;"))
{"fill": "none", "stroke": "#" + user_color,
"stroke-width": 1}))
return
if self.mode == "time":
@ -240,339 +242,69 @@ class Constructor:
time_color = get_time_color(way.timestamp)
self.ways.append(
Way("way", nodes, path,
f"fill:none;stroke:#{time_color};"
f"stroke-width:1;"))
{"fill": "none", "stroke": "#" + time_color,
"stroke-width": 1}))
return
# Indoor features
if not tags:
return
if "indoor" in tags:
v = tags["indoor"]
style = \
f"stroke:#{self.color('indoor_border_color')};" \
f"stroke-width:1;"
if v == "area":
style += f"fill:#{self.color('indoor_color')};"
layer += 10
elif v == "corridor":
style += f"fill:#{self.color('indoor_color')};"
layer += 11
elif v in ["yes", "room", "elevator"]:
style += f"fill:#{self.color('indoor_color')};"
layer += 12
elif v == "column":
style += f"fill:#{self.color('indoor_border_color')};"
layer += 13
self.ways.append(Way("way", nodes, path, style, layer, 50))
# Natural
if "natural" in tags:
v = tags["natural"]
style = "stroke:none;"
if v == "wood":
style += f"fill:#{self.color('wood_color')};"
layer += 21
elif v == "grassland":
style = \
f"fill:#{self.color('grass_color')};" \
f"stroke:#{self.color('grass_border_color')};"
layer += 20
elif v == "scrub":
style += f"fill:#{self.color('wood_color')};"
layer += 21
elif v == "sand":
style += f"fill:#{self.color('sand_color')};"
layer += 20
elif v == "beach":
style += f"fill:#{self.color('beach_color')};"
layer += 20
elif v == "desert":
style += f"fill:#{self.color('desert_color')};"
layer += 20
elif v == "forest":
style += f"fill:#{self.color('wood_color')};"
layer += 21
elif v == "tree_row":
style += \
f"fill:none;stroke:#{self.color('wood_color')};" \
f"stroke-width:5;"
layer += 21
elif v == "water":
style = \
f"fill:#{self.color('water_color')};" \
f"stroke:#{self.color('water_border_color')};" \
f"stroke-width:1.0;"
layer += 21
self.ways.append(Way("way", nodes, path, style, layer, 50))
# Landuse
if "landuse" in tags:
style = "fill:none;stroke:none;"
if tags["landuse"] == "grass":
style = \
f"fill:#{self.color('grass_color')};" \
f"stroke:#{self.color('grass_border_color')};"
layer += 20
elif tags["landuse"] == "conservation":
style = f"fill:#{self.color('grass_color')};stroke:none;"
layer += 20
elif tags["landuse"] == "forest":
style = f"fill:#{self.color('wood_color')};stroke:none;"
layer += 20
elif tags["landuse"] == "garages":
style = f"fill:#{self.color('parking_color')};stroke:none;"
layer += 21
shapes, fill, processed = self.scheme.get_icon(tags)
if way:
self.nodes.append(Node(
shapes, tags, c[0], c[1], fill, path, processed))
elif tags["landuse"] == "construction":
layer += 20
style = f"fill:#{self.color('construction_color')};stroke:none;"
elif tags["landuse"] in ["residential", "commercial"]:
return
self.ways.append(Way("way", nodes, path, style, layer, 50))
# Building
appended = False
kind: str = "way"
levels = None
if "building" in tags:
layer += 40
levels = 1
if "building:levels" in tags:
levels = float(tags["building:levels"])
style = \
f"fill:#{self.color('building_color')};" \
f"stroke:#{self.color('building_border_color')};" \
f"opacity:1.0;"
shapes, fill, processed = self.scheme.get_icon(tags)
if "height" in tags:
try:
layer += float(tags["height"])
except ValueError:
pass
if way:
self.nodes.append(
Node(shapes, tags, c[0], c[1], fill, path, processed, 1))
self.ways.append(Way(
"building", nodes, path, style, layer, 50, levels))
kind = "building"
if "building:levels" in tags:
levels = float(tags["building:levels"])
# Amenity
if "amenity" in tags:
style = "fill:none;stroke:none;"
layer += 21
if tags["amenity"] == "parking":
style = \
f"fill:#{self.color('parking_color')};" \
f"stroke:none;opacity:0.5;"
shapes, fill, processed = self.scheme.get_icon(tags)
if way:
for element in self.scheme.ways: # type: Dict[str, Any]
matched: bool = True
for config_tag_key in element["tags"]: # type: str
matcher = element["tags"][config_tag_key]
if config_tag_key not in tags or \
(matcher != "*" and
tags[config_tag_key] != matcher and
tags[config_tag_key] not in matcher):
matched = False
break
if "no_tags" in element:
for config_tag_key in element["no_tags"]: # type: str
if config_tag_key in tags and \
tags[config_tag_key] == \
element["no_tags"][config_tag_key]:
matched = False
break
if matched:
style: Dict[str, Any] = {"fill": "none"}
if "layer" in element:
layer += element["layer"]
for key in element: # type: str
if key not in ["tags", "no_tags", "layer", "level", "icon"]:
value = element[key]
if isinstance(value, str) and value.endswith("_color"):
value = "#" + self.scheme.get_color(value)
style[key] = value
self.ways.append(
Way(kind, nodes, path, style, layer, 50, levels))
if center_point and way.is_cycle() or \
"area" in tags and tags["area"]:
icon_set: IconSet = self.scheme.get_icon(tags)
self.nodes.append(Node(
shapes, tags, c[0], c[1], fill, path, processed, 1))
self.ways.append(Way("way", nodes, path, style, layer, 50))
icon_set, tags, center_point, path, is_for_node=False))
appended = True
# Waterway
if not appended:
style: Dict[str, Any] = {
"fill": "none", "stroke": "#FF0000", "stroke-width": 1}
self.ways.append(Way(kind, nodes, path, style, layer, 50, levels))
if center_point and way.is_cycle() or \
"area" in tags and tags["area"]:
icon_set: IconSet = self.scheme.get_icon(tags)
self.nodes.append(Node(
icon_set, tags, center_point, path, is_for_node=False))
if "waterway" in tags:
style = "fill:none;stroke:none;"
layer += 21
if tags["waterway"] == "riverbank":
style = \
f"fill:#{self.color('water_color')};" \
f"stroke:#{self.color('water_border_color')};" \
f"stroke-width:1.0;"
elif tags["waterway"] == "river":
style = \
f"fill:none;stroke:#{self.color('water_color')};" \
f"stroke-width:10.0;"
self.ways.append(Way("way", nodes, path, style, layer, 50))
# Railway
if "railway" in tags:
layer += 41
v = tags["railway"]
style = \
"fill:none;stroke-dasharray:none;stroke-linejoin:round;" \
"stroke-linecap:round;stroke-width:"
if v == "subway":
style += "10;stroke:#DDDDDD;"
if v in ["narrow_gauge", "tram"]:
style += "2;stroke:#000000;"
if v == "platform":
style = \
f"fill:#{self.color('platform_color')};" \
f"stroke:#{self.color('platform_border_color')};" \
f"stroke-width:1;"
else:
return
self.ways.append(Way("way", nodes, path, style, layer, 50))
# Highway
if "highway" in tags:
layer += 42
v = tags["highway"]
style = \
f"fill:none;stroke:#{self.color('road_border_color')};" \
f"stroke-dasharray:none;stroke-linejoin:round;" \
f"stroke-linecap:round;stroke-width:"
# Highway outline
if v == "motorway":
style += "33"
elif v == "trunk":
style += "31"
elif v == "primary":
style += f"29;stroke:#{self.color('primary_border_color')};"
elif v == "secondary":
style += "27"
elif v == "tertiary":
style += "25"
elif v == "unclassified":
style += "17"
elif v == "residential":
style += "17"
elif v == "service":
if "service" in tags and tags["service"] == "parking_aisle":
style += "7"
else:
style += "11"
elif v == "track":
style += "3"
elif v in ["footway", "pedestrian", "cycleway"]:
if not ("area" in tags and tags["area"] == "yes"):
style += f"3;stroke:#{self.color('foot_border_color')};"
elif v in ["steps"]:
style += \
f"6;stroke:#{self.color('foot_border_color')};" \
f"stroke-linecap:butt;"
else:
style = None
if style:
style += ";"
self.ways.append(Way(
"way", nodes, path, style, layer + 41, 50))
# Highway main shape
style = "fill:none;stroke:#FFFFFF;stroke-linecap:round;" + \
"stroke-linejoin:round;stroke-width:"
if v == "motorway":
style += "31"
elif v == "trunk":
style += "29"
elif v == "primary":
style += "27;stroke:#" + self.color('primary_color')
elif v == "secondary":
style += "25"
elif v == "tertiary":
style += "23"
elif v == "unclassified":
style += "15"
elif v == "residential":
style += "15"
elif v == "service":
if "service" in tags and tags["service"] == "parking_aisle":
style += "5"
else:
style += "9"
elif v == "cycleway":
style += \
f"1;stroke-dasharray:8,2;istroke-linecap:butt;" \
f"stroke:#{self.color('cycle_color')}"
elif v in ["footway", "pedestrian"]:
if "area" in tags and tags["area"] == "yes":
style += "1;stroke:none;fill:#DDDDDD"
layer -= 55 # FIXME!
else:
style += \
"1.5;stroke-dasharray:7,3;stroke-linecap:round;stroke:#"
if "guide_strips" in tags and tags["guide_strips"] == "yes":
style += self.color('guide_strips_color')
else:
style += self.color('foot_color')
elif v == "steps":
style += "5;stroke-dasharray:1.5,2;stroke-linecap:butt;" + \
"stroke:#"
if "conveying" in tags:
style += "888888"
else:
style += self.color('foot_color')
elif v == "path":
style += "1;stroke-dasharray:5,5;stroke-linecap:butt;" + \
"stroke:#" + self.color('foot_color')
style += ";"
self.ways.append(Way("way", nodes, path, style, layer + 42, 50))
if "oneway" in tags and tags["oneway"] == "yes" or \
"conveying" in tags and tags["conveying"] == "forward":
for k in range(7):
self.ways.append(Way(
"way", nodes, path,
f"fill:none;stroke:#EEEEEE;stroke-linecap:butt;"
f"stroke-width:{7 - k};stroke-dasharray:{k},{40 - k};",
layer + 43, 50))
if "access" in tags and tags["access"] == "private":
self.ways.append(Way(
"way", nodes, path,
f"fill:none;stroke:#{self.color('private_access_color')};"
f"stroke-linecap:butt;stroke-width:10;stroke-dasharray:1,5;"
f"opacity:0.4;", layer + 0.1, 50))
# Leisure
if "leisure" in tags:
layer += 21
if tags["leisure"] == "playground":
style = f"fill:#{self.color('playground_color')};opacity:0.2;"
# FIXME!!!!!!!!!!!!!!!!!!!!!
# if nodes:
# self.draw_point_shape("toy_horse", c[0], c[1], "444444")
elif tags["leisure"] == "garden":
style = f"fill:#{self.color('grass_color')};"
elif tags["leisure"] == "pitch":
style = f"fill:#{self.color('playground_color')};opacity:0.2;"
elif tags["leisure"] == "park":
return
else:
style = "fill:#FF0000;opacity:0.2;"
self.ways.append(Way("way", nodes, path, style, layer, 50))
# Barrier
if "barrier" in tags:
style = "fill:none;stroke:none;"
layer += 40
if tags["barrier"] == "hedge":
style += \
f"fill:none;stroke:#{self.color('wood_color')};" \
f"stroke-width:4;"
elif tags["barrier"] == "fense":
style += "fill:none;stroke:#000000;stroke-width:1;opacity:0.4;"
elif tags["barrier"] == "kerb":
style += "fill:none;stroke:#000000;stroke-width:1;opacity:0.2;"
else:
style += "fill:none;stroke:#000000;stroke-width:1;opacity:0.3;"
self.ways.append(Way("way", nodes, path, style, layer, 50))
# Border
if "border" in tags:
style = "fill:none;stroke:none;"
style += "fill:none;stroke:#FF0000;stroke-width:0.5;" + \
"stroke-dahsarray:10,20;"
self.ways.append(Way("way", nodes, path, style, layer, 50))
if "area:highway" in tags:
style = "fill:none;stroke:none;"
if tags["area:highway"] == "yes":
style += "fill:#FFFFFF;stroke:#DDDDDD;stroke-width:1;"
self.ways.append(Way("way", nodes, path, style, layer, 50))
def construct_relations(self):
def construct_relations(self) -> None:
"""
Construct Röntgen ways from OSM relations.
"""
@ -603,7 +335,7 @@ class Constructor:
p += path + " "
self.construct_way(None, tags, p)
def construct_nodes(self):
def construct_nodes(self) -> None:
"""
Draw nodes.
"""
@ -618,33 +350,27 @@ class Constructor:
for node_id in s: # type: int
node_number += 1
ui.write_line(node_number, len(self.map_.node_map))
ui.progress_bar(node_number, len(self.map_.node_map))
node = self.map_.node_map[node_id]
flung = self.flinger.fling(Geo(node.lat, node.lon))
x = flung[0]
y = flung[1]
tags = node.tags
if not self.check_level(tags):
continue
shapes, fill, processed = self.scheme.get_icon(tags)
icon_set: IconSet = self.scheme.get_icon(tags)
if self.mode in ["time", "user-coloring"]:
if not tags:
continue
shapes = ["small"]
icon_set.icons = [[DEFAULT_SMALL_SHAPE_ID]]
if self.mode == "user-coloring":
fill = get_user_color(node.user, self.seed)
icon_set.color = get_user_color(node.user, self.seed)
if self.mode == "time":
fill = get_time_color(node.timestamp)
icon_set.color = get_time_color(node.timestamp)
if shapes == [] and tags != {}:
shapes = [["no"]]
self.nodes.append(Node(icon_set, tags, flung, None))
self.nodes.append(Node(
shapes, tags, x, y, fill, None, processed))
ui.write_line(-1, len(self.map_.node_map))
ui.progress_bar(-1, len(self.map_.node_map))
print("Nodes painted in " + str(datetime.now() - start_time) + ".")