Source code for kmlorm.models.multigeometry

"""
MultiGeometry model for KML multi-geometry collections.

This module defines the MultiGeometry class for handling KML elements
that contain multiple geometry types within a single container.
"""

from typing import Any, Dict, Iterator, List, Optional

from .base import KMLElement


[docs] class MultiGeometry(KMLElement): """ Represents a KML MultiGeometry element. MultiGeometry elements can contain multiple geometry objects including Points, LineStrings, Polygons, and even nested MultiGeometries. This allows for complex geometric collections within a single KML feature. Attributes: geometries: List of geometry objects (Point, Path, Polygon, MultiGeometry) """
[docs] def __init__(self, geometries: Optional[List[Any]] = None, **kwargs: Any) -> None: """ Initialize a MultiGeometry with contained geometries. Args: geometries: List of geometry objects **kwargs: Additional base element attributes (id, name, etc.) """ super().__init__(**kwargs) self.geometries: List[Any] = geometries or []
[docs] def add_geometry(self, geometry: Any) -> None: """ Add a geometry object to this MultiGeometry. Args: geometry: A Point, Path, Polygon, or MultiGeometry object """ if geometry is not None: self.geometries.append(geometry)
[docs] def get_points(self) -> List[Any]: """ Get all Point objects from this MultiGeometry. Returns: List of Point objects, including nested ones """ from .point import Point # pylint: disable=import-outside-toplevel points = [] for geom in self.geometries: if isinstance(geom, Point): points.append(geom) elif hasattr(geom, "get_points"): # Nested MultiGeometry points.extend(geom.get_points()) return points
[docs] def get_paths(self) -> List[Any]: """ Get all Path objects from this MultiGeometry. Returns: List of Path objects, including nested ones """ from .path import Path # pylint: disable=import-outside-toplevel paths = [] for geom in self.geometries: if isinstance(geom, Path): paths.append(geom) elif hasattr(geom, "get_paths"): # Nested MultiGeometry paths.extend(geom.get_paths()) return paths
[docs] def get_polygons(self) -> List[Any]: """ Get all Polygon objects from this MultiGeometry. Returns: List of Polygon objects, including nested ones """ from .polygon import Polygon # pylint: disable=import-outside-toplevel polygons = [] for geom in self.geometries: if isinstance(geom, Polygon): polygons.append(geom) elif hasattr(geom, "get_polygons"): # Nested MultiGeometry polygons.extend(geom.get_polygons()) return polygons
[docs] def get_multigeometries(self) -> List["MultiGeometry"]: """ Get all nested MultiGeometry objects. Returns: List of nested MultiGeometry objects """ multigeoms = [] for geom in self.geometries: if isinstance(geom, MultiGeometry): multigeoms.append(geom) # Recursively get nested MultiGeometries multigeoms.extend(geom.get_multigeometries()) return multigeoms
[docs] def geometry_counts(self) -> Dict[str, int]: """ Get counts of each geometry type in this MultiGeometry. Returns: Dictionary with geometry type counts """ return { "points": len(self.get_points()), "paths": len(self.get_paths()), "polygons": len(self.get_polygons()), "multigeometries": len(self.get_multigeometries()), "total": len(self.geometries), }
[docs] def has_coordinates(self) -> bool: """ Check if any contained geometry has coordinates. Returns: True if any geometry has coordinates """ for geom in self.geometries: if hasattr(geom, "has_coordinates") and geom.has_coordinates(): return True return False
[docs] def to_dict(self) -> Dict[str, Any]: """ Convert MultiGeometry to dictionary representation. Returns: Dictionary with all MultiGeometry attributes """ base_dict = super().to_dict() base_dict.update( { "geometries": [ geom.to_dict() if hasattr(geom, "to_dict") else str(geom) for geom in self.geometries ], "geometry_counts": self.geometry_counts(), } ) return base_dict
[docs] def __str__(self) -> str: """String representation of the MultiGeometry.""" if self.name: return f"MultiGeometry: {self.name} ({len(self.geometries)} geometries)" return f"MultiGeometry ({len(self.geometries)} geometries)"
[docs] def __repr__(self) -> str: """Detailed representation of the MultiGeometry.""" return ( f"MultiGeometry(id='{self.id}', name='{self.name}', " f"geometries={len(self.geometries)})" )
[docs] def __len__(self) -> int: """Return the number of contained geometries.""" return len(self.geometries)
[docs] def __iter__(self) -> Iterator[Any]: """Iterate over contained geometries.""" return iter(self.geometries)
[docs] def __getitem__(self, index: int) -> Any: """Get geometry by index.""" return self.geometries[index]