Source code for monkey_wrench.geometry._models

from pathlib import Path
from typing import Any

from pydantic import BaseModel, FilePath, field_validator, validate_call
from pyresample import AreaDefinition, area_config, load_area

from monkey_wrench.generic import Model
from monkey_wrench.input_output._types import AbsolutePath


[docs] class Area(Model): area: AbsolutePath[FilePath] | dict[str, Any] | AreaDefinition """A filepath, a dictionary, or an object of type AreaDefinition which holds the area information for resampling."""
[docs] @field_validator("area", mode="after") def validate_and_load_area( cls, area: AbsolutePath[FilePath] | dict[str, Any] | AreaDefinition ) -> AreaDefinition | None: match area: case AreaDefinition(): return area case dict(): if len(area) != 1: raise ValueError("Area must have exactly one item.") k = [k for k in area.keys()][0] v = area[k] return area_config._create_area_def_from_dict(k, v) case Path(): return load_area(area)
[docs] class BoundingBox(BaseModel): """Pydantic model for a bounding box. Example: >>> BoundingBox(north=10, south=20, west=30, east=40) BoundingBox(north=10.0, south=20.0, west=30.0, east=40.0) >>> BoundingBox(10, 20, 30, 40) BoundingBox(north=10.0, south=20.0, west=30.0, east=40.0) """ north: float south: float west: float east: float @validate_call def __init__(self, north: float = None, south: float = None, west: float = None, east: float = None): kwargs = dict(north=north, south=south, west=west, east=east) kwargs = {k: v for k, v in kwargs.items() if v is not None} super().__init__(**kwargs)
[docs] def serialize(self, as_string: bool = False, delimiter: str = " ") -> list[float] | str: """Get the serialized version of the bounding box. Args: as_string: If ``True``, return a string representation of the bounding box. delimiter: The delimiter to use in the serialized version of the bounding box, if ``as_string`` is ``True``. Defaults to a blank space. Returns: Either a string, or a list of floats as ``[<North>, <South>, <West>, <East>]``. """ lst = [self.north, self.south, self.west, self.east] if as_string: return delimiter.join([str(i) for i in lst]) return lst
[docs] class Vertex(BaseModel): """Pydantic model for a vertex. Example: >>> Vertex(longitude=10, latitude=20) Vertex(longitude=10.0, latitude=20.0) >>> Vertex(10, 20) Vertex(longitude=10.0, latitude=20.0) """ longitude: float latitude: float @validate_call def __init__(self, longitude: float = None, latitude: float = None): kwargs = dict(longitude=longitude, latitude=latitude) kwargs = {k: v for k, v in kwargs.items() if v is not None} super().__init__(**kwargs)
[docs] def serialize(self, as_string: bool = False, delimiter: str = " ") -> list[float] | str: """Get the serialized version of the vertex. Args: as_string: If ``True``, return a string representation of the vertex. delimiter: The delimiter to use in the serialized version of the vertex, if ``as_string`` is ``True``. Defaults to a blank space. Returns: Either a string, or a list of floats as ``[<longitude>, <latitude>]``. """ lst = [self.longitude, self.latitude] if as_string: return delimiter.join([str(i) for i in lst]) return lst
[docs] class Polygon(BaseModel): """The Pydantic model for a polygon. Example: >>> polygon: Polygon = Polygon(vertices=[ ... Vertex(14.0, 64.0), ... Vertex(16.0, 64.0), ... Vertex(16.0, 62.0), ... Vertex(14.0, 62.0), ... Vertex(14.0, 64.0), ... ]) """ vertices: list[Vertex] @validate_call def __init__(self, vertices: list[Vertex] = None): kwargs = dict(vertices=vertices) if vertices else {} super().__init__(**kwargs)
[docs] def serialize(self, as_string: bool = False) -> list[list[float]] | str: """Get the serialized version of the polygon. Args: as_string: If ``True``, return a string representation of the polygon. Returns: Either a string, or a list of vertices, where each vertex is itself a list of floats. """ lst = [v.serialize(as_string=as_string) for v in self.vertices] if as_string: return f"POLYGON(({','.join(lst)}))" return lst