mirror of
https://github.com/enzet/map-machine.git
synced 2025-05-25 15:06:32 +02:00
Issue #84: add primitive road connections.
This commit is contained in:
parent
b46e65f2ec
commit
aa82353f00
6 changed files with 258 additions and 150 deletions
|
@ -5,7 +5,6 @@ from typing import Any, Iterator, Optional
|
|||
|
||||
import numpy as np
|
||||
from colour import Color
|
||||
from shapely.geometry import LineString
|
||||
from svgwrite import Drawing
|
||||
from svgwrite.container import Group
|
||||
from svgwrite.path import Path
|
||||
|
@ -14,12 +13,13 @@ from map_machine.direction import DirectionSet, Sector
|
|||
from map_machine.drawing import PathCommands
|
||||
from map_machine.flinger import Flinger
|
||||
from map_machine.osm_reader import OSMNode, Tagged
|
||||
from map_machine.road import Lane
|
||||
from map_machine.scheme import LineStyle, RoadMatcher, Scheme
|
||||
from map_machine.scheme import LineStyle, Scheme
|
||||
|
||||
__author__ = "Sergey Vartanov"
|
||||
__email__ = "me@enzet.ru"
|
||||
|
||||
from map_machine.vector import Polyline
|
||||
|
||||
BUILDING_HEIGHT_SCALE: float = 2.5
|
||||
BUILDING_MINIMAL_HEIGHT: float = 8.0
|
||||
|
||||
|
@ -61,20 +61,6 @@ class Figure(Tagged):
|
|||
|
||||
return path
|
||||
|
||||
def get_outer_path(
|
||||
self, flinger: Flinger, parallel_offset: float = 0
|
||||
) -> str:
|
||||
"""Get path of the first outer node list."""
|
||||
points: list[tuple[float, float]] = [
|
||||
tuple(flinger.fling(x.coordinates)) for x in self.outers[0]
|
||||
]
|
||||
offset = LineString(points).parallel_offset(parallel_offset)
|
||||
|
||||
path: str = ""
|
||||
for index, point in enumerate(offset.coords):
|
||||
path += ("L" if index else "M") + f" {point[0]},{point[1]} "
|
||||
return path[:-1]
|
||||
|
||||
|
||||
class Building(Figure):
|
||||
"""
|
||||
|
@ -221,101 +207,6 @@ class StyledFigure(Figure):
|
|||
self.line_style: LineStyle = line_style
|
||||
|
||||
|
||||
class Road(Figure):
|
||||
"""
|
||||
Road or track on the map.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
tags: dict[str, str],
|
||||
inners: list[list[OSMNode]],
|
||||
outers: list[list[OSMNode]],
|
||||
matcher: RoadMatcher,
|
||||
) -> None:
|
||||
super().__init__(tags, inners, outers)
|
||||
self.matcher: RoadMatcher = matcher
|
||||
|
||||
self.width: Optional[float] = None
|
||||
self.lanes: list[Lane] = []
|
||||
|
||||
if "lanes" in tags:
|
||||
try:
|
||||
self.width = int(tags["lanes"]) * 3.7
|
||||
self.lanes = [Lane()] * int(tags["lanes"])
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
number: int
|
||||
if "lanes:forward" in tags:
|
||||
number = int(tags["lanes:forward"])
|
||||
[x.set_forward(True) for x in self.lanes[-number:]]
|
||||
if "lanes:backward" in tags:
|
||||
number = int(tags["lanes:backward"])
|
||||
[x.set_forward(False) for x in self.lanes[:number]]
|
||||
|
||||
if "width" in tags:
|
||||
try:
|
||||
self.width = float(tags["width"])
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
self.layer: float = 0
|
||||
if "layer" in tags:
|
||||
self.layer = float(tags["layer"])
|
||||
|
||||
def draw(
|
||||
self,
|
||||
svg: Drawing,
|
||||
flinger: Flinger,
|
||||
color: Color,
|
||||
extra_width: float = 0,
|
||||
) -> None:
|
||||
"""Draw road as simple SVG path."""
|
||||
flinger.get_scale()
|
||||
width: float
|
||||
if self.width is not None:
|
||||
width = self.width
|
||||
else:
|
||||
width = self.matcher.default_width
|
||||
cap: str = "round"
|
||||
if extra_width:
|
||||
cap = "butt"
|
||||
if self.tags.get("bridge") == "yes":
|
||||
color = Color("#666666")
|
||||
scale: float = flinger.get_scale(self.outers[0][0].coordinates)
|
||||
path_commands: str = self.get_path(flinger)
|
||||
path: Path = Path(d=path_commands)
|
||||
style: dict[str, Any] = {
|
||||
"fill": "none",
|
||||
"stroke": color.hex,
|
||||
"stroke-linecap": cap,
|
||||
"stroke-linejoin": "round",
|
||||
"stroke-width": scale * width + extra_width,
|
||||
}
|
||||
path.update(style)
|
||||
svg.add(path)
|
||||
|
||||
def draw_lanes(self, svg: Drawing, flinger: Flinger, color: Color) -> None:
|
||||
scale: float = flinger.get_scale(self.outers[0][0].coordinates)
|
||||
if len(self.lanes) < 2:
|
||||
return
|
||||
for index in range(1, len(self.lanes)):
|
||||
shift = scale * (
|
||||
-self.width / 2 + index * self.width / len(self.lanes)
|
||||
)
|
||||
path: Path = Path(d=self.get_outer_path(flinger, shift))
|
||||
style: dict[str, Any] = {
|
||||
"fill": "none",
|
||||
"stroke": color.hex,
|
||||
"stroke-linejoin": "round",
|
||||
"stroke-width": 1,
|
||||
"opacity": 0.5,
|
||||
}
|
||||
path.update(style)
|
||||
svg.add(path)
|
||||
|
||||
|
||||
class Crater(Tagged):
|
||||
"""
|
||||
Volcano or impact crater on the map.
|
||||
|
@ -510,14 +401,6 @@ def make_counter_clockwise(polygon: list[OSMNode]) -> list[OSMNode]:
|
|||
|
||||
def get_path(nodes: list[OSMNode], shift: np.ndarray, flinger: Flinger) -> str:
|
||||
"""Construct SVG path commands from nodes."""
|
||||
path: str = ""
|
||||
prev_node: Optional[OSMNode] = None
|
||||
for node in nodes:
|
||||
flung: np.ndarray = flinger.fling(node.coordinates) + shift
|
||||
path += ("L" if prev_node else "M") + f" {flung[0]},{flung[1]} "
|
||||
prev_node = node
|
||||
if nodes[0] == nodes[-1]:
|
||||
path += "Z"
|
||||
else:
|
||||
path = path[:-1]
|
||||
return path
|
||||
return Polyline(
|
||||
[flinger.fling(x.coordinates) + shift for x in nodes]
|
||||
).get_path()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue