Skip to content

Polygon

Bases: Spatial

Represents a polygon with a boundary and optional holes.

Follows the GeoJSON specification (RFC 7946).

Parameters:

Name Type Description Default
value List[List[Tuple[float, float]]]

A polygon.

required

Attributes:

Name Type Description
area Float
boundary List[Tuple[float, float]]
holes List[List[Tuple[float, float]]]
xmin float
xmax float
ymin float
ymax float

Examples:

Create a polygon without any holes.

>>> Polygon([[(0,0), (0,1), (1,1), (0,0)]])

Create a polygon with 2 holes.

>>> Polygon(
...     [
...         [(0,0), (0,1), (1,1), (0,0)],
...         [(0.1, 0.1), (0.1, 0.2), (0.2, 0.2), (0.1, 0.1)],
...         [(0.6, 0.6), (0.6, 0.7), (0.7, 0.7), (0.6, 0.6)],
...     ]
... )
Source code in valor/schemas/symbolic/types.py
class Polygon(Spatial):
    """
    Represents a polygon with a boundary and optional holes.

    Follows the GeoJSON specification (RFC 7946).

    Parameters
    ----------
    value : List[List[Tuple[float, float]]], optional
        A polygon.

    Attributes
    ----------
    area
    boundary
    holes
    xmin
    xmax
    ymin
    ymax

    Examples
    --------
    Create a polygon without any holes.
    >>> Polygon([[(0,0), (0,1), (1,1), (0,0)]])

    Create a polygon with 2 holes.
    >>> Polygon(
    ...     [
    ...         [(0,0), (0,1), (1,1), (0,0)],
    ...         [(0.1, 0.1), (0.1, 0.2), (0.2, 0.2), (0.1, 0.1)],
    ...         [(0.6, 0.6), (0.6, 0.7), (0.7, 0.7), (0.6, 0.6)],
    ...     ]
    ... )
    """

    def __init__(
        self, value: typing.List[typing.List[typing.Tuple[float, float]]]
    ):
        super().__init__(value=value)

    @classmethod
    def __validate__(cls, value: typing.Any):
        MultiLineString.__validate__(value)
        for line in value:
            if not (len(line) >= 4 and line[0] == line[-1]):
                raise ValueError(
                    "Polygons are defined by at least 4 points with the first point being repeated at the end."
                )

    @classmethod
    def decode_value(
        cls,
        value: typing.Optional[typing.List[typing.List[typing.List[float]]]],
    ):
        """Decode object from JSON compatible dictionary."""
        if value is None:
            return None
        return cls(
            [
                [(point[0], point[1]) for point in subpolygon]
                for subpolygon in value
            ]
        )

    @property
    def area(self) -> Float:
        """
        Symbolic representation of area.
        """
        if not isinstance(self._value, Symbol):
            raise ValueError
        return Float.symbolic(
            name=self._value._name,
            key=self._value._key,
            attribute="area",
        )

    @property
    def boundary(self) -> typing.List[typing.Tuple[float, float]]:
        """
        The boundary of the polygon.

        Returns
        -------
        List[Tuple(float, float)]
            A list of points.
        """
        value = self.get_value()
        if value is None:
            raise ValueError("Polygon is 'None'")
        return value[0]

    @property
    def holes(self) -> typing.List[typing.List[typing.Tuple[float, float]]]:
        """
        typing.Any holes in the polygon.

        Returns
        -------
        List[List[Tuple(float, float)]]
            A list of holes.
        """
        value = self.get_value()
        if value is None:
            raise ValueError("Polygon is 'None'")
        return value[1:]

    @property
    def xmin(self) -> float:
        """
        Minimum x-value.

        Returns
        -------
        float
        """
        return min([p[0] for p in self.boundary])

    @property
    def xmax(self) -> float:
        """
        Maximum x-value.

        Returns
        -------
        float
        """
        return max([p[0] for p in self.boundary])

    @property
    def ymin(self) -> float:
        """
        Minimum y-value.

        Returns
        -------
        float
        """
        return min([p[1] for p in self.boundary])

    @property
    def ymax(self) -> float:
        """
        Maximum y-value.

        Returns
        -------
        float
        """
        return max([p[1] for p in self.boundary])

Attributes

valor.schemas.Polygon.area: Float property

Symbolic representation of area.

valor.schemas.Polygon.boundary: typing.List[typing.Tuple[float, float]] property

The boundary of the polygon.

Returns:

Type Description
List[Tuple(float, float)]

A list of points.

valor.schemas.Polygon.holes: typing.List[typing.List[typing.Tuple[float, float]]] property

typing.Any holes in the polygon.

Returns:

Type Description
List[List[Tuple(float, float)]]

A list of holes.

valor.schemas.Polygon.xmax: float property

Maximum x-value.

Returns:

Type Description
float

valor.schemas.Polygon.xmin: float property

Minimum x-value.

Returns:

Type Description
float

valor.schemas.Polygon.ymax: float property

Maximum y-value.

Returns:

Type Description
float

valor.schemas.Polygon.ymin: float property

Minimum y-value.

Returns:

Type Description
float

Functions

valor.schemas.Polygon.decode_value(value) classmethod

Decode object from JSON compatible dictionary.

Source code in valor/schemas/symbolic/types.py
@classmethod
def decode_value(
    cls,
    value: typing.Optional[typing.List[typing.List[typing.List[float]]]],
):
    """Decode object from JSON compatible dictionary."""
    if value is None:
        return None
    return cls(
        [
            [(point[0], point[1]) for point in subpolygon]
            for subpolygon in value
        ]
    )