From f6f33d7cd70ebc5f8fa5311736e0af550e83f20a Mon Sep 17 00:00:00 2001 From: Sergey Vartanov Date: Wed, 11 Feb 2026 23:30:53 +0400 Subject: [PATCH 01/10] Fix foot colors. --- map_machine/scheme/carto.yml | 1 + map_machine/scheme/default.yml | 3 ++- map_machine/scheme/ways.yml | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/map_machine/scheme/carto.yml b/map_machine/scheme/carto.yml index 012fa48..33ff066 100644 --- a/map_machine/scheme/carto.yml +++ b/map_machine/scheme/carto.yml @@ -73,6 +73,7 @@ variables: # ford_color foot_border_color: white foot_border_width: 3.0 + foot_border_opacity: 0.4 foot_color-noaccess: "#bbbbbb" foot_color: salmon foot_dasharray: 3,3 diff --git a/map_machine/scheme/default.yml b/map_machine/scheme/default.yml index 93e3313..5bc00ed 100644 --- a/map_machine/scheme/default.yml +++ b/map_machine/scheme/default.yml @@ -73,7 +73,8 @@ variables: embankment_color: "#666666" ford_color: "#88BBFF" foot_border_color: "#FFFFFF" - foot_border_width: 3.0 + foot_border_width: 0.0 + foot_border_opacity: 1.0 # foot_color-noaccess foot_color: "#B89A74" foot_dasharray: 7.0,3.0 diff --git a/map_machine/scheme/ways.yml b/map_machine/scheme/ways.yml index ecde08f..c5ea002 100644 --- a/map_machine/scheme/ways.yml +++ b/map_machine/scheme/ways.yml @@ -246,8 +246,9 @@ ways: stroke-linecap: butt - tags: {highway: path} style: - stroke-width: 3.0 + stroke-width: $foot_border_width stroke: $foot_border_color + opacity: $foot_border_opacity priority: $priority_road_3 - tags: {highway: footway} From e04c726b9147f60b0a8346afeee2ac5a1584eb50 Mon Sep 17 00:00:00 2001 From: Sergey Vartanov Date: Wed, 11 Feb 2026 23:32:11 +0400 Subject: [PATCH 02/10] Update readme. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 80e425b..25a39a2 100644 --- a/README.md +++ b/README.md @@ -202,8 +202,6 @@ will download OSM data to `cache/2.284,48.860,2.290,48.865.osm` and render an SV | Option | Description | |---|---| -| `--no-overpass` | do not use Overpass API to download complete data for incomplete relations | -| `--overpass-query` `` | path to a custom Overpass query file; use {{bbox}} as a placeholder for the bounding box | | `-i`, `--input` `` | input XML file name or names (if not specified, files will be downloaded using the OpenStreetMap API) | | `-o`, `--output` `` | output SVG file name, default value: `out/map.svg` | | `-b`, `--bounding-box`, `--boundary-box` `,,,` | geographic bounding box | @@ -211,6 +209,8 @@ will download OSM data to `cache/2.284,48.860,2.290,48.865.osm` and render an SV | `-z`, `--zoom` `` | OSM zoom level, default value: 18.0 | | `-c`, `--coordinates` `,` | coordinates of any location within the tile | | `-s`, `--size` `,` | resulting image size | +| `--no-overpass` | do not use Overpass API to download complete data for incomplete relations | +| `--overpass-query` `` | path to a custom Overpass query file; use {{bbox}} as a placeholder for the bounding box | | `--gpx` `` | path to a GPX file to draw as a track overlay | | `--track-color` `` | track stroke color (default: #FF0000), default value: `#FF0000` | | `--track-width` `` | track stroke width in pixels (default: 3.0), default value: 3.0 | From a0eb4a2608ccd6a24ee3262e513dd03c30fc52d5 Mon Sep 17 00:00:00 2001 From: Sergey Vartanov Date: Wed, 11 Feb 2026 23:40:44 +0400 Subject: [PATCH 03/10] Add courthouse color. --- map_machine/scheme/nodes.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/map_machine/scheme/nodes.yml b/map_machine/scheme/nodes.yml index a1a9bdf..87a1285 100644 --- a/map_machine/scheme/nodes.yml +++ b/map_machine/scheme/nodes.yml @@ -224,7 +224,7 @@ nodes: location_restrictions: {include: [jp]} shapes: [{shape: japan_fire_station, color: $emergency_color}] - tags: {amenity: courthouse} - shapes: [gavel] + shapes: [{shape: gavel, color: $amenity_brown_color}] - tags: {amenity: police} location_restrictions: {include: [jp]} shapes: [japan_police_station] From d53c70e8cd21c01f9021ef864b30f6b694ff9226 Mon Sep 17 00:00:00 2001 From: Sergey Vartanov Date: Wed, 11 Feb 2026 23:52:29 +0400 Subject: [PATCH 04/10] Change way matching. --- map_machine/constructor.py | 49 +++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/map_machine/constructor.py b/map_machine/constructor.py index c4f5195..ef17096 100644 --- a/map_machine/constructor.py +++ b/map_machine/constructor.py @@ -279,7 +279,8 @@ def construct_line( line_styles: list[LineStyle] = self.scheme.get_style(line.tags) - for line_style in line_styles: + if line_styles: + line_style = line_styles[-1] new_line_style: LineStyle = line_style if recolor is not None: new_style: dict[str, float | int | str] = dict(line_style.style) @@ -294,7 +295,7 @@ def construct_line( StyledFigure(line.tags, inners, outers, new_line_style) ) - if not ( + if ( line.get_tag("area") == "yes" or line.get_tag("type") == "multipolygon" or ( @@ -303,30 +304,28 @@ def construct_line( and self.scheme.is_area(line.tags) ) ): - continue - - priority: int - icon_set: IconSet | None - icon_set, priority = self.configuration.get_icon( - line.tags, processed - ) - if icon_set is not None: - labels: list[Label] = self.text_constructor.construct_text( - line.tags, - processed, - self.configuration.label_mode, + priority: int + icon_set: IconSet | None + icon_set, priority = self.configuration.get_icon( + line.tags, processed ) - point: Point = Point( - icon_set, - labels, - line.tags, - processed, - center_point, - is_for_node=False, - priority=priority, - add_tooltips=self.configuration.show_tooltips, - ) - self.points.append(point) + if icon_set is not None: + labels: list[Label] = self.text_constructor.construct_text( + line.tags, + processed, + self.configuration.label_mode, + ) + point: Point = Point( + icon_set, + labels, + line.tags, + processed, + center_point, + is_for_node=False, + priority=priority, + add_tooltips=self.configuration.show_tooltips, + ) + self.points.append(point) # TODO(enzet): probably we may want to skip the next part if # `line_styles` are not empty. From 06fb7bf47857594d413ee1a0bc93ad8dce9096ed Mon Sep 17 00:00:00 2001 From: Sergey Vartanov Date: Sun, 15 Feb 2026 23:36:46 +0400 Subject: [PATCH 05/10] Fix trunk color. --- map_machine/scheme/default.yml | 2 ++ map_machine/scheme/roads.yml | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/map_machine/scheme/default.yml b/map_machine/scheme/default.yml index 5bc00ed..87c7791 100644 --- a/map_machine/scheme/default.yml +++ b/map_machine/scheme/default.yml @@ -80,6 +80,8 @@ variables: foot_dasharray: 7.0,3.0 motorway_border_color: "#CC8800" motorway_color: "#FFAA33" + trunk_border_color: "#CC8800" + trunk_color: "#FFAA33" primary_border_color: "#AA8800" primary_color: "#FFDD66" secondary_border_color: "#BB9911" diff --git a/map_machine/scheme/roads.yml b/map_machine/scheme/roads.yml index 6294dc6..2e3b23a 100644 --- a/map_machine/scheme/roads.yml +++ b/map_machine/scheme/roads.yml @@ -6,13 +6,13 @@ roads: priority: 41.8 - tags: {highway: trunk} default_width: 7.0 - border_color: $motorway_border_color - color: $motorway_color + border_color: $trunk_border_color + color: $trunk_color priority: 41.0 - tags: {highway: trunk_link} default_width: 7.0 - border_color: $motorway_border_color - color: $motorway_color + border_color: $trunk_border_color + color: $trunk_color priority: 41.0 - tags: {highway: primary} default_width: 7.0 From 6579af150f0887da71b60c00ddb59758fa6aa11c Mon Sep 17 00:00:00 2001 From: Sergey Vartanov Date: Sat, 28 Feb 2026 22:12:00 +0400 Subject: [PATCH 06/10] Fix way opacity. --- map_machine/scheme/carto.yml | 1 + map_machine/scheme/default.yml | 1 + map_machine/scheme/ways.yml | 3 +++ 3 files changed, 5 insertions(+) diff --git a/map_machine/scheme/carto.yml b/map_machine/scheme/carto.yml index 33ff066..5edaef8 100644 --- a/map_machine/scheme/carto.yml +++ b/map_machine/scheme/carto.yml @@ -145,6 +145,7 @@ variables: place_of_worship_border_color: {color: "#d0d0d0", darken: 0.3} place_of_worship_border_width: 0.3 power_color: {color: $industrial_color, darken: 0.05} + power_opacity: $industrial_opacity power_border_color: {color: $industrial_border_color, darken: 0.05} societal_amenities_color: "#ffffe5" societal_amenities_border_color: {color: "#ffffe5", darken: 0.35} diff --git a/map_machine/scheme/default.yml b/map_machine/scheme/default.yml index 87c7791..c1d9336 100644 --- a/map_machine/scheme/default.yml +++ b/map_machine/scheme/default.yml @@ -251,6 +251,7 @@ variables: playground_color: "#FFDDCC" power_color: $industrial_color power_border_color: $industrial_border_color + power_opacity: $industrial_opacity prison_color: "#888888" prison_opacity: 0.1 prison_border_color: "#888888" diff --git a/map_machine/scheme/ways.yml b/map_machine/scheme/ways.yml index c5ea002..f98f9ac 100644 --- a/map_machine/scheme/ways.yml +++ b/map_machine/scheme/ways.yml @@ -608,18 +608,21 @@ ways: - tags: {power: substation} style: fill: $power_color + opacity: $power_opacity stroke: $power_border_color stroke-width: 0.5 priority: $priority_landuse_1 - tags: {power: plant} style: fill: $power_color + opacity: $power_opacity stroke: $power_border_color stroke-width: 0.5 priority: $priority_landuse_1 - tags: {power: generator} style: fill: $power_color + opacity: $power_opacity stroke: $power_border_color stroke-width: 0.5 priority: $priority_landuse_1 From b505a9ecf61d0e483bc8d3a2f8c29b5d381e39eb Mon Sep 17 00:00:00 2001 From: Sergey Vartanov Date: Sat, 28 Feb 2026 22:20:16 +0400 Subject: [PATCH 07/10] Fix version comparison. --- map_machine/__main__.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/map_machine/__main__.py b/map_machine/__main__.py index 5c53d2e..143803a 100644 --- a/map_machine/__main__.py +++ b/map_machine/__main__.py @@ -11,10 +11,7 @@ PYTHON_MAJOR_VERSION: int = 3 PYTHON_MINOR_VERSION: int = 9 - if ( - sys.version_info.major < PYTHON_MAJOR_VERSION - or sys.version_info.minor < PYTHON_MINOR_VERSION - ): + if sys.version_info < (PYTHON_MAJOR_VERSION, PYTHON_MINOR_VERSION): sys.exit(1) main() From 75813c8273c1ecc2e5e5b1f8f80f99436817a87b Mon Sep 17 00:00:00 2001 From: Sergey Vartanov Date: Sat, 28 Feb 2026 22:25:11 +0400 Subject: [PATCH 08/10] Fix open modes and exit after fatal. --- map_machine/main.py | 1 + map_machine/osm/osm_getter.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/map_machine/main.py b/map_machine/main.py index ee7e143..3da40f0 100644 --- a/map_machine/main.py +++ b/map_machine/main.py @@ -30,6 +30,7 @@ def main() -> None: if not arguments.command: logging.fatal("No command provided. See --help.") + sys.exit(1) elif arguments.command == "render": from map_machine import mapper # noqa: PLC0415 diff --git a/map_machine/osm/osm_getter.py b/map_machine/osm/osm_getter.py index 2ead82b..c88128c 100644 --- a/map_machine/osm/osm_getter.py +++ b/map_machine/osm/osm_getter.py @@ -85,7 +85,7 @@ def get_osm( message = "Cannot download data." raise NetworkError(message) - with cache_file_path.open("bw+") as output_file: + with cache_file_path.open("wb") as output_file: output_file.write(content) return content.decode("utf-8") @@ -226,7 +226,7 @@ def get_osm_overpass( message = "Unexpected Overpass API response." raise NetworkError(message) - with cache_file_path.open("bw+") as output_file: + with cache_file_path.open("wb") as output_file: output_file.write(content) return content.decode("utf-8") From 0e380a09cb6708efc48a4c8ba79edf8a88fed770 Mon Sep 17 00:00:00 2001 From: Sergey Vartanov Date: Sat, 28 Feb 2026 22:30:06 +0400 Subject: [PATCH 09/10] Handle user input. --- map_machine/element/element.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/map_machine/element/element.py b/map_machine/element/element.py index eb0dfbd..caeaa10 100644 --- a/map_machine/element/element.py +++ b/map_machine/element/element.py @@ -44,9 +44,13 @@ def draw_area(tags: Tags, path: Path) -> None: def draw_element(options: argparse.Namespace) -> None: """Entry point for element drawing.""" - tags_description: Tags = { - x.split("=")[0]: x.split("=")[1] for x in options.tags.split(",") - } + tags_description: Tags = {} + for x in options.tags.split(","): + parts: list[str] = x.split("=", 1) + if len(parts) != 2: + logger.fatal(f"Invalid tag `{x}`, expected `key=value` format.") + sys.exit(1) + tags_description[parts[0]] = parts[1] if options.type == "node": draw_node(tags_description, Path(options.output_file)) elif options.type == "way": From b7eba4422066da9ab2d8f83608628d576a6bef88 Mon Sep 17 00:00:00 2001 From: Sergey Vartanov Date: Tue, 5 May 2026 01:24:22 +0300 Subject: [PATCH 10/10] Issue #208: skip processing of empty ways. We can process OSM files even if some information is missing. --- map_machine/constructor.py | 3 +++ map_machine/osm/osm_util.py | 2 ++ 2 files changed, 5 insertions(+) diff --git a/map_machine/constructor.py b/map_machine/constructor.py index ef17096..3646bcb 100644 --- a/map_machine/constructor.py +++ b/map_machine/constructor.py @@ -185,6 +185,9 @@ def construct_ways(self) -> None: # Coastline is handled by `CoastlineProcessor`. continue + if not way.nodes: + continue + if not self._should_crop() or not self._crop_bounding_box: self.construct_line(way, [], [way.nodes]) continue diff --git a/map_machine/osm/osm_util.py b/map_machine/osm/osm_util.py index 8a02415..6d74418 100644 --- a/map_machine/osm/osm_util.py +++ b/map_machine/osm/osm_util.py @@ -5,6 +5,8 @@ def is_cycle(nodes: list[OSMNode]) -> bool: """Check whether the way is a cycle or an area boundary.""" + if not nodes: + return False return nodes[0] == nodes[-1]