Skip to content

Commit

Permalink
#133 type annotate geometries
Browse files Browse the repository at this point in the history
  • Loading branch information
cleder committed Oct 8, 2022
1 parent 53c27ec commit 57f957c
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 35 deletions.
110 changes: 76 additions & 34 deletions fastkml/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ def _set_altitude_mode(self, element: Element) -> None:
"absolute",
]
if self.altitude_mode != "clampToGround":
am_element = config.etree.SubElement(
element, f"{self.ns}altitudeMode" # type: ignore[arg-type]
am_element = config.etree.SubElement( # type: ignore[attr-defined]
element, f"{self.ns}altitudeMode"
)
am_element.text = self.altitude_mode

Expand All @@ -152,8 +152,8 @@ def _set_extrude(self, element: Element) -> None:
]:
et_element = cast(
Element,
config.etree.SubElement(
element, f"{self.ns}extrude" # type: ignore[arg-type]
config.etree.SubElement( # type: ignore[attr-defined]
element, f"{self.ns}extrude"
),
)
et_element.text = "1"
Expand All @@ -162,7 +162,10 @@ def _etree_coordinates(
self,
coordinates: Sequence[PointType],
) -> Element:
element = cast(Element, config.etree.Element(f"{self.ns}coordinates"))
element = cast(
Element,
config.etree.Element(f"{self.ns}coordinates"), # type: ignore[attr-defined]
)
if len(coordinates[0]) == 2:
if config.FORCE3D: # and not clampToGround:
tuples = (f"{c[0]:f},{c[1]:f},0.000000" for c in coordinates)
Expand All @@ -187,8 +190,8 @@ def _etree_linestring(self, linestring: LineString) -> Element:
"clampToGround",
"clampToSeaFloor",
]:
ts_element = config.etree.SubElement(
element, f"{self.ns}tessellate" # type: ignore[arg-type]
ts_element = config.etree.SubElement( # type: ignore[attr-defined]
element, f"{self.ns}tessellate"
)
ts_element.text = "1"
return self._extracted_from__etree_linearring_5(linestring, element)
Expand All @@ -208,58 +211,83 @@ def _etree_polygon(self, polygon: Polygon) -> Element:
element = self._extrude_and_altitude_mode("Polygon")
outer_boundary = cast(
Element,
config.etree.SubElement(
element, # type: ignore[arg-type]
config.etree.SubElement( # type: ignore[attr-defined]
element,
f"{self.ns}outerBoundaryIs",
),
)
outer_boundary.append(self._etree_linearring(polygon.exterior))
for ib in polygon.interiors:
inner_boundary = cast(
Element,
config.etree.SubElement(
element, # type: ignore[arg-type]
config.etree.SubElement( # type: ignore[attr-defined]
element,
f"{self.ns}innerBoundaryIs",
),
)
inner_boundary.append(self._etree_linearring(ib))
return element

def _extrude_and_altitude_mode(self, kml_geometry: str) -> Element:
result = cast(Element, config.etree.Element(f"{self.ns}{kml_geometry}"))
result = cast(
Element,
config.etree.Element( # type: ignore[attr-defined]
f"{self.ns}{kml_geometry}"
),
)
self._set_extrude(result)
self._set_altitude_mode(result)
return result

def _etree_multipoint(self, points: MultiPoint) -> Element:
element = cast(Element, config.etree.Element(f"{self.ns}MultiGeometry"))
element = cast(
Element,
config.etree.Element( # type: ignore[attr-defined]
f"{self.ns}MultiGeometry"
),
)
for point in points.geoms:
element.append(self._etree_point(point))
return element

def _etree_multilinestring(self, linestrings: MultiLineString) -> Element:
element = cast(Element, config.etree.Element(f"{self.ns}MultiGeometry"))
element = cast(
Element,
config.etree.Element( # type: ignore[attr-defined]
f"{self.ns}MultiGeometry"
),
)
for linestring in linestrings.geoms:
element.append(self._etree_linestring(linestring))
return element

def _etree_multipolygon(self, polygons: MultiPolygon) -> Element:
element = cast(Element, config.etree.Element(f"{self.ns}MultiGeometry"))
element = cast(
Element,
config.etree.Element( # type: ignore[attr-defined]
f"{self.ns}MultiGeometry"
),
)
for polygon in polygons.geoms:
element.append(self._etree_polygon(polygon))
return element

def _etree_collection(self, features: GeometryCollection) -> Element:
element = cast(Element, config.etree.Element(f"{self.ns}MultiGeometry"))
element = cast(
Element,
config.etree.Element( # type: ignore[attr-defined]
f"{self.ns}MultiGeometry"
),
)
for feature in features.geoms:
if feature.geom_type == "Point":
element.append(self._etree_point(feature))
element.append(self._etree_point(cast(Point, feature)))
elif feature.geom_type == "LinearRing":
element.append(self._etree_linearring(feature))
element.append(self._etree_linearring(cast(LinearRing, feature)))
elif feature.geom_type == "LineString":
element.append(self._etree_linestring(feature))
element.append(self._etree_linestring(cast(LineString, feature)))
elif feature.geom_type == "Polygon":
element.append(self._etree_polygon(feature))
element.append(self._etree_polygon(cast(Polygon, feature)))
else:
raise ValueError("Illegal geometry type.")
return element
Expand Down Expand Up @@ -295,7 +323,7 @@ def _get_geometry_spec(self, element: Element) -> None:
et = False
self.extrude = et
else:
self.extrude = False
self.extrude = False # type: ignore[unreachable]
tessellate = element.find(f"{self.ns}tessellate")
if tessellate is not None:
try:
Expand All @@ -304,7 +332,7 @@ def _get_geometry_spec(self, element: Element) -> None:
te = False
self.tessellate = te
else:
self.tessellate = False
self.tessellate = False # type: ignore[unreachable]
altitude_mode = element.find(f"{self.ns}altitudeMode")
if altitude_mode is not None:
am = altitude_mode.text.strip()
Expand All @@ -318,7 +346,7 @@ def _get_geometry_spec(self, element: Element) -> None:
else:
self.altitude_mode = None
else:
self.altitude_mode = None
self.altitude_mode = None # type: ignore[unreachable]

def _get_coordinates(self, element: Element) -> List[PointType]:
coordinates = element.find(f"{self.ns}coordinates")
Expand All @@ -341,7 +369,7 @@ def _get_linear_ring(self, element: Element) -> Optional[LinearRing]:
if lr is not None:
coords = self._get_coordinates(lr)
return LinearRing(coords)
return None
return None # type: ignore[unreachable]

def _get_geometry(self, element: Element) -> Optional[GeometryType]:
# Point, LineString,
Expand Down Expand Up @@ -372,9 +400,9 @@ def _get_geometry(self, element: Element) -> Optional[GeometryType]:
return LinearRing(coords)
return None

def _get_multigeometry(self, element: Element) -> Optional[GeometryType]:
def _get_multigeometry(self, element: Element) -> Optional[MultiGeometryType]:
# MultiGeometry
geoms: List[AnyGeometryType] = []
geoms: List[Union[AnyGeometryType, None]] = []
if element.tag == f"{self.ns}MultiGeometry":
points = element.findall(f"{self.ns}Point")
for point in points:
Expand All @@ -389,29 +417,43 @@ def _get_multigeometry(self, element: Element) -> Optional[GeometryType]:
self._get_geometry_spec(polygon)
outer_boundary = polygon.find(f"{self.ns}outerBoundaryIs")
ob = self._get_linear_ring(outer_boundary)
if not ob:
continue
inner_boundaries = polygon.findall(f"{self.ns}innerBoundaryIs")
ibs = [
inner_bs = [
self._get_linear_ring(inner_boundary)
for inner_boundary in inner_boundaries
]
ibs: List[LinearRing] = [ib for ib in inner_bs if ib]
geoms.append(Polygon.from_linear_rings(ob, *ibs))
linearings = element.findall(f"{self.ns}LinearRing")
if linearings:
for lr in linearings:
self._get_geometry_spec(lr)
geoms.append(LinearRing(self._get_coordinates(lr)))
if geoms:
geom_types = {geom.geom_type for geom in geoms}
clean_geoms: List[AnyGeometryType] = [g for g in geoms if g]
if clean_geoms:
geom_types = {geom.geom_type for geom in clean_geoms}
if len(geom_types) > 1:
return GeometryCollection(geoms)
return GeometryCollection(
clean_geoms, # type: ignore[arg-type]
)
if "Point" in geom_types:
return MultiPoint.from_points(*geoms)
return MultiPoint.from_points(
*clean_geoms, # type: ignore[arg-type]
)
elif "LineString" in geom_types:
return MultiLineString.from_linestrings(*geoms)
return MultiLineString.from_linestrings(
*clean_geoms, # type: ignore[arg-type]
)
elif "Polygon" in geom_types:
return MultiPolygon.from_polygons(*geoms)
return MultiPolygon.from_polygons(
*clean_geoms, # type: ignore[arg-type]
)
elif "LinearRing" in geom_types:
return GeometryCollection(geoms)
return GeometryCollection(
clean_geoms, # type: ignore[arg-type]
)
return None

def from_element(self, element: Element) -> None:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ show_error_codes = true
[[tool.mypy.overrides]]
module = [
"fastkml.kml", "fastkml.gx",
"fastkml.geometry", "fastkml.styles",
"fastkml.styles",
"fastkml.tests.oldunit_test", "fastkml.tests.config_test"]
ignore_errors = true

0 comments on commit 57f957c

Please sign in to comment.