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.
This commit is contained in:
Sergey Vartanov 2021-05-28 04:05:15 +03:00
parent 38925e3a71
commit 9d41b34214
4 changed files with 171 additions and 266 deletions

View file

@ -19,7 +19,7 @@ from roentgen.osm_reader import (
Map, OSMMember, OSMNode, OSMRelation, OSMWay, Tagged Map, OSMMember, OSMNode, OSMRelation, OSMWay, Tagged
) )
from roentgen.point import Point 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 from roentgen.util import MinMax
__author__ = "Sergey Vartanov" __author__ = "Sergey Vartanov"
@ -30,12 +30,6 @@ TIME_COLOR_SCALE: List[Color] = [
Color("#581845"), Color("#900C3F"), Color("#C70039"), Color("#FF5733"), Color("#581845"), Color("#900C3F"), Color("#C70039"), Color("#FF5733"),
Color("#FFC300"), Color("#DAF7A6") 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: def is_clockwise(polygon: List[OSMNode]) -> bool:
@ -175,11 +169,10 @@ class Road(Figure):
""" """
def __init__( def __init__(
self, tags: Dict[str, str], inners, outers, flinger: Flinger, self, tags: Dict[str, str], inners, outers, matcher
line_styles: List[LineStyle]
): ):
super().__init__(tags, inners, outers, None) 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: 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) Building(line.tags, inners, outers, self.flinger, self.scheme)
) )
if ( road_matcher = self.scheme.get_road(line.tags)
"highway" in line.tags if road_matcher:
and line.tags["highway"] in ROAD_HIGHWAY_VALUES
):
self.roads.append( self.roads.append(
Road(line.tags, inners, outers, self.flinger, line_styles) Road(line.tags, inners, outers, road_matcher)
) )
return return

View file

@ -75,17 +75,33 @@ class Painter:
ui.progress_bar(-1, 0, text="Drawing ways") ui.progress_bar(-1, 0, text="Drawing ways")
roads = sorted( roads = sorted(
constructor.roads, key=lambda x: x.line_styles[0].priority constructor.roads, key=lambda x: x.matcher.priority
) )
for road in roads: for road in roads:
path_commands: str = road.get_path(self.flinger) path_commands: str = road.get_path(self.flinger)
path = Path(d=path_commands) 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) self.svg.add(path)
for road in roads: for road in roads:
path_commands: str = road.get_path(self.flinger) path_commands: str = road.get_path(self.flinger)
path = Path(d=path_commands) 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) self.svg.add(path)
# Trees # Trees

View file

@ -163,22 +163,18 @@ class WayMatcher(Matcher):
if "priority" in structure: if "priority" in structure:
self.priority = structure["priority"] 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): class RoadMatcher(Matcher):
if self.r: def __init__(self, structure: Dict[str, Any], scheme):
return {**self.style, **{"stroke-width": self.r * scale + self.l}} super().__init__(structure)
else: self.border_color: Color = Color(scheme.get_color(structure["border_color"]))
return self.style 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: class Scheme:
@ -206,6 +202,9 @@ class Scheme:
self.way_matchers: List[WayMatcher] = [ self.way_matchers: List[WayMatcher] = [
WayMatcher(x, self.colors) for x in content["ways"] 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] = [ self.area_matchers: List[Matcher] = [
Matcher(x) for x in content["area_tags"] Matcher(x) for x in content["area_tags"]
] ]
@ -374,12 +373,17 @@ class Scheme:
if not matcher.is_matched(tags): if not matcher.is_matched(tags):
continue continue
line_styles.append( line_styles.append(LineStyle(matcher.style, matcher.priority))
LineStyle(matcher.get_style(scale), matcher.priority)
)
return line_styles 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( def construct_text(
self, tags: Dict[str, str], draw_captions: str self, tags: Dict[str, str], draw_captions: str
) -> List[Label]: ) -> List[Label]:

View file

@ -822,6 +822,56 @@ node_icons:
- tags: {crossing:island: "no"} - tags: {crossing:island: "no"}
add_shapes: [rectangle_vertical_rounded_crossed] 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: ways:
- tags: {indoor: area} - tags: {indoor: area}
style: style:
@ -866,6 +916,79 @@ ways:
opacity: 0.1 opacity: 0.1
priority: 80 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} - tags: {natural: wood}
style: style:
fill: wood_color fill: wood_color
@ -1004,7 +1127,7 @@ ways:
- tags: {amenity: ferry_terminal} - tags: {amenity: ferry_terminal}
style: style:
fill: ferry_terminal_color fill: ferry_terminal_color
priority: 50 priority: 50
- tags: {amenity: parking} - tags: {amenity: parking}
style: style:
fill: parking_color fill: parking_color
@ -1047,235 +1170,6 @@ ways:
stroke: platform_border_color stroke: platform_border_color
priority: 41 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} - tags: {route: ferry}
style: style:
stroke-width: 1 stroke-width: 1