mirror of
https://github.com/enzet/map-machine.git
synced 2025-06-20 19:47:13 +02:00
Add groups to icon configuration.
This commit is contained in:
parent
5a9760f618
commit
c005dcc423
3 changed files with 524 additions and 950 deletions
|
@ -29,6 +29,7 @@ from map_machine.scheme import RoadMatcher
|
||||||
__author__ = "Sergey Vartanov"
|
__author__ = "Sergey Vartanov"
|
||||||
__email__ = "me@enzet.ru"
|
__email__ = "me@enzet.ru"
|
||||||
|
|
||||||
|
DEFAULT_LANE_WIDTH: float = 3.7
|
||||||
USE_BLUR: bool = False
|
USE_BLUR: bool = False
|
||||||
|
|
||||||
|
|
||||||
|
@ -386,7 +387,7 @@ class Road(Tagged):
|
||||||
|
|
||||||
if "lanes" in tags:
|
if "lanes" in tags:
|
||||||
try:
|
try:
|
||||||
self.width = int(tags["lanes"]) * 3.7
|
self.width = int(tags["lanes"]) * DEFAULT_LANE_WIDTH
|
||||||
self.lanes = [Lane()] * int(tags["lanes"])
|
self.lanes = [Lane()] * int(tags["lanes"])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -47,6 +47,7 @@ class Shape:
|
||||||
is_right_directed: Optional[bool] = None
|
is_right_directed: Optional[bool] = None
|
||||||
emojis: set[str] = field(default_factory=set)
|
emojis: set[str] = field(default_factory=set)
|
||||||
is_part: bool = False
|
is_part: bool = False
|
||||||
|
group: str = ""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_structure(
|
def from_structure(
|
||||||
|
@ -81,6 +82,9 @@ class Shape:
|
||||||
if "is_part" in structure:
|
if "is_part" in structure:
|
||||||
shape.is_part = structure["is_part"]
|
shape.is_part = structure["is_part"]
|
||||||
|
|
||||||
|
if "group" in structure:
|
||||||
|
shape.group = structure["group"]
|
||||||
|
|
||||||
return shape
|
return shape
|
||||||
|
|
||||||
def is_default(self) -> bool:
|
def is_default(self) -> bool:
|
||||||
|
@ -117,6 +121,10 @@ class Shape:
|
||||||
d=self.path, transform=" ".join(transformations)
|
d=self.path, transform=" ".join(transformations)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def get_full_id(self) -> str:
|
||||||
|
"""Compute full shape identifier with group for sorting."""
|
||||||
|
return self.group + "_" + self.id_
|
||||||
|
|
||||||
|
|
||||||
def parse_length(text: str) -> float:
|
def parse_length(text: str) -> float:
|
||||||
"""Parse length from SVG attribute."""
|
"""Parse length from SVG attribute."""
|
||||||
|
@ -169,6 +177,41 @@ def verify_sketch_element(element: Element, id_: str) -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def parse_configuration(root: dict, configuration: dict, group: str) -> None:
|
||||||
|
"""
|
||||||
|
Shape description is a probably empty dictionary with optional fields
|
||||||
|
`name`, `emoji`, `is_part`, and `directed`. Shape configuration is a
|
||||||
|
dictionary that contains shape descriptions. Shape descriptions may be
|
||||||
|
grouped and the nesting level may be arbitrary:
|
||||||
|
|
||||||
|
{
|
||||||
|
<shape id>: {<shape description>},
|
||||||
|
<shape id>: {<shape description>},
|
||||||
|
<group>: {
|
||||||
|
<shape id>: {<shape description>},
|
||||||
|
<shape id>: {<shape description>}
|
||||||
|
},
|
||||||
|
<group>: {
|
||||||
|
<subgroup>: {
|
||||||
|
<shape id>: {<shape description>},
|
||||||
|
<shape id>: {<shape description>}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
for key, value in root.items():
|
||||||
|
if (
|
||||||
|
not value
|
||||||
|
or "name" in value
|
||||||
|
or "emoji" in value
|
||||||
|
or "is_part" in value
|
||||||
|
or "directed" in value
|
||||||
|
):
|
||||||
|
configuration[key] = value | {"group": group}
|
||||||
|
else:
|
||||||
|
parse_configuration(value, configuration, f"{group}_{key}")
|
||||||
|
|
||||||
|
|
||||||
class ShapeExtractor:
|
class ShapeExtractor:
|
||||||
"""
|
"""
|
||||||
Extract shapes from SVG file.
|
Extract shapes from SVG file.
|
||||||
|
@ -182,10 +225,16 @@ class ShapeExtractor:
|
||||||
"""
|
"""
|
||||||
:param svg_file_name: input SVG file name with icons. File may contain
|
:param svg_file_name: input SVG file name with icons. File may contain
|
||||||
any other irrelevant graphics.
|
any other irrelevant graphics.
|
||||||
|
:param configuration_file_name: JSON file with grouped shape
|
||||||
|
descriptions
|
||||||
"""
|
"""
|
||||||
self.shapes: dict[str, Shape] = {}
|
self.shapes: dict[str, Shape] = {}
|
||||||
self.configuration: dict[str, Any] = json.load(
|
|
||||||
configuration_file_name.open(encoding="utf-8")
|
self.configuration: dict[str, Any] = {}
|
||||||
|
parse_configuration(
|
||||||
|
json.load(configuration_file_name.open(encoding="utf-8")),
|
||||||
|
self.configuration,
|
||||||
|
"root",
|
||||||
)
|
)
|
||||||
root: Element = ElementTree.parse(svg_file_name).getroot()
|
root: Element = ElementTree.parse(svg_file_name).getroot()
|
||||||
self.parse(root)
|
self.parse(root)
|
||||||
|
@ -439,8 +488,8 @@ class Icon:
|
||||||
|
|
||||||
def __lt__(self, other: "Icon") -> bool:
|
def __lt__(self, other: "Icon") -> bool:
|
||||||
return "".join(
|
return "".join(
|
||||||
[x.shape.id_ for x in self.shape_specifications]
|
[x.shape.get_full_id() for x in self.shape_specifications]
|
||||||
) < "".join([x.shape.id_ for x in other.shape_specifications])
|
) < "".join([x.shape.get_full_id() for x in other.shape_specifications])
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue