diff --git a/README.md b/README.md index 80e425b5..25a39a25 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 | diff --git a/map_machine/__main__.py b/map_machine/__main__.py index 5c53d2e0..143803a6 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() diff --git a/map_machine/constructor.py b/map_machine/constructor.py index c4f51955..3646bcb8 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 @@ -279,7 +282,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 +298,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 +307,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. diff --git a/map_machine/element/element.py b/map_machine/element/element.py index eb0dfbd2..caeaa103 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": diff --git a/map_machine/main.py b/map_machine/main.py index ee7e143c..3da40f06 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 2ead82b4..c88128c6 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") diff --git a/map_machine/osm/osm_util.py b/map_machine/osm/osm_util.py index 8a024150..6d744185 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] diff --git a/map_machine/scheme/carto.yml b/map_machine/scheme/carto.yml index 012fa481..5edaef8b 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 @@ -144,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 93e33134..c1d93364 100644 --- a/map_machine/scheme/default.yml +++ b/map_machine/scheme/default.yml @@ -73,12 +73,15 @@ 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 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" @@ -248,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/nodes.yml b/map_machine/scheme/nodes.yml index a1a9bdfe..87a12858 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] diff --git a/map_machine/scheme/roads.yml b/map_machine/scheme/roads.yml index 6294dc67..2e3b23a8 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 diff --git a/map_machine/scheme/ways.yml b/map_machine/scheme/ways.yml index ecde08f3..f98f9ac0 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} @@ -607,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