From 9d41b342142ccf9548b1d86bddb02c55a8cee74a Mon Sep 17 00:00:00 2001 From: Sergey Vartanov Date: Fri, 28 May 2021 04:05:15 +0300 Subject: [PATCH] Issue #45: refactor road specification in scheme. Add special "road" part and move road specifications from the "ways". Add road matcher. We should remove "priority" key and use specifications order instead in the future. --- roentgen/constructor.py | 21 +-- roentgen/mapper.py | 22 ++- roentgen/scheme.py | 40 +++-- scheme/default.yml | 354 ++++++++++++++-------------------------- 4 files changed, 171 insertions(+), 266 deletions(-) diff --git a/roentgen/constructor.py b/roentgen/constructor.py index 036d749..9cf1598 100644 --- a/roentgen/constructor.py +++ b/roentgen/constructor.py @@ -19,7 +19,7 @@ from roentgen.osm_reader import ( Map, OSMMember, OSMNode, OSMRelation, OSMWay, Tagged ) from roentgen.point import Point -from roentgen.scheme import DEFAULT_COLOR, LineStyle, Scheme +from roentgen.scheme import DEFAULT_COLOR, LineStyle, Scheme, RoadMatcher from roentgen.util import MinMax __author__ = "Sergey Vartanov" @@ -30,12 +30,6 @@ TIME_COLOR_SCALE: List[Color] = [ Color("#581845"), Color("#900C3F"), Color("#C70039"), Color("#FF5733"), Color("#FFC300"), Color("#DAF7A6") ] -ROAD_HIGHWAY_VALUES: List[str] = [ - "motorway", "trunk", "primary", "secondary", "tertiary", "unclassified", - "residential", "motorway_link", "trunk_link", "primary_link", - "secondary_link", "tertiary_link", "living_street", "service", - "pedestrian", "track", "bus_guideway", "escape", "raceway", "road", "busway" -] def is_clockwise(polygon: List[OSMNode]) -> bool: @@ -175,11 +169,10 @@ class Road(Figure): """ def __init__( - self, tags: Dict[str, str], inners, outers, flinger: Flinger, - line_styles: List[LineStyle] + self, tags: Dict[str, str], inners, outers, matcher ): super().__init__(tags, inners, outers, None) - self.line_styles = line_styles + self.matcher: RoadMatcher = matcher def line_center(nodes: List[OSMNode], flinger: Flinger) -> np.array: @@ -387,12 +380,10 @@ class Constructor: Building(line.tags, inners, outers, self.flinger, self.scheme) ) - if ( - "highway" in line.tags - and line.tags["highway"] in ROAD_HIGHWAY_VALUES - ): + road_matcher = self.scheme.get_road(line.tags) + if road_matcher: self.roads.append( - Road(line.tags, inners, outers, self.flinger, line_styles) + Road(line.tags, inners, outers, road_matcher) ) return diff --git a/roentgen/mapper.py b/roentgen/mapper.py index a315e1a..cecf0b0 100644 --- a/roentgen/mapper.py +++ b/roentgen/mapper.py @@ -75,17 +75,33 @@ class Painter: ui.progress_bar(-1, 0, text="Drawing ways") roads = sorted( - constructor.roads, key=lambda x: x.line_styles[0].priority + constructor.roads, key=lambda x: x.matcher.priority ) for road in roads: path_commands: str = road.get_path(self.flinger) path = Path(d=path_commands) - path.update(road.line_styles[0].style) + path.update({ + "fill": "none", + "stroke": road.matcher.border_color.hex, + "stroke-linecap": "round", + "stroke-linejoin": "round", + "stroke-width": + road.matcher.default_width + * self.flinger.get_scale(road.outers[0][0].coordinates) + 2 + }) self.svg.add(path) for road in roads: path_commands: str = road.get_path(self.flinger) path = Path(d=path_commands) - path.update(road.line_styles[1].style) + path.update({ + "fill": "none", + "stroke": road.matcher.color.hex, + "stroke-linecap": "round", + "stroke-linejoin": "round", + "stroke-width": + road.matcher.default_width + * self.flinger.get_scale(road.outers[0][0].coordinates) + }) self.svg.add(path) # Trees diff --git a/roentgen/scheme.py b/roentgen/scheme.py index fe84e53..e7d72ff 100644 --- a/roentgen/scheme.py +++ b/roentgen/scheme.py @@ -163,22 +163,18 @@ class WayMatcher(Matcher): if "priority" in structure: self.priority = structure["priority"] - self.r = None - if "r" in structure: - self.r = structure["r"] - self.l = 0 - if "r1" in structure: - self.r = structure["r1"] - self.l = 1 - if "r2" in structure: - self.r = structure["r2"] - self.l = 2 - def get_style(self, scale): - if self.r: - return {**self.style, **{"stroke-width": self.r * scale + self.l}} - else: - return self.style +class RoadMatcher(Matcher): + def __init__(self, structure: Dict[str, Any], scheme): + super().__init__(structure) + self.border_color: Color = Color(scheme.get_color(structure["border_color"])) + self.color: Color = Color("white") + if "color" in structure: + self.color = Color(scheme.get_color(structure["color"])) + self.default_width: float = structure["default_width"] + self.priority: float = 0 + if "priority" in structure: + self.priority = structure["priority"] class Scheme: @@ -206,6 +202,9 @@ class Scheme: self.way_matchers: List[WayMatcher] = [ WayMatcher(x, self.colors) for x in content["ways"] ] + self.road_matchers: List[RoadMatcher] = [ + RoadMatcher(x, self) for x in content["roads"] + ] self.area_matchers: List[Matcher] = [ Matcher(x) for x in content["area_tags"] ] @@ -374,12 +373,17 @@ class Scheme: if not matcher.is_matched(tags): continue - line_styles.append( - LineStyle(matcher.get_style(scale), matcher.priority) - ) + line_styles.append(LineStyle(matcher.style, matcher.priority)) return line_styles + def get_road(self, tags: Dict[str, Any]) -> Optional[RoadMatcher]: + for matcher in self.road_matchers: + if not matcher.is_matched(tags): + continue + return matcher + return None + def construct_text( self, tags: Dict[str, str], draw_captions: str ) -> List[Label]: diff --git a/scheme/default.yml b/scheme/default.yml index c39a32f..6d1d1f6 100644 --- a/scheme/default.yml +++ b/scheme/default.yml @@ -822,6 +822,56 @@ node_icons: - tags: {crossing:island: "no"} add_shapes: [rectangle_vertical_rounded_crossed] +roads: + - tags: {highway: motorway} + default_width: 15 + border_color: road_border_color + color: "#FFFFFF" + - tags: {highway: trunk} + default_width: 13 + border_color: road_border_color + priority: 41 + - tags: {highway: primary} + default_width: 11 + border_color: primary_border_color + color: primary_color + priority: 41.9 + - tags: {highway: motorway_link} + default_width: 9 + border_color: road_border_color + priority: 41 + - tags: {highway: secondary} + default_width: 9 + border_color: secondary_border_color + priority: 41.8 + color: secondary_color + - tags: {highway: tertiary} + default_width: 7 + border_color: tertiary_border_color + priority: 41.7 + color: tertiary_color + - tags: {highway: unclassified} + default_width: 5 + border_color: road_border_color + priority: 41 + - tags: {highway: residential} + default_width: 5 + border_color: road_border_color + priority: 41 + - tags: {highway: living_street} + default_width: 4 + border_color: road_border_color + priority: 41 + - tags: {highway: service} + exception: {service: parking_aisle} + default_width: 3 + border_color: road_border_color + priority: 41 + - tags: {highway: service, service: parking_aisle} + default_width: 2 + border_color: road_border_color + priority: 41 + ways: - tags: {indoor: area} style: @@ -866,6 +916,79 @@ ways: opacity: 0.1 priority: 80 + - tags: {highway: track} + style: + stroke-width: 1.5 + stroke: track_color + stroke-linecap: round + stroke-linejoin: round + priority: 41 + - tags: {highway: [footway, pedestrian, cycleway]} + exception: {area: "yes"} + style: + stroke-width: 3 + stroke: foot_border_color + stroke-linecap: round + stroke-linejoin: round + priority: 41 + - tags: {highway: steps} + style: + stroke-width: 6 + stroke: foot_border_color + stroke-linecap: butt + - tags: {highway: path} + style: + stroke-width: 3 + stroke: foot_border_color + priority: 41 + + - tags: {highway: [footway, pedestrian]} + exception: {area: "yes"} + style: + stroke-width: 1.5 + stroke-dasharray: 7,3 + stroke-linecap: round + stroke-linejoin: round + stroke: foot_color + priority: 42 + - tags: {highway: [footway, pedestrian], area: "yes"} + style: + stroke: none + fill: "#DDDDDD" + stroke-linecap: round + stroke-linejoin: round + priority: -55 # FIXME + - tags: {highway: cycleway} + exception: {area: "yes"} + style: + stroke-width: 1 + stroke: cycle_color + stroke-dasharray: 8,2 + stroke-linecap: butt + priority: 42 + - tags: {highway: steps, conveying: "*"} + style: + stroke-width: 5 + stroke-dasharray: 1.5,2 + stroke-linecap: butt + stroke: "#888888" + priority: 42 + - tags: {highway: steps} + exception: {conveying: "*"} + style: + stroke-width: 5 + stroke-dasharray: 1.5,2 + stroke-linecap: butt + stroke: foot_color + priority: 42 + - tags: {highway: path} + style: + stroke-width: 1.5 + stroke-dasharray: 5,3 + stroke-linecap: butt + stroke: foot_color + priority: 42 + - tags: {natural: wood} style: fill: wood_color @@ -1004,7 +1127,7 @@ ways: - tags: {amenity: ferry_terminal} style: fill: ferry_terminal_color - priority: 50 + priority: 50 - tags: {amenity: parking} style: fill: parking_color @@ -1047,235 +1170,6 @@ ways: stroke: platform_border_color priority: 41 - - tags: {highway: motorway} - r2: 15 - style: - stroke: road_border_color - stroke-linecap: round - stroke-linejoin: round - priority: 41 - - tags: {highway: trunk} - r2: 13 - style: - stroke: road_border_color - stroke-linecap: round - stroke-linejoin: round - priority: 41 - - tags: {highway: primary} - r2: 11 - style: - stroke: primary_border_color - stroke-linecap: round - stroke-linejoin: round - priority: 41.9 - - tags: {highway: motorway_link} - r2: 9 - style: - stroke: road_border_color - stroke-linecap: round - stroke-linejoin: round - priority: 41 - - tags: {highway: secondary} - r2: 9 - style: - stroke: secondary_border_color - stroke-linecap: round - stroke-linejoin: round - priority: 41.8 - - tags: {highway: tertiary} - r2: 7 - style: - stroke: tertiary_border_color - stroke-linecap: round - stroke-linejoin: round - priority: 41.7 - - tags: {highway: unclassified} - r2: 5 - style: - stroke: road_border_color - stroke-linecap: round - stroke-linejoin: round - priority: 41 - - tags: {highway: residential} - r2: 5 - style: - stroke: road_border_color - stroke-linecap: round - stroke-linejoin: round - priority: 41 - - tags: {highway: living_street} - r2: 4 - style: - stroke: road_border_color - stroke-linecap: round - stroke-linejoin: round - priority: 41 - - tags: {highway: service} - exception: {service: parking_aisle} - r2: 3 - style: - stroke: road_border_color - stroke-linecap: round - stroke-linejoin: round - priority: 41 - - tags: {highway: service, service: parking_aisle} - r2: 2 - style: - stroke: road_border_color - stroke-linecap: round - stroke-linejoin: round - priority: 41 - - tags: {highway: track} - style: - stroke-width: 1.5 - stroke: track_color - stroke-linecap: round - stroke-linejoin: round - priority: 41 - - tags: {highway: [footway, pedestrian, cycleway]} - exception: {area: "yes"} - style: - stroke-width: 3 - stroke: foot_border_color - stroke-linecap: round - stroke-linejoin: round - priority: 41 - - tags: {highway: steps} - style: - stroke-width: 6 - stroke: foot_border_color - stroke-linecap: butt - - tags: {highway: path} - style: - stroke-width: 3 - stroke: foot_border_color - priority: 41 - - - tags: {highway: motorway} - r: 15 - style: - stroke: "#FFFFFF" - stroke-linecap: round - stroke-linejoin: round - priority: 42 - - tags: {highway: trunk} - r: 13 - style: - stroke: "#FFFFFF" - stroke-linecap: round - stroke-linejoin: round - priority: 42 - - tags: {highway: primary} - r: 11 - style: - stroke: primary_color - stroke-linecap: round - stroke-linejoin: round - priority: 42.9 - - tags: {highway: secondary} - r: 9 - style: - stroke: secondary_color - stroke-linecap: round - stroke-linejoin: round - priority: 42.8 - - tags: {highway: motorway_link} - r: 9 - style: - stroke: "#FFFFFF" - stroke-linecap: round - stroke-linejoin: round - priority: 42 - - tags: {highway: tertiary} - r: 7 - style: - stroke: tertiary_color - stroke-linecap: round - stroke-linejoin: round - priority: 42.7 - - tags: {highway: unclassified} - r: 5 - style: - stroke: "#FFFFFF" - stroke-linecap: round - stroke-linejoin: round - priority: 42 - - tags: {highway: residential} - r: 5 - style: - stroke: "#FFFFFF" - stroke-linecap: round - stroke-linejoin: round - priority: 42 - - tags: {highway: living_street} - r: 4 - style: - stroke: "#FFFFFF" - stroke-linecap: round - stroke-linejoin: round - priority: 42 - - tags: {highway: service} - exception: {service: parking_aisle} - r: 3 - style: - stroke: "#FFFFFF" - stroke-linecap: round - stroke-linejoin: round - priority: 42 - - tags: {highway: service, service: parking_aisle} - r: 2 - style: - stroke: "#FFFFFF" - stroke-linecap: round - stroke-linejoin: round - priority: 42 - - tags: {highway: [footway, pedestrian]} - exception: {area: "yes"} - style: - stroke-width: 1.5 - stroke-dasharray: 7,3 - stroke-linecap: round - stroke-linejoin: round - stroke: foot_color - priority: 42 - - tags: {highway: [footway, pedestrian], area: "yes"} - style: - stroke: none - fill: "#DDDDDD" - stroke-linecap: round - stroke-linejoin: round - priority: -55 # FIXME - - tags: {highway: cycleway} - exception: {area: "yes"} - style: - stroke-width: 1 - stroke: cycle_color - stroke-dasharray: 8,2 - stroke-linecap: butt - priority: 42 - - tags: {highway: steps, conveying: "*"} - style: - stroke-width: 5 - stroke-dasharray: 1.5,2 - stroke-linecap: butt - stroke: "#888888" - priority: 42 - - tags: {highway: steps} - exception: {conveying: "*"} - style: - stroke-width: 5 - stroke-dasharray: 1.5,2 - stroke-linecap: butt - stroke: foot_color - priority: 42 - - tags: {highway: path} - style: - stroke-width: 1.5 - stroke-dasharray: 5,3 - stroke-linecap: butt - stroke: foot_color - priority: 42 - - tags: {route: ferry} style: stroke-width: 1