Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MultiGeometry Support #9

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions mapbuilder/data/kml.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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):
Expand Down
84 changes: 81 additions & 3 deletions mapbuilder/handlers/jinja.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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
Expand All @@ -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"""
Expand Down Expand Up @@ -157,6 +189,20 @@ 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:
if isinstance(geometry, MultiLineString):
_render_linestring(lines, _get_geoms(geometry))
continue

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 []

Expand All @@ -166,6 +212,23 @@ 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:
if isinstance(geometry, MultiLineString):
_render_linestring(lines, _get_geoms(geometry))
lines.extend(("COORDLINE", ""))
continue

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):
Expand All @@ -186,6 +249,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:
Expand Down Expand Up @@ -229,8 +304,11 @@ def simplify(geometries, tolerance):
return shapely.simplify(geo, tolerance)


def join_segments(lines):
return shapely.ops.linemerge(_get_geoms(lines))
def join_segments(geometries):
if isinstance(geometries, list):
return [shapely.ops.linemerge(_get_geoms(geometry)) for geometry in geometries]
else:
return shapely.ops.linemerge(_get_geoms(geometries))


def coord2es(coord):
Expand Down
Loading