Refactor road scale computing.

This commit is contained in:
Sergey Vartanov 2021-11-08 00:41:41 +03:00
parent 3b83cf15e6
commit a60b3493b5

View file

@ -428,10 +428,14 @@ class Road(Tagged):
self.layer = float(tags["layer"]) self.layer = float(tags["layer"])
self.placement_offset: float = 0.0 self.placement_offset: float = 0.0
self.transition: bool = False
if "placement" in tags: if "placement" in tags:
value: str = tags["placement"] value: str = tags["placement"]
if ":" in value: if value == "transition":
place, lane = value.split(":") self.is_transition = True
elif ":" in value and len(parts := value.split(":")) == 2:
place, lane = parts
lane_number: int = int(lane) lane_number: int = int(lane)
self.placement_offset = ( self.placement_offset = (
sum( sum(
@ -454,7 +458,7 @@ class Road(Tagged):
logging.error(f"Unknown placement `{place}`.") logging.error(f"Unknown placement `{place}`.")
def get_style( def get_style(
self, flinger: Flinger, is_border: bool, is_for_stroke: bool = False self, is_border: bool, is_for_stroke: bool = False
) -> dict[str, Union[int, float, str]]: ) -> dict[str, Union[int, float, str]]:
"""Get road SVG style.""" """Get road SVG style."""
width: float width: float
@ -480,13 +484,12 @@ class Road(Tagged):
if self.tags.get("embankment") == "yes": if self.tags.get("embankment") == "yes":
extra_width = 4.0 extra_width = 4.0
scale: float = flinger.get_scale(self.nodes[0].coordinates)
style: dict[str, Union[int, float, str]] = { style: dict[str, Union[int, float, str]] = {
"fill": "none", "fill": "none",
"stroke": color.hex, "stroke": color.hex,
"stroke-linecap": "butt", "stroke-linecap": "butt",
"stroke-linejoin": "round", "stroke-linejoin": "round",
"stroke-width": scale * width + extra_width + border_width, "stroke-width": self.scale * width + extra_width + border_width,
} }
if is_for_stroke: if is_for_stroke:
style["stroke-width"] = 2.0 + extra_width style["stroke-width"] = 2.0 + extra_width
@ -510,13 +513,11 @@ class Road(Tagged):
return None return None
def draw(self, svg: Drawing, flinger: Flinger, is_border: bool) -> None: def draw(self, svg: Drawing, is_border: bool) -> None:
"""Draw road as simple SVG path.""" """Draw road as simple SVG path."""
filter_: Filter = self.get_filter(svg, is_border) filter_: Filter = self.get_filter(svg, is_border)
style: dict[str, Union[int, float, str]] = self.get_style( style: dict[str, Union[int, float, str]] = self.get_style(is_border)
flinger, is_border
)
path_commands: str = self.line.get_path(self.placement_offset) path_commands: str = self.line.get_path(self.placement_offset)
path: Path path: Path
if filter_: if filter_:
@ -593,7 +594,6 @@ class Road(Tagged):
def get_curve_points( def get_curve_points(
road: Road, road: Road,
scale: float,
center: np.ndarray, center: np.ndarray,
road_end: np.ndarray, road_end: np.ndarray,
placement_offset: float, placement_offset: float,
@ -601,11 +601,12 @@ def get_curve_points(
) -> list[np.ndarray]: ) -> list[np.ndarray]:
""" """
:param road: road segment :param road: road segment
:param scale: current zoom scale
:param center: road intersection point :param center: road intersection point
:param road_end: end point of the road segment :param road_end: end point of the road segment
:param placement_offset: offset based on placement tag value
:param is_end: whether the point represents road end
""" """
width: float = road.width / 2.0 * scale width: float = road.width / 2.0 * road.scale
direction: np.ndarray = (center - road_end) / np.linalg.norm( direction: np.ndarray = (center - road_end) / np.linalg.norm(
center - road_end center - road_end
@ -623,15 +624,12 @@ def get_curve_points(
class Connector: class Connector:
""" """Two roads connection."""
Two roads connection.
"""
def __init__( def __init__(
self, self,
connections: list[tuple[Road, int]], connections: list[tuple[Road, int]],
flinger: Flinger, flinger: Flinger,
scale: float,
) -> None: ) -> None:
self.connections: list[tuple[Road, int]] = connections self.connections: list[tuple[Road, int]] = connections
self.road_1: Road self.road_1: Road
@ -641,7 +639,7 @@ class Connector:
self.min_layer: float = min(x[0].layer for x in connections) self.min_layer: float = min(x[0].layer for x in connections)
self.max_layer: float = max(x[0].layer for x in connections) self.max_layer: float = max(x[0].layer for x in connections)
self.scale: float = scale self.scale: float = self.road_1.scale
self.flinger: Flinger = flinger self.flinger: Flinger = flinger
def draw(self, svg: Drawing) -> None: def draw(self, svg: Drawing) -> None:
@ -654,17 +652,14 @@ class Connector:
class SimpleConnector(Connector): class SimpleConnector(Connector):
""" """Simple connection between roads that don't change width."""
Simple connection between roads that don't change width.
"""
def __init__( def __init__(
self, self,
connections: list[tuple[Road, int]], connections: list[tuple[Road, int]],
flinger: Flinger, flinger: Flinger,
scale: float,
) -> None: ) -> None:
super().__init__(connections, flinger, scale) super().__init__(connections, flinger)
self.road_2: Road = connections[1][0] self.road_2: Road = connections[1][0]
self.index_2: int = connections[1][1] self.index_2: int = connections[1][1]
@ -698,14 +693,15 @@ class ComplexConnector(Connector):
self, self,
connections: list[tuple[Road, int]], connections: list[tuple[Road, int]],
flinger: Flinger, flinger: Flinger,
scale: float,
) -> None: ) -> None:
super().__init__(connections, flinger, scale) super().__init__(connections, flinger)
self.road_2: Road = connections[1][0] self.road_2: Road = connections[1][0]
self.index_2: int = connections[1][1] self.index_2: int = connections[1][1]
length: float = abs(self.road_2.width - self.road_1.width) * scale length: float = (
abs(self.road_2.width - self.road_1.width) * self.road_1.scale
)
self.road_1.line.shorten(self.index_1, length) self.road_1.line.shorten(self.index_1, length)
self.road_2.line.shorten(self.index_2, length) self.road_2.line.shorten(self.index_2, length)
@ -714,7 +710,6 @@ class ComplexConnector(Connector):
points_1: list[np.ndarray] = get_curve_points( points_1: list[np.ndarray] = get_curve_points(
self.road_1, self.road_1,
scale,
point, point,
self.road_1.line.points[self.index_1], self.road_1.line.points[self.index_1],
self.road_1.placement_offset, self.road_1.placement_offset,
@ -722,7 +717,6 @@ class ComplexConnector(Connector):
) )
points_2: list[np.ndarray] = get_curve_points( points_2: list[np.ndarray] = get_curve_points(
self.road_2, self.road_2,
scale,
point, point,
self.road_2.line.points[self.index_2], self.road_2.line.points[self.index_2],
self.road_2.placement_offset, self.road_2.placement_offset,
@ -768,22 +762,19 @@ class ComplexConnector(Connector):
) )
else: else:
path: Path = svg.path(d=["M"] + self.curve_1 + ["M"] + self.curve_2) path: Path = svg.path(d=["M"] + self.curve_1 + ["M"] + self.curve_2)
path.update(self.road_1.get_style(self.flinger, True, True)) path.update(self.road_1.get_style(True, True))
svg.add(path) svg.add(path)
class SimpleIntersection(Connector): class SimpleIntersection(Connector):
""" """Connection between more than two roads."""
Connection between more than two roads.
"""
def __init__( def __init__(
self, self,
connections: list[tuple[Road, int]], connections: list[tuple[Road, int]],
flinger: Flinger, flinger: Flinger,
scale: float,
) -> None: ) -> None:
super().__init__(connections, flinger, scale) super().__init__(connections, flinger)
def draw(self, svg: Drawing) -> None: def draw(self, svg: Drawing) -> None:
"""Draw connection fill.""" """Draw connection fill."""
@ -832,7 +823,6 @@ class Roads:
if not self.roads: if not self.roads:
return return
scale: float = flinger.get_scale(self.roads[0].nodes[0].coordinates)
layered_roads: dict[float, list[Road]] = {} layered_roads: dict[float, list[Road]] = {}
layered_connectors: dict[float, list[Connector]] = {} layered_connectors: dict[float, list[Connector]] = {}
@ -855,9 +845,9 @@ class Roads:
or index_1 not in [0, len(road_1.nodes) - 1] or index_1 not in [0, len(road_1.nodes) - 1]
or index_2 not in [0, len(road_2.nodes) - 1] or index_2 not in [0, len(road_2.nodes) - 1]
): ):
connector = SimpleConnector(connected, flinger, scale) connector = SimpleConnector(connected, flinger)
else: else:
connector = ComplexConnector(connected, flinger, scale) connector = ComplexConnector(connected, flinger)
else: else:
# We can also use SimpleIntersection(connected, flinger, scale) # We can also use SimpleIntersection(connected, flinger, scale)
# here. # here.
@ -884,7 +874,7 @@ class Roads:
# Draw borders. # Draw borders.
for road in roads: for road in roads:
road.draw(svg, flinger, True) road.draw(svg, True)
for connector in connectors: for connector in connectors:
if connector.min_layer == layer: if connector.min_layer == layer:
connector.draw_border(svg) connector.draw_border(svg)
@ -892,7 +882,7 @@ class Roads:
# Draw inner parts. # Draw inner parts.
for road in roads: for road in roads:
road.draw(svg, flinger, False) road.draw(svg, False)
for connector in connectors: for connector in connectors:
if connector.max_layer == layer: if connector.max_layer == layer:
connector.draw(svg) connector.draw(svg)