diff --git a/map_machine/constructor.py b/map_machine/constructor.py index 31f6d9a..2f0c212 100644 --- a/map_machine/constructor.py +++ b/map_machine/constructor.py @@ -278,7 +278,7 @@ class Constructor: self.extractor, line.tags, processed, - self.configuration.zoom_level, + self.configuration, ) if icon_set is not None: labels: list[Label] = self.scheme.construct_text( @@ -316,7 +316,7 @@ class Constructor: self.extractor, line.tags, processed, - self.configuration.zoom_level, + self.configuration, ) if icon_set is not None: labels: list[Label] = self.scheme.construct_text( @@ -430,7 +430,7 @@ class Constructor: return icon_set, priority = self.scheme.get_icon( - self.extractor, tags, processed, self.configuration.zoom_level + self.extractor, tags, processed, self.configuration ) if icon_set is None: return diff --git a/map_machine/element.py b/map_machine/element.py index 68726af..d68d944 100644 --- a/map_machine/element.py +++ b/map_machine/element.py @@ -41,7 +41,7 @@ def draw_element(options: argparse.Namespace) -> None: workspace.ICONS_PATH, workspace.ICONS_CONFIG_PATH ) processed: set[str] = set() - icon, priority = scheme.get_icon(extractor, tags, processed, 18) + icon, priority = scheme.get_icon(extractor, tags, processed) is_for_node: bool = target == "node" labels: list[Label] = scheme.construct_text(tags, "all", processed) point: Point = Point( diff --git a/map_machine/icons/icons.svg b/map_machine/icons/icons.svg index f08f06a..c8046e7 100644 --- a/map_machine/icons/icons.svg +++ b/map_machine/icons/icons.svg @@ -148,9 +148,9 @@ showgrid="true" inkscape:document-units="px" inkscape:current-layer="layer1" - inkscape:cy="491.93534" - inkscape:cx="710.8436" - inkscape:zoom="22.627417" + inkscape:cy="421.22467" + inkscape:cx="81.518562" + inkscape:zoom="5.6568542" inkscape:pageshadow="2" inkscape:pageopacity="0.0" borderopacity="1.0" @@ -4441,20 +4441,20 @@ d="m 119,562 c -0.0693,0 -0.12764,0.006 -0.1875,0.0312 C 117.24696,562.13217 116,563.40897 116,565 l -1,7 2,0 0,-7 c 0,-1.10457 0.89543,-2 2,-2 l 1.5,0 c 0.277,0 0.5,-0.223 0.5,-0.5 0,-0.277 -0.223,-0.5 -0.5,-0.5 z m 1,2 c -1.108,0 -2,0.892 -2,2 l 0,0.5 0,1.5 0,5.5 c 0,0.277 0.223,0.5 0.5,0.5 l 3,0 c 0.277,0 0.5,-0.223 0.5,-0.5 l 0,-5.5 0,-1.5 0,-0.5 c 0,-1.108 -0.892,-2 -2,-2 z" style="fill:#000000;fill-opacity:1;stroke:none" /> @@ -5671,12 +5671,12 @@ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate" /> + y="164" /> + d="m 55.5,166.5 -1.5,0 -1,2.5 5,1" + style="opacity:0.2;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + d="m 58,168.5 2,0" + style="opacity:0.2;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" /> + d="m 59,168.5 -2.5,4 -2,-3" + style="opacity:0.2;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + d="m 39.5,166.5 -1.5,0 -1,2.5 5,1" + style="opacity:0.2;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + d="m 42,168.5 2,0" + style="opacity:0.2;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" /> + d="m 43,168.5 -2.5,4 -2,-3" + style="opacity:0.2;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> str: return f'[{key}="{value}"]' +def match_location(restrictions: dict[str, str], country: str) -> bool: + """Check whether country is matched by location restrictions.""" + if "exclude" in restrictions and country in restrictions["exclude"]: + return False + if ( + "include" in restrictions + and restrictions["include"] != "world" + and country != "world" + and country not in restrictions["include"] + ): + return False + return True + + class Matcher: """ Tag matching. @@ -121,14 +136,25 @@ class Matcher: self.start_zoom_level is None or zoom_level >= self.start_zoom_level ) - def is_matched(self, tags: dict[str, str]) -> bool: + def is_matched( + self, + tags: dict[str, str], + configuration: Optional[MapConfiguration] = None, + ) -> bool: """ Check whether element tags matches tag matcher. - :param tags: element tags to match + :param tags: element tags to be matched + :param configuration: current map configuration to be matched """ - if self.location_restrictions: - return False # FIXME: implement + if ( + configuration is not None + and self.location_restrictions + and not match_location( + self.location_restrictions, configuration.country + ) + ): + return False for config_tag_key in self.tags: config_tag_key: str @@ -355,7 +381,7 @@ class Scheme: extractor: ShapeExtractor, tags: dict[str, Any], processed: set[str], - zoom_level: float, + configuration: MapConfiguration = MapConfiguration(), ) -> tuple[Optional[IconSet], int]: """ Construct icon set. @@ -363,7 +389,7 @@ class Scheme: :param extractor: extractor with icon specifications :param tags: OpenStreetMap element tags dictionary :param processed: set of already processed tag keys - :param zoom_level: zoom level in current context + :param configuration: current map configuration to be matched :return (icon set, icon priority) """ tags_hash: str = ( @@ -381,9 +407,9 @@ class Scheme: for matcher in self.node_matchers: if not matcher.replace_shapes and main_icon: continue - if not matcher.is_matched(tags): + if not matcher.is_matched(tags, configuration): continue - if not matcher.check_zoom_level(zoom_level): + if not matcher.check_zoom_level(configuration.zoom_level): return None, 0 matcher_tags: set[str] = set(matcher.tags.keys()) priority = len(self.node_matchers) - index diff --git a/map_machine/scheme/default.yml b/map_machine/scheme/default.yml index a38f5a3..8d5b26f 100644 --- a/map_machine/scheme/default.yml +++ b/map_machine/scheme/default.yml @@ -281,7 +281,7 @@ node_icons: shapes: [volcanic_cone] - tags: {historic: castle} - location_restrictions: {include: jp} + location_restrictions: {include: [jp]} shapes: [japan_castle] - tags: {shop: mall} shapes: [bag] @@ -316,10 +316,10 @@ node_icons: - tags: {amenity: clinic} shapes: [greek_cross] - tags: {amenity: post_office} - location_restrictions: {include: world, exclude: jp} + location_restrictions: {include: world, exclude: [jp]} shapes: [envelope] - tags: {amenity: post_office} - location_restrictions: {include: jp} + location_restrictions: {include: [jp]} shapes: [japan_post] - tags: {shop: car_repair} shapes: [car_repair] @@ -363,7 +363,7 @@ node_icons: - tags: {historic: "*"} shapes: [japan_historic] replace_shapes: no - location_restrictions: {include: jp} + location_restrictions: {include: [jp]} - group: "Normal big objects" start_zoom_level: 15 @@ -562,7 +562,7 @@ node_icons: - tags: {building: office} shapes: [briefcase] - tags: {amenity: school} - location_restrictions: {include: jp} + location_restrictions: {include: [jp]} shapes: [japan_elementary_school] - tags: {office: company} shapes: [briefcase] @@ -577,7 +577,7 @@ node_icons: start_zoom_level: 15 tags: - tags: {man_made: communications_tower} - location_restrictions: {include: jp} + location_restrictions: {include: [jp]} shapes: [japan_tv_tower] - tags: {man_made: tower} shapes: [tower] diff --git a/tests/test_icons.py b/tests/test_icons.py index 484747c..49d719d 100644 --- a/tests/test_icons.py +++ b/tests/test_icons.py @@ -35,7 +35,7 @@ def test_icons_by_name(init_collection: IconCollection) -> None: def get_icon(tags: dict[str, str]) -> IconSet: """Construct icon from tags.""" processed: set[str] = set() - icon, _ = SCHEME.get_icon(SHAPE_EXTRACTOR, tags, processed, 18) + icon, _ = SCHEME.get_icon(SHAPE_EXTRACTOR, tags, processed) return icon