From 494beaaeeffd7f6f99c805112c2a48a1df976520 Mon Sep 17 00:00:00 2001 From: Sergei Dutenhefner <74149595+sergej-singer@users.noreply.github.com> Date: Thu, 18 Jul 2024 00:21:07 +0200 Subject: [PATCH 1/6] MultiGeometry Support --- .gitignore | 5 +++ mapbuilder/data/kml.py | 27 +++++++++++++++ mapbuilder/handlers/jinja.py | 66 ++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) diff --git a/.gitignore b/.gitignore index 5654e6a..924f704 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,8 @@ __pycache__/ /.direnv /.ruff_cache /result* +/aixm +/kml +/maps +mapbuilder.toml +/grp diff --git a/mapbuilder/data/kml.py b/mapbuilder/data/kml.py index f65309e..4b4e2fb 100644 --- a/mapbuilder/data/kml.py +++ b/mapbuilder/data/kml.py @@ -55,6 +55,11 @@ def parse_recursively(self, root, result): ) elif "Point" in placemark: geom = Point(self.parse_pos_list(placemark["Point"]["coordinates"])) + elif "MultiGeometry" in placemark: + if len(placemark["MultiGeometry"]) != 1: + raise ValueError(f"Placemark '{placemark["name"]}': in MultiGeometry only one type of Geometry is allowed") + + geom = self.parse_multigeometry(placemark["MultiGeometry"]) else: msg = f"Placemark {placemark} unknown" raise ValueError(msg) @@ -64,6 +69,28 @@ def parse_recursively(self, root, result): result[name] = [geom] else: result[name].append(geom) + + def parse_multigeometry(self, root) -> list: + geom = [] + + if "LineString" in root: + for linestring in ensure_list(root["LineString"]): + geom.append(LineString(KMLParser.parse_pos_list(linestring["coordinates"]))) + elif "Polygon" in root: + for polygon in ensure_list(root["Polygon"]): + geom.append(LinearRing( + KMLParser.parse_pos_list( + polygon["outerBoundaryIs"]["LinearRing"]["coordinates"], + ) + )) + elif "Point" in root: + for point in ensure_list(root["Point"]): + geom.append(Point(KMLParser.parse_pos_list(point["coordinates"]))) + else: + msg = f"Geometry {root} unknown" + raise ValueError(msg) + + return geom def ensure_list(thing): diff --git a/mapbuilder/handlers/jinja.py b/mapbuilder/handlers/jinja.py index 5a67b90..bc5ec51 100644 --- a/mapbuilder/handlers/jinja.py +++ b/mapbuilder/handlers/jinja.py @@ -51,6 +51,11 @@ def handle(self, item: Path) -> str: to_text=to_text, to_text_buffer=to_text_buffer, to_symbol=to_symbol, + to_multipoly=to_multipoly, + to_multiline=to_multiline, + to_multicoordline=to_multicoordline, + to_multisymbol=to_multisymbol, + to_multitext=to_multitext, ) return jinja_env.get_template(item.name).render() @@ -115,6 +120,20 @@ def to_text(geometry, label: str): labeltext, _, _ = label.partition("#") return f"TEXT:{coord2es(point.coords[0])}:{labeltext}" +def to_multitext(geometries, label: str): + lines = [] + labeltext, _, _ = label.partition("#") + + for geometry in geometries: + for point in geometry: + if point is None: + lines.append("") + continue + + lines.append(f"TEXT:{coord2es(point.coords[0])}:{labeltext}") + + return "\n".join(lines) + def to_symbol(geometry, symbol): point = geometry[0] if isinstance(geometry, list) else geometry @@ -124,6 +143,19 @@ def to_symbol(geometry, symbol): return f"SYMBOL:{symbol}:{coord2es(point.coords[0])}" +def to_multisymbol(geometries, symbol): + lines = [] + + for geometry in geometries: + for point in geometry: + if point is None: + lines.append("") + continue + + lines.append(f"SYMBOL:{symbol}:{coord2es(point.coords[0])}") + + return "\n".join(lines) + def _get_geoms(thing): """Extracts the geometries from either an AIXMFeature or geometry object""" @@ -157,6 +189,16 @@ def to_line(geometries, designator: str): return "\n".join(lines) +def to_multiline(geometries, designator: str): + lines = [f"// {designator}"] if designator else [] + + for geometry in geometries: + for linestring in geometry: + _render_linestring(lines, _get_geoms(linestring)) + + return "\n".join(lines) + + def to_coordline(geometries, designator: str): lines = [f"// {designator}"] if designator else [] @@ -166,6 +208,18 @@ def to_coordline(geometries, designator: str): return "\n".join(lines) +def to_multicoordline(geometries, designator: str): + lines = [f"// {designator}"] if designator else [] + + for geometry in geometries: + for linestring in geometry: + _render_coords(lines, _get_geoms(linestring)) + + lines.extend(("COORDLINE", "")) + + return "\n".join(lines) + + def filter_smaller_than(geometries, threshold): geo = _get_geoms(geometries) if isinstance(geo, list): @@ -186,6 +240,18 @@ def to_poly(geometries, designator: str, color: str | None = None, coordpoly=Fal return "\n".join(lines) +def to_multipoly(geometries, designator: str, color: str | None = None, coordpoly=False): + lines = [f"// {designator}"] if designator else [] + + for geometry in geometries: + for polygon in geometry: + _render_polygon(lines, _get_geoms(polygon), color) + + if coordpoly: + lines.append(f"COORDPOLY:{coordpoly}") + + return "\n".join(lines) + def _render_polygon(lines, polygons, color=None): for polygon in polygons: From 5a37d67d7c16005ecdc1aa6ebf48ab3e9859dc98 Mon Sep 17 00:00:00 2001 From: Sergei Dutenhefner <74149595+sergej-singer@users.noreply.github.com> Date: Thu, 18 Jul 2024 00:33:39 +0200 Subject: [PATCH 2/6] Update .gitignore --- .gitignore | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.gitignore b/.gitignore index 924f704..5654e6a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,3 @@ __pycache__/ /.direnv /.ruff_cache /result* -/aixm -/kml -/maps -mapbuilder.toml -/grp From 376529cab4b078e1355b1381db4f16bf853faae6 Mon Sep 17 00:00:00 2001 From: Sergei Dutenhefner <74149595+sergej-singer@users.noreply.github.com> Date: Thu, 18 Jul 2024 23:38:50 +0200 Subject: [PATCH 3/6] Update jinja.py --- mapbuilder/handlers/jinja.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/mapbuilder/handlers/jinja.py b/mapbuilder/handlers/jinja.py index bc5ec51..4cb0a5c 100644 --- a/mapbuilder/handlers/jinja.py +++ b/mapbuilder/handlers/jinja.py @@ -6,7 +6,7 @@ import shapely.ops from jinja2 import Environment, FileSystemLoader from more_itertools import unique_everseen -from shapely import Geometry, Polygon +from shapely import MultiLineString, Geometry, Polygon from mapbuilder.data.aixm2 import AIXMFeature from mapbuilder.utils.ad import render_cl, render_runways @@ -193,6 +193,10 @@ def to_multiline(geometries, designator: str): lines = [f"// {designator}"] if designator else [] for geometry in geometries: + if isinstance(geometry, MultiLineString): + _render_linestring(lines, _get_geoms(geometry)) + continue + for linestring in geometry: _render_linestring(lines, _get_geoms(linestring)) @@ -212,6 +216,11 @@ def to_multicoordline(geometries, designator: str): lines = [f"// {designator}"] if designator else [] for geometry in geometries: + if isinstance(geometry, MultiLineString): + _render_linestring(lines, _get_geoms(geometry)) + lines.extend(("COORDLINE", "")) + continue + for linestring in geometry: _render_coords(lines, _get_geoms(linestring)) @@ -295,8 +304,12 @@ def simplify(geometries, tolerance): return shapely.simplify(geo, tolerance) -def join_segments(lines): - return shapely.ops.linemerge(_get_geoms(lines)) +def join_segments(geometries): + geo = _get_geoms(geometries) + if isinstance(geo, list): + return [shapely.ops.linemerge(_get_geoms(geometry)) for geometry in geo] + else: + return shapely.ops.linemerge(_get_geoms(geo)) def coord2es(coord): From 9fa343200685963116ffb2fa3f689edd9dfdcfe6 Mon Sep 17 00:00:00 2001 From: Sergei Dutenhefner <74149595+sergej-singer@users.noreply.github.com> Date: Thu, 18 Jul 2024 23:54:17 +0200 Subject: [PATCH 4/6] Update jinja.py --- mapbuilder/handlers/jinja.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mapbuilder/handlers/jinja.py b/mapbuilder/handlers/jinja.py index 4cb0a5c..d5513e7 100644 --- a/mapbuilder/handlers/jinja.py +++ b/mapbuilder/handlers/jinja.py @@ -305,11 +305,10 @@ def simplify(geometries, tolerance): def join_segments(geometries): - geo = _get_geoms(geometries) - if isinstance(geo, list): - return [shapely.ops.linemerge(_get_geoms(geometry)) for geometry in geo] + if isinstance(geometries, list): + return [shapely.ops.linemerge(_get_geoms(geometry)) for geometry in geometries] else: - return shapely.ops.linemerge(_get_geoms(geo)) + return shapely.ops.linemerge(_get_geoms(geometries)) def coord2es(coord): From 8994ebe2b5dff10b371af2c0cf0a978fd86388e3 Mon Sep 17 00:00:00 2001 From: Sergei Dutenhefner <74149595+sergej-singer@users.noreply.github.com> Date: Fri, 13 Dec 2024 23:04:02 +0100 Subject: [PATCH 5/6] Update action.yml --- .github/workflows/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index a5d7132..23325bd 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -7,7 +7,7 @@ on: - main env: - CI_PROJECT_PATH: vatger-nav/mapbuilder + CI_PROJECT_PATH: sergej-singer/mapbuilder jobs: image: From 8b4ff6a5f57aa93f9634367c5e7346855fade565 Mon Sep 17 00:00:00 2001 From: Sergei Dutenhefner <74149595+sergej-singer@users.noreply.github.com> Date: Fri, 13 Dec 2024 23:07:36 +0100 Subject: [PATCH 6/6] Revert "Update action.yml" This reverts commit 8994ebe2b5dff10b371af2c0cf0a978fd86388e3. --- .github/workflows/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index 23325bd..a5d7132 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -7,7 +7,7 @@ on: - main env: - CI_PROJECT_PATH: sergej-singer/mapbuilder + CI_PROJECT_PATH: vatger-nav/mapbuilder jobs: image: