Skip to content

Spatial Expressions

All expressions listed are avaliable under the .spatial namespace.

Spatial Polars expressions.

This module provides a spatial namespace of polars expressions which compute various spatial properties, measurements, predicates, and operations.

GeometryProperties

Expressions derived from shapely's geometry properties.

Source code in src\spatial_polars\spatialexpr.py
class GeometryProperties:
    """Expressions derived from shapely's [geometry properties](https://shapely.readthedocs.io/en/stable/properties.html)."""

    def __init__(self, expr: pl.Expr) -> None:
        """For making polars expressions of geometry properties."""
        self._expr = expr

    def force_2d(self) -> pl.Expr:
        """Force the dimensionality of a geometry to 2D."""
        return self._expr.map_batches(
            lambda s: s.spatial.force_2d(),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def force_3d(self) -> pl.Expr:
        """Force the dimensionality of a geometry to 3D.

        2D geometries will get the provided Z coordinate; Z coordinates of 3D geometries
        are unchanged (unless they are nan).

        Note that for empty geometries, 3D is only supported since GEOS 3.9 and then
        still only for simple geometries (non-collections).
        """
        return self._expr.map_batches(
            lambda s: s.spatial.force_3d(),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def get_coordinate_dimension(self) -> pl.Expr:
        """Return the dimensionality of the coordinates in a geometry (2, 3 or 4).

        The return value can be one of the following:

        Return 2 for geometries with XY coordinate types,

        Return 3 for XYZ or XYM coordinate types (distinguished by has_z() or has_m()),

        Return 4 for XYZM coordinate types,

        Return -1 for missing geometries (None values).

        Note that with GEOS < 3.12, if the first Z coordinate equals nan, this function
        will return 2. Geometries with M coordinates are supported with GEOS >= 3.12.
        """
        return self._expr.map_batches(
            lambda s: s.spatial.get_coordinate_dimension(),
            return_dtype=pl.Int8,
            is_elementwise=True,
        )

    def get_dimensions(self) -> pl.Expr:
        """Return the inherent dimensionality of a geometry.

        The inherent dimension is 0 for points, 1 for linestrings and linearrings, and 2
        for polygons. For geometrycollections it is the max of the containing elements.
        Empty collections and None values return -1.
        """
        return self._expr.map_batches(
            lambda s: s.spatial.get_dimensions(),
            return_dtype=pl.Int8,
            is_elementwise=True,
        )

    def get_exterior_ring(self) -> pl.Expr:
        """Return the exterior ring of a polygon."""
        return self._expr.map_batches(
            lambda s: s.spatial.get_exterior_ring(),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def get_geometry(self, index: int) -> pl.Expr:
        """Return the nth geometry from a collection of geometries.

        Parameters
        ----------
        index
            Negative values count from the end of the collection backwards.

        """
        if index is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.get_geometry(index),
                return_dtype=spatial_series_dtype,
                is_elementwise=True,
            )

        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: combined.struct[0].spatial.get_geometry(
                combined.struct[1],
            ),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def get_interior_ring(self, index: int) -> pl.Expr:
        """Return the nth interior ring of a polygon.

        The number of interior rings in non-polygons equals zero.
        """
        if index is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.get_interior_ring(index),
                return_dtype=spatial_series_dtype,
                is_elementwise=True,
            )

        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: combined.struct[0].spatial.get_interior_ring(
                combined.struct[1],
            ),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def get_num_coordinates(self) -> pl.Expr:
        """Return the total number of coordinates in a geometry.

        Returns 0 for not-a-geometry values.
        """
        return self._expr.map_batches(
            lambda s: s.spatial.get_num_coordinates(),
            return_dtype=pl.Int32,
            is_elementwise=True,
        )

    def get_num_interior_rings(self) -> pl.Expr:
        """Return number of internal rings in a polygon.

        Returns 0 for not-a-geometry values.
        """
        return self._expr.map_batches(
            lambda s: s.spatial.get_num_interior_rings(),
            return_dtype=pl.Int32,
            is_elementwise=True,
        )

    def get_num_points(self) -> pl.Expr:
        """Return the number of points in a linestring or linearring.

        Returns 0 for not-a-geometry values. The number of points in geometries other
        than linestring or linearring equals zero.
        """
        return self._expr.map_batches(
            lambda s: s.spatial.get_num_points(),
            return_dtype=pl.Int32,
            is_elementwise=True,
        )

    def get_point(self, index: int) -> pl.Expr:
        """Return the nth point of a linestring or linearring."""
        if index is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.get_point(index),
                return_dtype=spatial_series_dtype,
                is_elementwise=True,
            )
        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: combined.struct[0].spatial.get_point(
                combined.struct[1],
            ),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def get_type_id(self) -> pl.Expr:
        """Return the type ID of a geometry.

        Possible values are:

        None (missing) is -1

        POINT is 0

        LINESTRING is 1

        LINEARRING is 2

        POLYGON is 3

        MULTIPOINT is 4

        MULTILINESTRING is 5

        MULTIPOLYGON is 6

        GEOMETRYCOLLECTION is 7
        """
        return self._expr.map_batches(
            lambda s: s.spatial.get_type_id(),
            return_dtype=pl.Int8,
            is_elementwise=True,
        )

    def get_x(self) -> pl.Expr:
        """Return the x-coordinate of a point."""
        return self._expr.map_batches(
            lambda s: s.spatial.get_x(),
            return_dtype=pl.Float64,
            is_elementwise=True,
        )

    def get_y(self) -> pl.Expr:
        """Return the y-coordinate of a point."""
        return self._expr.map_batches(
            lambda s: s.spatial.get_y(),
            return_dtype=pl.Float64,
            is_elementwise=True,
        )

    def get_z(self) -> pl.Expr:
        """Return the z-coordinate of a point."""
        return self._expr.map_batches(
            lambda s: s.spatial.get_z(),
            return_dtype=pl.Float64,
            is_elementwise=True,
        )

    def get_m(self) -> pl.Expr:
        """Return the m-coordinate of a point."""
        return self._expr.map_batches(
            lambda s: s.spatial.get_m(),
            return_dtype=pl.Float64,
            is_elementwise=True,
        )

__init__(expr)

For making polars expressions of geometry properties.

Source code in src\spatial_polars\spatialexpr.py
def __init__(self, expr: pl.Expr) -> None:
    """For making polars expressions of geometry properties."""
    self._expr = expr

force_2d()

Force the dimensionality of a geometry to 2D.

Source code in src\spatial_polars\spatialexpr.py
def force_2d(self) -> pl.Expr:
    """Force the dimensionality of a geometry to 2D."""
    return self._expr.map_batches(
        lambda s: s.spatial.force_2d(),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

force_3d()

Force the dimensionality of a geometry to 3D.

2D geometries will get the provided Z coordinate; Z coordinates of 3D geometries are unchanged (unless they are nan).

Note that for empty geometries, 3D is only supported since GEOS 3.9 and then still only for simple geometries (non-collections).

Source code in src\spatial_polars\spatialexpr.py
def force_3d(self) -> pl.Expr:
    """Force the dimensionality of a geometry to 3D.

    2D geometries will get the provided Z coordinate; Z coordinates of 3D geometries
    are unchanged (unless they are nan).

    Note that for empty geometries, 3D is only supported since GEOS 3.9 and then
    still only for simple geometries (non-collections).
    """
    return self._expr.map_batches(
        lambda s: s.spatial.force_3d(),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

get_coordinate_dimension()

Return the dimensionality of the coordinates in a geometry (2, 3 or 4).

The return value can be one of the following:

Return 2 for geometries with XY coordinate types,

Return 3 for XYZ or XYM coordinate types (distinguished by has_z() or has_m()),

Return 4 for XYZM coordinate types,

Return -1 for missing geometries (None values).

Note that with GEOS < 3.12, if the first Z coordinate equals nan, this function will return 2. Geometries with M coordinates are supported with GEOS >= 3.12.

Source code in src\spatial_polars\spatialexpr.py
def get_coordinate_dimension(self) -> pl.Expr:
    """Return the dimensionality of the coordinates in a geometry (2, 3 or 4).

    The return value can be one of the following:

    Return 2 for geometries with XY coordinate types,

    Return 3 for XYZ or XYM coordinate types (distinguished by has_z() or has_m()),

    Return 4 for XYZM coordinate types,

    Return -1 for missing geometries (None values).

    Note that with GEOS < 3.12, if the first Z coordinate equals nan, this function
    will return 2. Geometries with M coordinates are supported with GEOS >= 3.12.
    """
    return self._expr.map_batches(
        lambda s: s.spatial.get_coordinate_dimension(),
        return_dtype=pl.Int8,
        is_elementwise=True,
    )

get_dimensions()

Return the inherent dimensionality of a geometry.

The inherent dimension is 0 for points, 1 for linestrings and linearrings, and 2 for polygons. For geometrycollections it is the max of the containing elements. Empty collections and None values return -1.

Source code in src\spatial_polars\spatialexpr.py
def get_dimensions(self) -> pl.Expr:
    """Return the inherent dimensionality of a geometry.

    The inherent dimension is 0 for points, 1 for linestrings and linearrings, and 2
    for polygons. For geometrycollections it is the max of the containing elements.
    Empty collections and None values return -1.
    """
    return self._expr.map_batches(
        lambda s: s.spatial.get_dimensions(),
        return_dtype=pl.Int8,
        is_elementwise=True,
    )

get_exterior_ring()

Return the exterior ring of a polygon.

Source code in src\spatial_polars\spatialexpr.py
def get_exterior_ring(self) -> pl.Expr:
    """Return the exterior ring of a polygon."""
    return self._expr.map_batches(
        lambda s: s.spatial.get_exterior_ring(),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

get_geometry(index)

Return the nth geometry from a collection of geometries.

Parameters:

Name Type Description Default
index int

Negative values count from the end of the collection backwards.

required
Source code in src\spatial_polars\spatialexpr.py
def get_geometry(self, index: int) -> pl.Expr:
    """Return the nth geometry from a collection of geometries.

    Parameters
    ----------
    index
        Negative values count from the end of the collection backwards.

    """
    if index is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.get_geometry(index),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: combined.struct[0].spatial.get_geometry(
            combined.struct[1],
        ),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

get_interior_ring(index)

Return the nth interior ring of a polygon.

The number of interior rings in non-polygons equals zero.

Source code in src\spatial_polars\spatialexpr.py
def get_interior_ring(self, index: int) -> pl.Expr:
    """Return the nth interior ring of a polygon.

    The number of interior rings in non-polygons equals zero.
    """
    if index is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.get_interior_ring(index),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: combined.struct[0].spatial.get_interior_ring(
            combined.struct[1],
        ),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

get_num_coordinates()

Return the total number of coordinates in a geometry.

Returns 0 for not-a-geometry values.

Source code in src\spatial_polars\spatialexpr.py
def get_num_coordinates(self) -> pl.Expr:
    """Return the total number of coordinates in a geometry.

    Returns 0 for not-a-geometry values.
    """
    return self._expr.map_batches(
        lambda s: s.spatial.get_num_coordinates(),
        return_dtype=pl.Int32,
        is_elementwise=True,
    )

get_num_interior_rings()

Return number of internal rings in a polygon.

Returns 0 for not-a-geometry values.

Source code in src\spatial_polars\spatialexpr.py
def get_num_interior_rings(self) -> pl.Expr:
    """Return number of internal rings in a polygon.

    Returns 0 for not-a-geometry values.
    """
    return self._expr.map_batches(
        lambda s: s.spatial.get_num_interior_rings(),
        return_dtype=pl.Int32,
        is_elementwise=True,
    )

get_num_points()

Return the number of points in a linestring or linearring.

Returns 0 for not-a-geometry values. The number of points in geometries other than linestring or linearring equals zero.

Source code in src\spatial_polars\spatialexpr.py
def get_num_points(self) -> pl.Expr:
    """Return the number of points in a linestring or linearring.

    Returns 0 for not-a-geometry values. The number of points in geometries other
    than linestring or linearring equals zero.
    """
    return self._expr.map_batches(
        lambda s: s.spatial.get_num_points(),
        return_dtype=pl.Int32,
        is_elementwise=True,
    )

get_point(index)

Return the nth point of a linestring or linearring.

Source code in src\spatial_polars\spatialexpr.py
def get_point(self, index: int) -> pl.Expr:
    """Return the nth point of a linestring or linearring."""
    if index is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.get_point(index),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )
    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: combined.struct[0].spatial.get_point(
            combined.struct[1],
        ),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

get_type_id()

Return the type ID of a geometry.

Possible values are:

None (missing) is -1

POINT is 0

LINESTRING is 1

LINEARRING is 2

POLYGON is 3

MULTIPOINT is 4

MULTILINESTRING is 5

MULTIPOLYGON is 6

GEOMETRYCOLLECTION is 7

Source code in src\spatial_polars\spatialexpr.py
def get_type_id(self) -> pl.Expr:
    """Return the type ID of a geometry.

    Possible values are:

    None (missing) is -1

    POINT is 0

    LINESTRING is 1

    LINEARRING is 2

    POLYGON is 3

    MULTIPOINT is 4

    MULTILINESTRING is 5

    MULTIPOLYGON is 6

    GEOMETRYCOLLECTION is 7
    """
    return self._expr.map_batches(
        lambda s: s.spatial.get_type_id(),
        return_dtype=pl.Int8,
        is_elementwise=True,
    )

get_x()

Return the x-coordinate of a point.

Source code in src\spatial_polars\spatialexpr.py
def get_x(self) -> pl.Expr:
    """Return the x-coordinate of a point."""
    return self._expr.map_batches(
        lambda s: s.spatial.get_x(),
        return_dtype=pl.Float64,
        is_elementwise=True,
    )

get_y()

Return the y-coordinate of a point.

Source code in src\spatial_polars\spatialexpr.py
def get_y(self) -> pl.Expr:
    """Return the y-coordinate of a point."""
    return self._expr.map_batches(
        lambda s: s.spatial.get_y(),
        return_dtype=pl.Float64,
        is_elementwise=True,
    )

get_z()

Return the z-coordinate of a point.

Source code in src\spatial_polars\spatialexpr.py
def get_z(self) -> pl.Expr:
    """Return the z-coordinate of a point."""
    return self._expr.map_batches(
        lambda s: s.spatial.get_z(),
        return_dtype=pl.Float64,
        is_elementwise=True,
    )

get_m()

Return the m-coordinate of a point.

Source code in src\spatial_polars\spatialexpr.py
def get_m(self) -> pl.Expr:
    """Return the m-coordinate of a point."""
    return self._expr.map_batches(
        lambda s: s.spatial.get_m(),
        return_dtype=pl.Float64,
        is_elementwise=True,
    )

Measurement

Expressions derived from shapely's Measurements.

Source code in src\spatial_polars\spatialexpr.py
class Measurement:
    """Expressions derived from shapely's [Measurements](https://shapely.readthedocs.io/en/stable/measurement.html)."""

    def __init__(self, expr: pl.Expr) -> None:
        """For making polars expressions of Measurements."""
        self._expr = expr

    def area(self) -> pl.Expr:
        """Compute the area of a (multi)polygon."""
        return self._expr.map_batches(
            lambda s: s.spatial.area(),
            return_dtype=pl.Float64,
            is_elementwise=True,
        )

    def distance(self, other: shapely.Geometry | None = None) -> pl.Expr:
        """Compute the Cartesian distance between two geometries.

        Parameters
        ----------
        other
            A shapely geometry object

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)
        for details.

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.distance(other),
                return_dtype=pl.Float64,
                is_elementwise=True,
            )
        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: shapely.distance(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1].spatial.to_shapely_array(),
            ),
            return_dtype=pl.Float64,
            is_elementwise=True,
        )

    def bounds(self) -> pl.Expr:
        """Compute the bounds (extent) of a geometry.

        For each geometry these 4 numbers are returned as a struct: min x, min y, max x,
        max y.
        """
        return self._expr.map_batches(
            lambda s: s.spatial.bounds(),
            return_dtype=pl.Array(pl.Float64, 4),
            is_elementwise=True,
        )

    def length(self) -> pl.Expr:
        """Compute the length of a (multi)linestring or polygon perimeter."""
        return self._expr.map_batches(
            lambda s: s.spatial.length(),
            return_dtype=pl.Float64,
            is_elementwise=True,
        )

    def hausdorff_distance(
        self,
        other: shapely.Geometry | None = None,
        densify: float | None = None,
    ) -> pl.Expr:
        """Compute the discrete Hausdorff distance between two geometries.

        The Hausdorff distance is a measure of similarity: it is the greatest distance
        between any point in A and the closest point in B. The discrete distance is an
        approximation of this metric: only vertices are considered. The parameter
        `densify` makes this approximation less coarse by splitting the line segments
        between vertices before computing the distance.

        Parameters
        ----------
        other
            A shapely geometry object

        densify
            The value of densify is required to be between 0 and 1.

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)
        for details.

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.hausdorff_distance(other, densify),
                return_dtype=pl.Float64,
                is_elementwise=True,
            )

        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: shapely.hausdorff_distance(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1].spatial.to_shapely_array(),
                densify=densify,
            ),
            return_dtype=pl.Float64,
            is_elementwise=True,
        )

    def frechet_distance(
        self,
        other: shapely.Geometry | None = None,
        densify: float | None = None,
    ) -> pl.Expr:
        """Compute the discrete Fréchet distance between two geometries.

        The Fréchet distance is a measure of similarity: it is the greatest distance
        between any point in A and the closest point in B. The discrete distance is an
        approximation of this metric: only vertices are considered. The parameter
        `densify` makes this approximation less coarse by splitting the line segments
        between vertices before computing the distance.

        Fréchet distance sweep continuously along their respective curves and the
        direction of curves is significant. This makes it a better measure of similarity
        than Hausdorff distance for curve or surface matching.

        Parameters
        ----------
        other
            A shapely geometry object

        densify
            The value of densify is required to be between 0 and 1.

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)
        for details.

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.frechet_distance(other, densify),
                return_dtype=pl.Float64,
                is_elementwise=True,
            )
        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: shapely.frechet_distance(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1].spatial.to_shapely_array(),
                densify=densify,
            ),
            return_dtype=pl.Float64,
            is_elementwise=True,
        )

    def minimum_clearance(self) -> pl.Expr:
        """Compute the Minimum Clearance distance.

        A geometry's "minimum clearance" is the smallest distance by which a vertex of
        the geometry could be moved to produce an invalid geometry.

        If no minimum clearance exists for a geometry (for example, a single point, or
        an empty geometry), infinity is returned.
        """
        return self._expr.map_batches(
            lambda s: s.spatial.minimum_clearance(),
            return_dtype=pl.Float64,
            is_elementwise=True,
        )

    def minimum_bounding_radius(self) -> pl.Expr:
        """Compute the radius of the minimum bounding circle of an input geometry."""
        return self._expr.map_batches(
            lambda s: s.spatial.minimum_bounding_radius(),
            return_dtype=pl.Float64,
            is_elementwise=True,
        )

__init__(expr)

For making polars expressions of Measurements.

Source code in src\spatial_polars\spatialexpr.py
def __init__(self, expr: pl.Expr) -> None:
    """For making polars expressions of Measurements."""
    self._expr = expr

area()

Compute the area of a (multi)polygon.

Source code in src\spatial_polars\spatialexpr.py
def area(self) -> pl.Expr:
    """Compute the area of a (multi)polygon."""
    return self._expr.map_batches(
        lambda s: s.spatial.area(),
        return_dtype=pl.Float64,
        is_elementwise=True,
    )

distance(other=None)

Compute the Cartesian distance between two geometries.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry for details.

Source code in src\spatial_polars\spatialexpr.py
def distance(self, other: shapely.Geometry | None = None) -> pl.Expr:
    """Compute the Cartesian distance between two geometries.

    Parameters
    ----------
    other
        A shapely geometry object

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)
    for details.

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.distance(other),
            return_dtype=pl.Float64,
            is_elementwise=True,
        )
    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: shapely.distance(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1].spatial.to_shapely_array(),
        ),
        return_dtype=pl.Float64,
        is_elementwise=True,
    )

bounds()

Compute the bounds (extent) of a geometry.

For each geometry these 4 numbers are returned as a struct: min x, min y, max x, max y.

Source code in src\spatial_polars\spatialexpr.py
def bounds(self) -> pl.Expr:
    """Compute the bounds (extent) of a geometry.

    For each geometry these 4 numbers are returned as a struct: min x, min y, max x,
    max y.
    """
    return self._expr.map_batches(
        lambda s: s.spatial.bounds(),
        return_dtype=pl.Array(pl.Float64, 4),
        is_elementwise=True,
    )

length()

Compute the length of a (multi)linestring or polygon perimeter.

Source code in src\spatial_polars\spatialexpr.py
def length(self) -> pl.Expr:
    """Compute the length of a (multi)linestring or polygon perimeter."""
    return self._expr.map_batches(
        lambda s: s.spatial.length(),
        return_dtype=pl.Float64,
        is_elementwise=True,
    )

hausdorff_distance(other=None, densify=None)

Compute the discrete Hausdorff distance between two geometries.

The Hausdorff distance is a measure of similarity: it is the greatest distance between any point in A and the closest point in B. The discrete distance is an approximation of this metric: only vertices are considered. The parameter densify makes this approximation less coarse by splitting the line segments between vertices before computing the distance.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
densify float | None

The value of densify is required to be between 0 and 1.

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry for details.

Source code in src\spatial_polars\spatialexpr.py
def hausdorff_distance(
    self,
    other: shapely.Geometry | None = None,
    densify: float | None = None,
) -> pl.Expr:
    """Compute the discrete Hausdorff distance between two geometries.

    The Hausdorff distance is a measure of similarity: it is the greatest distance
    between any point in A and the closest point in B. The discrete distance is an
    approximation of this metric: only vertices are considered. The parameter
    `densify` makes this approximation less coarse by splitting the line segments
    between vertices before computing the distance.

    Parameters
    ----------
    other
        A shapely geometry object

    densify
        The value of densify is required to be between 0 and 1.

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)
    for details.

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.hausdorff_distance(other, densify),
            return_dtype=pl.Float64,
            is_elementwise=True,
        )

    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: shapely.hausdorff_distance(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1].spatial.to_shapely_array(),
            densify=densify,
        ),
        return_dtype=pl.Float64,
        is_elementwise=True,
    )

frechet_distance(other=None, densify=None)

Compute the discrete Fréchet distance between two geometries.

The Fréchet distance is a measure of similarity: it is the greatest distance between any point in A and the closest point in B. The discrete distance is an approximation of this metric: only vertices are considered. The parameter densify makes this approximation less coarse by splitting the line segments between vertices before computing the distance.

Fréchet distance sweep continuously along their respective curves and the direction of curves is significant. This makes it a better measure of similarity than Hausdorff distance for curve or surface matching.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
densify float | None

The value of densify is required to be between 0 and 1.

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry for details.

Source code in src\spatial_polars\spatialexpr.py
def frechet_distance(
    self,
    other: shapely.Geometry | None = None,
    densify: float | None = None,
) -> pl.Expr:
    """Compute the discrete Fréchet distance between two geometries.

    The Fréchet distance is a measure of similarity: it is the greatest distance
    between any point in A and the closest point in B. The discrete distance is an
    approximation of this metric: only vertices are considered. The parameter
    `densify` makes this approximation less coarse by splitting the line segments
    between vertices before computing the distance.

    Fréchet distance sweep continuously along their respective curves and the
    direction of curves is significant. This makes it a better measure of similarity
    than Hausdorff distance for curve or surface matching.

    Parameters
    ----------
    other
        A shapely geometry object

    densify
        The value of densify is required to be between 0 and 1.

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)
    for details.

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.frechet_distance(other, densify),
            return_dtype=pl.Float64,
            is_elementwise=True,
        )
    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: shapely.frechet_distance(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1].spatial.to_shapely_array(),
            densify=densify,
        ),
        return_dtype=pl.Float64,
        is_elementwise=True,
    )

minimum_clearance()

Compute the Minimum Clearance distance.

A geometry's "minimum clearance" is the smallest distance by which a vertex of the geometry could be moved to produce an invalid geometry.

If no minimum clearance exists for a geometry (for example, a single point, or an empty geometry), infinity is returned.

Source code in src\spatial_polars\spatialexpr.py
def minimum_clearance(self) -> pl.Expr:
    """Compute the Minimum Clearance distance.

    A geometry's "minimum clearance" is the smallest distance by which a vertex of
    the geometry could be moved to produce an invalid geometry.

    If no minimum clearance exists for a geometry (for example, a single point, or
    an empty geometry), infinity is returned.
    """
    return self._expr.map_batches(
        lambda s: s.spatial.minimum_clearance(),
        return_dtype=pl.Float64,
        is_elementwise=True,
    )

minimum_bounding_radius()

Compute the radius of the minimum bounding circle of an input geometry.

Source code in src\spatial_polars\spatialexpr.py
def minimum_bounding_radius(self) -> pl.Expr:
    """Compute the radius of the minimum bounding circle of an input geometry."""
    return self._expr.map_batches(
        lambda s: s.spatial.minimum_bounding_radius(),
        return_dtype=pl.Float64,
        is_elementwise=True,
    )

Predicates

Expressions derived from shapely's Predicates.

Source code in src\spatial_polars\spatialexpr.py
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
class Predicates:
    """Expressions derived from shapely's [Predicates](https://shapely.readthedocs.io/en/stable/predicates.html)."""

    def __init__(self, expr: pl.Expr) -> None:
        """For making polars expressions of Predicates."""
        self._expr = expr

    def has_z(self) -> pl.Expr:
        """Return True if a geometry has Z coordinates.

        Note that for GEOS < 3.12 this function returns False if the (first) Z
        coordinate equals NaN.
        """
        return self._expr.map_batches(
            lambda s: s.spatial.has_z(),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def is_ccw(self) -> pl.Expr:
        """Return True if a linestring or linearring is counterclockwise.

        Note that there are no checks on whether lines are actually closed and not
        self-intersecting, while this is a requirement for is_ccw. The recommended
        usage of this function for linestrings is is_ccw(g) & is_simple(g) and for
        linearrings is_ccw(g) & is_valid(g).
        """
        return self._expr.map_batches(
            lambda s: s.spatial.is_ccw(),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def is_closed(self) -> pl.Expr:
        """Return True if a linestring's first and last points are equal."""
        return self._expr.map_batches(
            lambda s: s.spatial.is_closed(),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def is_empty(self) -> pl.Expr:
        """Return True if a geometry is an empty point, polygon, etc."""
        return self._expr.map_batches(
            lambda s: s.spatial.is_empty(),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def is_geometry(self) -> pl.Expr:
        """Return True if the object is a geometry."""
        return self._expr.map_batches(
            lambda s: s.spatial.is_geometry(),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def is_missing(self) -> pl.Expr:
        """Return True if the object is not a geometry (None)."""
        return self._expr.map_batches(
            lambda s: s.spatial.is_missing(),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def is_ring(self) -> pl.Expr:
        """Return True if a linestring is closed and simple.

        This function will return False for non-linestrings.
        """
        return self._expr.map_batches(
            lambda s: s.spatial.is_ring(),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def is_simple(self) -> pl.Expr:
        """Return True if the geometry is simple.

        A simple geometry has no anomalous geometric points, such as self-intersections
        or self tangency.

        Note that polygons and linearrings are assumed to be simple. Use is_valid to
        check these kind of geometries for self-intersections.

        This function will return False for geometrycollections.
        """
        return self._expr.map_batches(
            lambda s: s.spatial.is_simple(),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def is_valid(self) -> pl.Expr:
        """Return True if a geometry is well formed.

        Returns False for missing values.
        """
        return self._expr.map_batches(
            lambda s: s.spatial.is_valid(),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def is_valid_input(self) -> pl.Expr:
        """Return True if the object is a geometry or None."""
        return self._expr.map_batches(
            lambda s: s.spatial.is_valid_input(),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def is_valid_reason(self) -> pl.Expr:
        """Return a string stating if a geometry is valid and if not, why.

        Returns None for missing values.

        """
        return self._expr.map_batches(
            lambda s: s.spatial.is_valid_reason(),
            return_dtype=pl.String,
            is_elementwise=True,
        )

    def crosses(self, other: shapely.Geometry | None = None) -> pl.Expr:
        """Return True if A and B spatially cross.

        A crosses B if they have some but not all interior points in common, the
        intersection is one dimension less than the maximum dimension of A or B, and
        the intersection is not equal to either A or B.

        Parameters
        ----------
        other
            A shapely geometry object

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.crosses(other),
                return_dtype=pl.Boolean,
                is_elementwise=True,
            )

        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: shapely.crosses(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1].spatial.to_shapely_array(),
            ),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def contains(self, other: shapely.Geometry | None = None) -> pl.Expr:
        """Return True if geometry B is completely inside geometry A.

        A contains B if no points of B lie in the exterior of A and at least one point
        of the interior of B lies in the interior of A.

        Parameters
        ----------
        other
            A shapely geometry object

        Note
        ----
        Following this definition, a geometry does not contain its boundary, but it does
        contain itself. See contains_properly for a version where a geometry does not
        contain itself.

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.contains(other),
                return_dtype=pl.Boolean,
                is_elementwise=True,
            )
        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: shapely.contains(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1].spatial.to_shapely_array(),
            ),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def contains_properly(self, other: shapely.Geometry | None = None) -> pl.Expr:
        """Return True if geometry B is completely inside geometry A, with no common boundary points.

        A contains B properly if B intersects the interior of A but not the boundary
        (or exterior). This means that a geometry A does not "contain properly" itself,
        which contrasts with the contains function, where common points on the boundary
        are allowed.

        Parameters
        ----------
        other
            A shapely geometry object

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.contains_properly(other),
                return_dtype=pl.Boolean,
                is_elementwise=True,
            )

        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: shapely.contains_properly(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1].spatial.to_shapely_array(),
            ),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def covered_by(self, other: shapely.Geometry | None = None) -> pl.Expr:
        """Return True if no point in geometry A is outside geometry B.

        Parameters
        ----------
        other
            A shapely geometry object

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.covered_by(other),
                return_dtype=pl.Boolean,
                is_elementwise=True,
            )
        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: shapely.covered_by(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1].spatial.to_shapely_array(),
            ),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def covers(self, other: shapely.Geometry | None = None) -> pl.Expr:
        """Return True if no point in geometry B is outside geometry A.

        Parameters
        ----------
        other
            A shapely geometry object

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.covers(other),
                return_dtype=pl.Boolean,
                is_elementwise=True,
            )
        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: shapely.covers(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1].spatial.to_shapely_array(),
            ),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def disjoint(self, other: shapely.Geometry | None = None) -> pl.Expr:
        """Return True if A and B do not share any point in space.

        Disjoint implies that overlaps, touches, within, and intersects are False. Note
        missing (None) values are never disjoint.

        Parameters
        ----------
        other
            A shapely geometry object

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.disjoint(other),
                return_dtype=pl.Boolean,
                is_elementwise=True,
            )
        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: shapely.disjoint(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1].spatial.to_shapely_array(),
            ),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def equals(self, other: shapely.Geometry | None = None) -> pl.Expr:
        """Return True if A and B are spatially equal.

        If A is within B and B is within A, A and B are considered equal. The ordering
        of points can be different.

        Parameters
        ----------
        other
            A shapely geometry object

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.equals(other),
                return_dtype=pl.Boolean,
                is_elementwise=True,
            )

        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: shapely.equals(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1].spatial.to_shapely_array(),
            ),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def intersects(self, other: shapely.Geometry | None = None) -> pl.Expr:
        """Return True if A and B share any portion of space.

        Intersects implies that overlaps, touches, covers, or within are True.

        Parameters
        ----------
        other
            A shapely geometry object

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.intersects(other),
                return_dtype=pl.Boolean,
                is_elementwise=True,
            )
        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: shapely.intersects(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1].spatial.to_shapely_array(),
            ),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def overlaps(self, other: shapely.Geometry | None = None) -> pl.Expr:
        """Return True if A and B spatially overlap.

        A and B overlap if they have some but not all points/space in common, have the
        same dimension, and the intersection of the interiors of the two geometries has
        the same dimension as the geometries themselves. That is, only polyons can
        overlap other polygons and only lines can overlap other lines. If A covers or is
        within B, overlaps won't be True.

        Parameters
        ----------
        other
            A shapely geometry object

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.overlaps(other),
                return_dtype=pl.Boolean,
                is_elementwise=True,
            )

        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: shapely.overlaps(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1].spatial.to_shapely_array(),
            ),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def touches(self, other: shapely.Geometry | None = None) -> pl.Expr:
        """Return True if the only points shared between A and B are on their boundaries.

        Parameters
        ----------
        other
            A shapely geometry object

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.touches(other),
                return_dtype=pl.Boolean,
                is_elementwise=True,
            )
        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: shapely.touches(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1].spatial.to_shapely_array(),
            ),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def within(self, other: shapely.Geometry | None = None) -> pl.Expr:
        """Return True if geometry A is completely inside geometry B.

        A is within B if no points of A lie in the exterior of B and at least one point
        of the interior of A lies in the interior of B.

        Parameters
        ----------
        other
            A shapely geometry object

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.within(other),
                return_dtype=pl.Boolean,
                is_elementwise=True,
            )

        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: shapely.within(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1].spatial.to_shapely_array(),
            ),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def relate(self, other: shapely.Geometry | None = None) -> pl.Expr:
        """Return a string representation of the DE-9IM intersection matrix.

        Parameters
        ----------
        other
            A shapely geometry object

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.relate(other),
                return_dtype=pl.String,
                is_elementwise=True,
            )

        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: shapely.relate(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1].spatial.to_shapely_array(),
            ),
            return_dtype=pl.String,
            is_elementwise=True,
        )

    def contains_xy(self, x: float | None = None, y: float | None = None) -> pl.Expr:
        """Return True if the Point (x, y) is completely inside geom.

        This is a special-case (and faster) variant of the contains function which
        avoids having to create a Point object if you start from x/y coordinates.

        Note that in the case of points, the contains_properly predicate is equivalent
        to contains.

        See the docstring of contains for more details about the predicate.

        Parameters
        ----------
        x
            The X coordinate to check

        y
            The Y coordinate to check

        One geometry different x/y coordinate input
        -------------------------------------------
        **To compute between the values in the series and a single x,y pair** provide
        the `x` and `y` parameters.

        **To compute between two geometries in a column and columns of x/y coordinates
        of the frame** wrap all columns into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if x is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.contains_xy(x, y),
                return_dtype=pl.Boolean,
                is_elementwise=True,
            )
        # expect struct with a geometry and x/y fields.
        return self._expr.map_batches(
            lambda combined: shapely.contains_xy(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1],
                combined.struct[2],
            ),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def dwithin(
        self,
        other: shapely.Geometry | None = None,
        distance: float | None = None,
    ) -> pl.Expr:
        """Return True if the geometries are within a given distance.

        Using this function is more efficient than computing the distance and comparing
        the result.

        Parameters
        ----------
        other
            A shapely geometry object

        distance
            The distance to check if the geometries are within

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.dwithin(other, distance),
                return_dtype=pl.Boolean,
                is_elementwise=True,
            )

        # expect struct with a two geometry and distance fields.
        return self._expr.map_batches(
            lambda combined: shapely.dwithin(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1].spatial.to_shapely_array(),
                combined.struct[2],
            ),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def intersects_xy(self, x: float | None, y: float | None) -> pl.Expr:
        """Return True if geom and the Point (x, y) share any portion of space.

        This is a special-case (and faster) variant of the intersects function which
        avoids having to create a Point object if you start from x/y coordinates.

        See the docstring of intersects for more details about the predicate.

        Parameters
        ----------
        x
            The X coordinate to check

        y
            The Y coordinate to check

        One geometry different x/y coordinate input
        -------------------------------------------
        **To compute between the values in the series and a single x,y pair** provide
        the `x` and `y` parameters.

        **To compute between two geometries in a column and columns of x/y coordinates
        of the frame** wrap all columns into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if x is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.intersects_xy(x, y),
                return_dtype=pl.Boolean,
                is_elementwise=True,
            )
        # expect struct with a geometry and x/y fields.
        return self._expr.map_batches(
            lambda combined: shapely.intersects_xy(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1],
                combined.struct[2],
            ),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def equals_exact(
        self,
        other: shapely.Geometry | None = None,
        tolerance: float | None = None,
    ) -> pl.Expr:
        """Return True if the geometries are structurally equivalent within a given tolerance.

        This method uses exact coordinate equality, which requires coordinates to be
        equal (within specified tolerance) and in the same order for all components
        (vertices, rings, or parts) of a geometry. This is in contrast with the equals
        function which uses spatial (topological) equality and does not require all
        components to be in the same order. Because of this, it is possible for equals
        to be True while equals_exact is False.

        The order of the coordinates can be normalized (by setting the normalize keyword
        to True) so that this function will return True when geometries are structurally
        equivalent but differ only in the ordering of vertices. However, this function
        will still return False if the order of interior rings within a Polygon or the
        order of geometries within a multi geometry are different.

        Parameters
        ----------
        other
            A shapely geometry object

        tolerance
            The tolerance to use in the comparison.

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.equals_exact(other, tolerance),
                return_dtype=pl.Boolean,
                is_elementwise=True,
            )
        # expect struct with two geometry and tolerance fields.
        return self._expr.map_batches(
            lambda combined: shapely.equals_exact(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1].spatial.to_shapely_array(),
                combined.struct[2],
            ),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    def relate_pattern(
        self,
        other: shapely.Geometry | None = None,
        pattern: str | None = None,
    ) -> pl.Expr:
        """Return True if the DE-9IM relationship code satisfies the pattern.

        This function compares the DE-9IM code string for two geometries against a
        specified pattern. If the string matches the pattern then True is returned,
        otherwise False. The pattern specified can be an exact match (0, 1 or 2), a
        boolean match (uppercase T or F), or a wildcard (*). For example, the pattern
        for the within predicate is 'T*F**F***'.

        Parameters
        ----------
        other
            A shapely geometry object

        pattern
            The pattern to match the DE-9IM relationship code against.

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.relate_pattern(other, pattern),
                return_dtype=pl.Boolean,
                is_elementwise=True,
            )
        # expect struct with two geometry and pattern fields.
        return self._expr.map_batches(
            lambda combined: shapely.relate_pattern(
                combined.struct[0].spatial.to_shapely_array(),
                combined.struct[1].spatial.to_shapely_array(),
                combined.struct[2],
            ),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

__init__(expr)

For making polars expressions of Predicates.

Source code in src\spatial_polars\spatialexpr.py
def __init__(self, expr: pl.Expr) -> None:
    """For making polars expressions of Predicates."""
    self._expr = expr

has_z()

Return True if a geometry has Z coordinates.

Note that for GEOS < 3.12 this function returns False if the (first) Z coordinate equals NaN.

Source code in src\spatial_polars\spatialexpr.py
def has_z(self) -> pl.Expr:
    """Return True if a geometry has Z coordinates.

    Note that for GEOS < 3.12 this function returns False if the (first) Z
    coordinate equals NaN.
    """
    return self._expr.map_batches(
        lambda s: s.spatial.has_z(),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

is_ccw()

Return True if a linestring or linearring is counterclockwise.

Note that there are no checks on whether lines are actually closed and not self-intersecting, while this is a requirement for is_ccw. The recommended usage of this function for linestrings is is_ccw(g) & is_simple(g) and for linearrings is_ccw(g) & is_valid(g).

Source code in src\spatial_polars\spatialexpr.py
def is_ccw(self) -> pl.Expr:
    """Return True if a linestring or linearring is counterclockwise.

    Note that there are no checks on whether lines are actually closed and not
    self-intersecting, while this is a requirement for is_ccw. The recommended
    usage of this function for linestrings is is_ccw(g) & is_simple(g) and for
    linearrings is_ccw(g) & is_valid(g).
    """
    return self._expr.map_batches(
        lambda s: s.spatial.is_ccw(),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

is_closed()

Return True if a linestring's first and last points are equal.

Source code in src\spatial_polars\spatialexpr.py
def is_closed(self) -> pl.Expr:
    """Return True if a linestring's first and last points are equal."""
    return self._expr.map_batches(
        lambda s: s.spatial.is_closed(),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

is_empty()

Return True if a geometry is an empty point, polygon, etc.

Source code in src\spatial_polars\spatialexpr.py
def is_empty(self) -> pl.Expr:
    """Return True if a geometry is an empty point, polygon, etc."""
    return self._expr.map_batches(
        lambda s: s.spatial.is_empty(),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

is_geometry()

Return True if the object is a geometry.

Source code in src\spatial_polars\spatialexpr.py
def is_geometry(self) -> pl.Expr:
    """Return True if the object is a geometry."""
    return self._expr.map_batches(
        lambda s: s.spatial.is_geometry(),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

is_missing()

Return True if the object is not a geometry (None).

Source code in src\spatial_polars\spatialexpr.py
def is_missing(self) -> pl.Expr:
    """Return True if the object is not a geometry (None)."""
    return self._expr.map_batches(
        lambda s: s.spatial.is_missing(),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

is_ring()

Return True if a linestring is closed and simple.

This function will return False for non-linestrings.

Source code in src\spatial_polars\spatialexpr.py
def is_ring(self) -> pl.Expr:
    """Return True if a linestring is closed and simple.

    This function will return False for non-linestrings.
    """
    return self._expr.map_batches(
        lambda s: s.spatial.is_ring(),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

is_simple()

Return True if the geometry is simple.

A simple geometry has no anomalous geometric points, such as self-intersections or self tangency.

Note that polygons and linearrings are assumed to be simple. Use is_valid to check these kind of geometries for self-intersections.

This function will return False for geometrycollections.

Source code in src\spatial_polars\spatialexpr.py
def is_simple(self) -> pl.Expr:
    """Return True if the geometry is simple.

    A simple geometry has no anomalous geometric points, such as self-intersections
    or self tangency.

    Note that polygons and linearrings are assumed to be simple. Use is_valid to
    check these kind of geometries for self-intersections.

    This function will return False for geometrycollections.
    """
    return self._expr.map_batches(
        lambda s: s.spatial.is_simple(),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

is_valid()

Return True if a geometry is well formed.

Returns False for missing values.

Source code in src\spatial_polars\spatialexpr.py
def is_valid(self) -> pl.Expr:
    """Return True if a geometry is well formed.

    Returns False for missing values.
    """
    return self._expr.map_batches(
        lambda s: s.spatial.is_valid(),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

is_valid_input()

Return True if the object is a geometry or None.

Source code in src\spatial_polars\spatialexpr.py
def is_valid_input(self) -> pl.Expr:
    """Return True if the object is a geometry or None."""
    return self._expr.map_batches(
        lambda s: s.spatial.is_valid_input(),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

is_valid_reason()

Return a string stating if a geometry is valid and if not, why.

Returns None for missing values.

Source code in src\spatial_polars\spatialexpr.py
def is_valid_reason(self) -> pl.Expr:
    """Return a string stating if a geometry is valid and if not, why.

    Returns None for missing values.

    """
    return self._expr.map_batches(
        lambda s: s.spatial.is_valid_reason(),
        return_dtype=pl.String,
        is_elementwise=True,
    )

crosses(other=None)

Return True if A and B spatially cross.

A crosses B if they have some but not all interior points in common, the intersection is one dimension less than the maximum dimension of A or B, and the intersection is not equal to either A or B.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def crosses(self, other: shapely.Geometry | None = None) -> pl.Expr:
    """Return True if A and B spatially cross.

    A crosses B if they have some but not all interior points in common, the
    intersection is one dimension less than the maximum dimension of A or B, and
    the intersection is not equal to either A or B.

    Parameters
    ----------
    other
        A shapely geometry object

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.crosses(other),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: shapely.crosses(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1].spatial.to_shapely_array(),
        ),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

contains(other=None)

Return True if geometry B is completely inside geometry A.

A contains B if no points of B lie in the exterior of A and at least one point of the interior of B lies in the interior of A.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
Note

Following this definition, a geometry does not contain its boundary, but it does contain itself. See contains_properly for a version where a geometry does not contain itself.

Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def contains(self, other: shapely.Geometry | None = None) -> pl.Expr:
    """Return True if geometry B is completely inside geometry A.

    A contains B if no points of B lie in the exterior of A and at least one point
    of the interior of B lies in the interior of A.

    Parameters
    ----------
    other
        A shapely geometry object

    Note
    ----
    Following this definition, a geometry does not contain its boundary, but it does
    contain itself. See contains_properly for a version where a geometry does not
    contain itself.

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.contains(other),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )
    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: shapely.contains(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1].spatial.to_shapely_array(),
        ),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

contains_properly(other=None)

Return True if geometry B is completely inside geometry A, with no common boundary points.

A contains B properly if B intersects the interior of A but not the boundary (or exterior). This means that a geometry A does not "contain properly" itself, which contrasts with the contains function, where common points on the boundary are allowed.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def contains_properly(self, other: shapely.Geometry | None = None) -> pl.Expr:
    """Return True if geometry B is completely inside geometry A, with no common boundary points.

    A contains B properly if B intersects the interior of A but not the boundary
    (or exterior). This means that a geometry A does not "contain properly" itself,
    which contrasts with the contains function, where common points on the boundary
    are allowed.

    Parameters
    ----------
    other
        A shapely geometry object

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.contains_properly(other),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: shapely.contains_properly(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1].spatial.to_shapely_array(),
        ),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

covered_by(other=None)

Return True if no point in geometry A is outside geometry B.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def covered_by(self, other: shapely.Geometry | None = None) -> pl.Expr:
    """Return True if no point in geometry A is outside geometry B.

    Parameters
    ----------
    other
        A shapely geometry object

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.covered_by(other),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )
    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: shapely.covered_by(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1].spatial.to_shapely_array(),
        ),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

covers(other=None)

Return True if no point in geometry B is outside geometry A.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def covers(self, other: shapely.Geometry | None = None) -> pl.Expr:
    """Return True if no point in geometry B is outside geometry A.

    Parameters
    ----------
    other
        A shapely geometry object

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.covers(other),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )
    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: shapely.covers(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1].spatial.to_shapely_array(),
        ),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

disjoint(other=None)

Return True if A and B do not share any point in space.

Disjoint implies that overlaps, touches, within, and intersects are False. Note missing (None) values are never disjoint.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def disjoint(self, other: shapely.Geometry | None = None) -> pl.Expr:
    """Return True if A and B do not share any point in space.

    Disjoint implies that overlaps, touches, within, and intersects are False. Note
    missing (None) values are never disjoint.

    Parameters
    ----------
    other
        A shapely geometry object

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.disjoint(other),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )
    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: shapely.disjoint(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1].spatial.to_shapely_array(),
        ),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

equals(other=None)

Return True if A and B are spatially equal.

If A is within B and B is within A, A and B are considered equal. The ordering of points can be different.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def equals(self, other: shapely.Geometry | None = None) -> pl.Expr:
    """Return True if A and B are spatially equal.

    If A is within B and B is within A, A and B are considered equal. The ordering
    of points can be different.

    Parameters
    ----------
    other
        A shapely geometry object

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.equals(other),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: shapely.equals(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1].spatial.to_shapely_array(),
        ),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

intersects(other=None)

Return True if A and B share any portion of space.

Intersects implies that overlaps, touches, covers, or within are True.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def intersects(self, other: shapely.Geometry | None = None) -> pl.Expr:
    """Return True if A and B share any portion of space.

    Intersects implies that overlaps, touches, covers, or within are True.

    Parameters
    ----------
    other
        A shapely geometry object

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.intersects(other),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )
    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: shapely.intersects(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1].spatial.to_shapely_array(),
        ),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

overlaps(other=None)

Return True if A and B spatially overlap.

A and B overlap if they have some but not all points/space in common, have the same dimension, and the intersection of the interiors of the two geometries has the same dimension as the geometries themselves. That is, only polyons can overlap other polygons and only lines can overlap other lines. If A covers or is within B, overlaps won't be True.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def overlaps(self, other: shapely.Geometry | None = None) -> pl.Expr:
    """Return True if A and B spatially overlap.

    A and B overlap if they have some but not all points/space in common, have the
    same dimension, and the intersection of the interiors of the two geometries has
    the same dimension as the geometries themselves. That is, only polyons can
    overlap other polygons and only lines can overlap other lines. If A covers or is
    within B, overlaps won't be True.

    Parameters
    ----------
    other
        A shapely geometry object

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.overlaps(other),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: shapely.overlaps(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1].spatial.to_shapely_array(),
        ),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

touches(other=None)

Return True if the only points shared between A and B are on their boundaries.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def touches(self, other: shapely.Geometry | None = None) -> pl.Expr:
    """Return True if the only points shared between A and B are on their boundaries.

    Parameters
    ----------
    other
        A shapely geometry object

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.touches(other),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )
    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: shapely.touches(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1].spatial.to_shapely_array(),
        ),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

within(other=None)

Return True if geometry A is completely inside geometry B.

A is within B if no points of A lie in the exterior of B and at least one point of the interior of A lies in the interior of B.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def within(self, other: shapely.Geometry | None = None) -> pl.Expr:
    """Return True if geometry A is completely inside geometry B.

    A is within B if no points of A lie in the exterior of B and at least one point
    of the interior of A lies in the interior of B.

    Parameters
    ----------
    other
        A shapely geometry object

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.within(other),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: shapely.within(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1].spatial.to_shapely_array(),
        ),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

relate(other=None)

Return a string representation of the DE-9IM intersection matrix.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def relate(self, other: shapely.Geometry | None = None) -> pl.Expr:
    """Return a string representation of the DE-9IM intersection matrix.

    Parameters
    ----------
    other
        A shapely geometry object

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.relate(other),
            return_dtype=pl.String,
            is_elementwise=True,
        )

    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: shapely.relate(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1].spatial.to_shapely_array(),
        ),
        return_dtype=pl.String,
        is_elementwise=True,
    )

contains_xy(x=None, y=None)

Return True if the Point (x, y) is completely inside geom.

This is a special-case (and faster) variant of the contains function which avoids having to create a Point object if you start from x/y coordinates.

Note that in the case of points, the contains_properly predicate is equivalent to contains.

See the docstring of contains for more details about the predicate.

Parameters:

Name Type Description Default
x float | None

The X coordinate to check

None
y float | None

The Y coordinate to check

None
One geometry different x/y coordinate input

To compute between the values in the series and a single x,y pair provide the x and y parameters.

To compute between two geometries in a column and columns of x/y coordinates of the frame wrap all columns into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def contains_xy(self, x: float | None = None, y: float | None = None) -> pl.Expr:
    """Return True if the Point (x, y) is completely inside geom.

    This is a special-case (and faster) variant of the contains function which
    avoids having to create a Point object if you start from x/y coordinates.

    Note that in the case of points, the contains_properly predicate is equivalent
    to contains.

    See the docstring of contains for more details about the predicate.

    Parameters
    ----------
    x
        The X coordinate to check

    y
        The Y coordinate to check

    One geometry different x/y coordinate input
    -------------------------------------------
    **To compute between the values in the series and a single x,y pair** provide
    the `x` and `y` parameters.

    **To compute between two geometries in a column and columns of x/y coordinates
    of the frame** wrap all columns into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if x is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.contains_xy(x, y),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )
    # expect struct with a geometry and x/y fields.
    return self._expr.map_batches(
        lambda combined: shapely.contains_xy(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1],
            combined.struct[2],
        ),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

dwithin(other=None, distance=None)

Return True if the geometries are within a given distance.

Using this function is more efficient than computing the distance and comparing the result.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
distance float | None

The distance to check if the geometries are within

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def dwithin(
    self,
    other: shapely.Geometry | None = None,
    distance: float | None = None,
) -> pl.Expr:
    """Return True if the geometries are within a given distance.

    Using this function is more efficient than computing the distance and comparing
    the result.

    Parameters
    ----------
    other
        A shapely geometry object

    distance
        The distance to check if the geometries are within

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.dwithin(other, distance),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )

    # expect struct with a two geometry and distance fields.
    return self._expr.map_batches(
        lambda combined: shapely.dwithin(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1].spatial.to_shapely_array(),
            combined.struct[2],
        ),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

intersects_xy(x, y)

Return True if geom and the Point (x, y) share any portion of space.

This is a special-case (and faster) variant of the intersects function which avoids having to create a Point object if you start from x/y coordinates.

See the docstring of intersects for more details about the predicate.

Parameters:

Name Type Description Default
x float | None

The X coordinate to check

required
y float | None

The Y coordinate to check

required
One geometry different x/y coordinate input

To compute between the values in the series and a single x,y pair provide the x and y parameters.

To compute between two geometries in a column and columns of x/y coordinates of the frame wrap all columns into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def intersects_xy(self, x: float | None, y: float | None) -> pl.Expr:
    """Return True if geom and the Point (x, y) share any portion of space.

    This is a special-case (and faster) variant of the intersects function which
    avoids having to create a Point object if you start from x/y coordinates.

    See the docstring of intersects for more details about the predicate.

    Parameters
    ----------
    x
        The X coordinate to check

    y
        The Y coordinate to check

    One geometry different x/y coordinate input
    -------------------------------------------
    **To compute between the values in the series and a single x,y pair** provide
    the `x` and `y` parameters.

    **To compute between two geometries in a column and columns of x/y coordinates
    of the frame** wrap all columns into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if x is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.intersects_xy(x, y),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )
    # expect struct with a geometry and x/y fields.
    return self._expr.map_batches(
        lambda combined: shapely.intersects_xy(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1],
            combined.struct[2],
        ),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

equals_exact(other=None, tolerance=None)

Return True if the geometries are structurally equivalent within a given tolerance.

This method uses exact coordinate equality, which requires coordinates to be equal (within specified tolerance) and in the same order for all components (vertices, rings, or parts) of a geometry. This is in contrast with the equals function which uses spatial (topological) equality and does not require all components to be in the same order. Because of this, it is possible for equals to be True while equals_exact is False.

The order of the coordinates can be normalized (by setting the normalize keyword to True) so that this function will return True when geometries are structurally equivalent but differ only in the ordering of vertices. However, this function will still return False if the order of interior rings within a Polygon or the order of geometries within a multi geometry are different.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
tolerance float | None

The tolerance to use in the comparison.

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def equals_exact(
    self,
    other: shapely.Geometry | None = None,
    tolerance: float | None = None,
) -> pl.Expr:
    """Return True if the geometries are structurally equivalent within a given tolerance.

    This method uses exact coordinate equality, which requires coordinates to be
    equal (within specified tolerance) and in the same order for all components
    (vertices, rings, or parts) of a geometry. This is in contrast with the equals
    function which uses spatial (topological) equality and does not require all
    components to be in the same order. Because of this, it is possible for equals
    to be True while equals_exact is False.

    The order of the coordinates can be normalized (by setting the normalize keyword
    to True) so that this function will return True when geometries are structurally
    equivalent but differ only in the ordering of vertices. However, this function
    will still return False if the order of interior rings within a Polygon or the
    order of geometries within a multi geometry are different.

    Parameters
    ----------
    other
        A shapely geometry object

    tolerance
        The tolerance to use in the comparison.

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.equals_exact(other, tolerance),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )
    # expect struct with two geometry and tolerance fields.
    return self._expr.map_batches(
        lambda combined: shapely.equals_exact(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1].spatial.to_shapely_array(),
            combined.struct[2],
        ),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

relate_pattern(other=None, pattern=None)

Return True if the DE-9IM relationship code satisfies the pattern.

This function compares the DE-9IM code string for two geometries against a specified pattern. If the string matches the pattern then True is returned, otherwise False. The pattern specified can be an exact match (0, 1 or 2), a boolean match (uppercase T or F), or a wildcard (). For example, the pattern for the within predicate is 'TFF*'.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
pattern str | None

The pattern to match the DE-9IM relationship code against.

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def relate_pattern(
    self,
    other: shapely.Geometry | None = None,
    pattern: str | None = None,
) -> pl.Expr:
    """Return True if the DE-9IM relationship code satisfies the pattern.

    This function compares the DE-9IM code string for two geometries against a
    specified pattern. If the string matches the pattern then True is returned,
    otherwise False. The pattern specified can be an exact match (0, 1 or 2), a
    boolean match (uppercase T or F), or a wildcard (*). For example, the pattern
    for the within predicate is 'T*F**F***'.

    Parameters
    ----------
    other
        A shapely geometry object

    pattern
        The pattern to match the DE-9IM relationship code against.

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.relate_pattern(other, pattern),
            return_dtype=pl.Boolean,
            is_elementwise=True,
        )
    # expect struct with two geometry and pattern fields.
    return self._expr.map_batches(
        lambda combined: shapely.relate_pattern(
            combined.struct[0].spatial.to_shapely_array(),
            combined.struct[1].spatial.to_shapely_array(),
            combined.struct[2],
        ),
        return_dtype=pl.Boolean,
        is_elementwise=True,
    )

SetOperations

Expressions derived from shapely's Set Operations.

Source code in src\spatial_polars\spatialexpr.py
class SetOperations:
    """Expressions derived from shapely's [Set Operations](https://shapely.readthedocs.io/en/stable/set_operations.html)."""

    def __init__(self, expr: pl.Expr) -> None:
        """For making polars expressions of Set Operations."""
        self._expr = expr

    def difference(
        self,
        other: shapely.Geometry | None = None,
        grid_size: float | None = None,
    ) -> pl.Expr:
        """Return the part of geometry A that does not intersect with geometry B.

        If grid_size is nonzero, input coordinates will be snapped to a precision grid
        of that size and resulting coordinates will be snapped to that same grid. If 0,
        this operation will use double precision coordinates. If None, the highest
        precision of the inputs will be used, which may be previously set using
        set_precision. Note: returned geometry does not have precision set unless
        specified previously by set_precision.

        Parameters
        ----------
        other
            A shapely geometry object

        grid_size
            Precision grid size; will use the highest precision of the inputs by default.

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.difference(other, grid_size),
                return_dtype=spatial_series_dtype,
                is_elementwise=True,
            )

        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: combined.struct[0].spatial.difference(
                combined.struct[1].spatial.to_shapely_array(),
                grid_size,
            ),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def intersection(
        self,
        other: shapely.Geometry | None = None,
        grid_size: float | None = None,
    ) -> pl.Expr:
        """Return the geometry that is shared between input geometries.

        If grid_size is nonzero, input coordinates will be snapped to a precision grid
        of that size and resulting coordinates will be snapped to that same grid. If 0,
        this operation will use double precision coordinates. If None, the highest
        precision of the inputs will be used, which may be previously set using
        set_precision. Note: returned geometry does not have precision set unless
        specified previously by set_precision.

        Parameters
        ----------
        other
            A shapely geometry object

        grid_size
            Precision grid size; will use the highest precision of the inputs by default.

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.intersection(other, grid_size),
                return_dtype=spatial_series_dtype,
                is_elementwise=True,
            )

        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: combined.struct[0].spatial.intersection(
                combined.struct[1].spatial.to_shapely_array(),
                grid_size,
            ),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def intersection_all(self, grid_size: float | None = None) -> pl.Expr:
        """Return the intersection of multiple geometries.

        This function ignores None values when other Geometry elements are present. If
        all elements of the given axis are None, an empty GeometryCollection is returned
        .

        If grid_size is nonzero, input coordinates will be snapped to a precision grid
        of that size and resulting coordinates will be snapped to that same grid. If 0,
        this operation will use double precision coordinates. If None, the highest
        precision of the inputs will be used, which may be previously set using
        set_precision. Note: returned geometry does not have precision set unless
        specified previously by set_precision.

        Parameters
        ----------
        grid_size
            Precision grid size; will use the highest precision of the inputs by default
            .

        """
        return self._expr.map_batches(
            lambda s: s.spatial.intersection_all(grid_size),
            return_dtype=spatial_series_dtype,
            returns_scalar=True,
        )

    def symmetric_difference(
        self,
        other: shapely.Geometry | None = None,
        grid_size: float | None = None,
    ) -> pl.Expr:
        """Return the geometry with the portions of input geometries that do not intersect.

        If grid_size is nonzero, input coordinates will be snapped to a precision grid
        of that size and resulting coordinates will be snapped to that same grid. If 0,
        this operation will use double precision coordinates. If None, the highest
        precision of the inputs will be used, which may be previously set using
        set_precision. Note: returned geometry does not have precision set unless
        specified previously by set_precision.

        Parameters
        ----------
        other
            A shapely geometry object

        grid_size
            Precision grid size; will use the highest precision of the inputs by default.

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.symmetric_difference(other, grid_size),
                return_dtype=spatial_series_dtype,
                is_elementwise=True,
            )
        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: combined.struct[0].spatial.symmetric_difference(
                combined.struct[1].spatial.to_shapely_array(),
                grid_size,
            ),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def union(
        self,
        other: shapely.Geometry | None = None,
        grid_size: float | None = None,
    ) -> pl.Expr:
        """Merge geometries into one.

        If grid_size is nonzero, input coordinates will be snapped to a precision grid
        of that size and resulting coordinates will be snapped to that same grid. If 0,
        this operation will use double precision coordinates. If None, the highest
        precision of the inputs will be used, which may be previously set using
        set_precision. Note: returned geometry does not have precision set unless
        specified previously by set_precision.

        Parameters
        ----------
        other
            A shapely geometry object

        grid_size
            Precision grid size; will use the highest precision of the inputs by default.

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.union(other, grid_size),
                return_dtype=spatial_series_dtype,
                is_elementwise=True,
            )
        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: combined.struct[0].spatial.union(
                combined.struct[1].spatial.to_shapely_array(),
                grid_size,
            ),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def union_all(self, grid_size: float | None = None) -> pl.Expr:
        """Return the union of multiple geometries.

        This function ignores None values when other Geometry elements are present. If
        all elements of the given axis are None an empty GeometryCollection is returned.

        If grid_size is nonzero, input coordinates will be snapped to a precision grid
        of that size and resulting coordinates will be snapped to that same grid. If 0,
        this operation will use double precision coordinates. If None, the highest
        precision of the inputs will be used, which may be previously set using
        set_precision. Note: returned geometry does not have precision set unless
        specified previously by set_precision.

        Parameters
        ----------
        grid_size
            Precision grid size; will use the highest precision of the inputs by default
            .

        """
        return self._expr.map_batches(
            lambda s: s.spatial.union_all(grid_size),
            return_dtype=spatial_series_dtype,
            returns_scalar=True,
        )

__init__(expr)

For making polars expressions of Set Operations.

Source code in src\spatial_polars\spatialexpr.py
def __init__(self, expr: pl.Expr) -> None:
    """For making polars expressions of Set Operations."""
    self._expr = expr

difference(other=None, grid_size=None)

Return the part of geometry A that does not intersect with geometry B.

If grid_size is nonzero, input coordinates will be snapped to a precision grid of that size and resulting coordinates will be snapped to that same grid. If 0, this operation will use double precision coordinates. If None, the highest precision of the inputs will be used, which may be previously set using set_precision. Note: returned geometry does not have precision set unless specified previously by set_precision.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
grid_size float | None

Precision grid size; will use the highest precision of the inputs by default.

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def difference(
    self,
    other: shapely.Geometry | None = None,
    grid_size: float | None = None,
) -> pl.Expr:
    """Return the part of geometry A that does not intersect with geometry B.

    If grid_size is nonzero, input coordinates will be snapped to a precision grid
    of that size and resulting coordinates will be snapped to that same grid. If 0,
    this operation will use double precision coordinates. If None, the highest
    precision of the inputs will be used, which may be previously set using
    set_precision. Note: returned geometry does not have precision set unless
    specified previously by set_precision.

    Parameters
    ----------
    other
        A shapely geometry object

    grid_size
        Precision grid size; will use the highest precision of the inputs by default.

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.difference(other, grid_size),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: combined.struct[0].spatial.difference(
            combined.struct[1].spatial.to_shapely_array(),
            grid_size,
        ),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

intersection(other=None, grid_size=None)

Return the geometry that is shared between input geometries.

If grid_size is nonzero, input coordinates will be snapped to a precision grid of that size and resulting coordinates will be snapped to that same grid. If 0, this operation will use double precision coordinates. If None, the highest precision of the inputs will be used, which may be previously set using set_precision. Note: returned geometry does not have precision set unless specified previously by set_precision.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
grid_size float | None

Precision grid size; will use the highest precision of the inputs by default.

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def intersection(
    self,
    other: shapely.Geometry | None = None,
    grid_size: float | None = None,
) -> pl.Expr:
    """Return the geometry that is shared between input geometries.

    If grid_size is nonzero, input coordinates will be snapped to a precision grid
    of that size and resulting coordinates will be snapped to that same grid. If 0,
    this operation will use double precision coordinates. If None, the highest
    precision of the inputs will be used, which may be previously set using
    set_precision. Note: returned geometry does not have precision set unless
    specified previously by set_precision.

    Parameters
    ----------
    other
        A shapely geometry object

    grid_size
        Precision grid size; will use the highest precision of the inputs by default.

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.intersection(other, grid_size),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: combined.struct[0].spatial.intersection(
            combined.struct[1].spatial.to_shapely_array(),
            grid_size,
        ),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

intersection_all(grid_size=None)

Return the intersection of multiple geometries.

This function ignores None values when other Geometry elements are present. If all elements of the given axis are None, an empty GeometryCollection is returned .

If grid_size is nonzero, input coordinates will be snapped to a precision grid of that size and resulting coordinates will be snapped to that same grid. If 0, this operation will use double precision coordinates. If None, the highest precision of the inputs will be used, which may be previously set using set_precision. Note: returned geometry does not have precision set unless specified previously by set_precision.

Parameters:

Name Type Description Default
grid_size float | None

Precision grid size; will use the highest precision of the inputs by default .

None
Source code in src\spatial_polars\spatialexpr.py
def intersection_all(self, grid_size: float | None = None) -> pl.Expr:
    """Return the intersection of multiple geometries.

    This function ignores None values when other Geometry elements are present. If
    all elements of the given axis are None, an empty GeometryCollection is returned
    .

    If grid_size is nonzero, input coordinates will be snapped to a precision grid
    of that size and resulting coordinates will be snapped to that same grid. If 0,
    this operation will use double precision coordinates. If None, the highest
    precision of the inputs will be used, which may be previously set using
    set_precision. Note: returned geometry does not have precision set unless
    specified previously by set_precision.

    Parameters
    ----------
    grid_size
        Precision grid size; will use the highest precision of the inputs by default
        .

    """
    return self._expr.map_batches(
        lambda s: s.spatial.intersection_all(grid_size),
        return_dtype=spatial_series_dtype,
        returns_scalar=True,
    )

symmetric_difference(other=None, grid_size=None)

Return the geometry with the portions of input geometries that do not intersect.

If grid_size is nonzero, input coordinates will be snapped to a precision grid of that size and resulting coordinates will be snapped to that same grid. If 0, this operation will use double precision coordinates. If None, the highest precision of the inputs will be used, which may be previously set using set_precision. Note: returned geometry does not have precision set unless specified previously by set_precision.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
grid_size float | None

Precision grid size; will use the highest precision of the inputs by default.

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def symmetric_difference(
    self,
    other: shapely.Geometry | None = None,
    grid_size: float | None = None,
) -> pl.Expr:
    """Return the geometry with the portions of input geometries that do not intersect.

    If grid_size is nonzero, input coordinates will be snapped to a precision grid
    of that size and resulting coordinates will be snapped to that same grid. If 0,
    this operation will use double precision coordinates. If None, the highest
    precision of the inputs will be used, which may be previously set using
    set_precision. Note: returned geometry does not have precision set unless
    specified previously by set_precision.

    Parameters
    ----------
    other
        A shapely geometry object

    grid_size
        Precision grid size; will use the highest precision of the inputs by default.

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.symmetric_difference(other, grid_size),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )
    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: combined.struct[0].spatial.symmetric_difference(
            combined.struct[1].spatial.to_shapely_array(),
            grid_size,
        ),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

union(other=None, grid_size=None)

Merge geometries into one.

If grid_size is nonzero, input coordinates will be snapped to a precision grid of that size and resulting coordinates will be snapped to that same grid. If 0, this operation will use double precision coordinates. If None, the highest precision of the inputs will be used, which may be previously set using set_precision. Note: returned geometry does not have precision set unless specified previously by set_precision.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
grid_size float | None

Precision grid size; will use the highest precision of the inputs by default.

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def union(
    self,
    other: shapely.Geometry | None = None,
    grid_size: float | None = None,
) -> pl.Expr:
    """Merge geometries into one.

    If grid_size is nonzero, input coordinates will be snapped to a precision grid
    of that size and resulting coordinates will be snapped to that same grid. If 0,
    this operation will use double precision coordinates. If None, the highest
    precision of the inputs will be used, which may be previously set using
    set_precision. Note: returned geometry does not have precision set unless
    specified previously by set_precision.

    Parameters
    ----------
    other
        A shapely geometry object

    grid_size
        Precision grid size; will use the highest precision of the inputs by default.

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.union(other, grid_size),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )
    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: combined.struct[0].spatial.union(
            combined.struct[1].spatial.to_shapely_array(),
            grid_size,
        ),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

union_all(grid_size=None)

Return the union of multiple geometries.

This function ignores None values when other Geometry elements are present. If all elements of the given axis are None an empty GeometryCollection is returned.

If grid_size is nonzero, input coordinates will be snapped to a precision grid of that size and resulting coordinates will be snapped to that same grid. If 0, this operation will use double precision coordinates. If None, the highest precision of the inputs will be used, which may be previously set using set_precision. Note: returned geometry does not have precision set unless specified previously by set_precision.

Parameters:

Name Type Description Default
grid_size float | None

Precision grid size; will use the highest precision of the inputs by default .

None
Source code in src\spatial_polars\spatialexpr.py
def union_all(self, grid_size: float | None = None) -> pl.Expr:
    """Return the union of multiple geometries.

    This function ignores None values when other Geometry elements are present. If
    all elements of the given axis are None an empty GeometryCollection is returned.

    If grid_size is nonzero, input coordinates will be snapped to a precision grid
    of that size and resulting coordinates will be snapped to that same grid. If 0,
    this operation will use double precision coordinates. If None, the highest
    precision of the inputs will be used, which may be previously set using
    set_precision. Note: returned geometry does not have precision set unless
    specified previously by set_precision.

    Parameters
    ----------
    grid_size
        Precision grid size; will use the highest precision of the inputs by default
        .

    """
    return self._expr.map_batches(
        lambda s: s.spatial.union_all(grid_size),
        return_dtype=spatial_series_dtype,
        returns_scalar=True,
    )

ConstructiveOperations

Expressions derived from shapely's Constructive Operations.

Source code in src\spatial_polars\spatialexpr.py
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
class ConstructiveOperations:
    """Expressions derived from shapely's [Constructive Operations](https://shapely.readthedocs.io/en/stable/constructive.html)."""

    def __init__(self, expr: pl.Expr) -> None:
        """For making polars expressions of Constructive Operations."""
        self._expr = expr

    def boundary(self) -> pl.Expr:
        """Return the topological boundary of a geometry.

        This function will return None for geometrycollections.
        """
        return self._expr.map_batches(
            lambda s: s.spatial.boundary(),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def buffer(
        self,
        distance: float,
        quad_segs: int = 8,
        cap_style: Literal["round", "square", "flat"] = "round",
        join_style: Literal["round", "bevel", "mitre"] = "round",
        mitre_limit: float = 5.0,
        *,
        single_sided: bool = False,
    ) -> pl.Expr:
        """Compute the buffer of a geometry for positive and negative buffer distance.

        The buffer of a geometry is defined as the Minkowski sum (or difference, for
        negative distance) of the geometry with a circle with radius equal to the
        absolute value of the buffer distance.

        The buffer operation always returns a polygonal result. The negative or
        zero-distance buffer of lines and points is always empty.

        Parameters
        ----------
        distance
            Specifies the circle radius in the Minkowski sum (or difference).

        quad_segs
            Specifies the number of linear segments in a quarter circle in the
            approximation of circular arcs.

        cap_style
            Specifies the shape of buffered line endings. BufferCapStyle.round (`round`)
            results in circular line endings (see quad_segs). Both BufferCapStyle.square
            (`square`) and BufferCapStyle.flat (`flat`) result in rectangular line
            endings, only BufferCapStyle.flat (`flat`) will end at the original vertex,
            while BufferCapStyle.square (`square`) involves adding the buffer width.

        join_style
            Specifies the shape of buffered line midpoints. BufferJoinStyle.round
            (`round`) results in rounded shapes. BufferJoinStyle.bevel (`bevel`) results
            in a beveled edge that touches the original vertex. BufferJoinStyle.mitre
            (`mitre`) results in a single vertex that is beveled depending on the
            mitre_limit parameter.

        mitre_limit
            Crops of `mitre`-style joins if the point is displaced from the buffered
            vertex by more than this limit.

        single_sided
            Only buffer at one side of the geometry.

        """
        return self._expr.map_batches(
            lambda s: s.spatial.buffer(
                distance,
                quad_segs=quad_segs,
                cap_style=cap_style,
                join_style=join_style,
                mitre_limit=mitre_limit,
                single_sided=single_sided,
            ),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def offset_curve(
        self,
        distance: float,
        quad_segs: int = 8,
        join_style: Literal["round", "bevel", "mitre"] = "round",
        mitre_limit: float = 5.0,
    ) -> pl.Expr:
        """Return a (Multi)LineString at a distance from the object.

        For positive distance the offset will be at the left side of the input line. For
        a negative distance it will be at the right side. In general, this function
        tries to preserve the direction of the input.

        Note: the behaviour regarding orientation of the resulting line depends on the
        GEOS version. With GEOS < 3.11, the line retains the same direction for a left
        offset (positive distance) or has opposite direction for a right offset
        (negative distance), and this behaviour was documented as such in previous
        Shapely versions. Starting with GEOS 3.11, the function tries to preserve the
        orientation of the original line.

        Parameters
        ----------
        distance
            Specifies the circle radius in the Minkowski sum (or difference).

        quad_segs
            Specifies the number of linear segments in a quarter circle in the
            approximation of circular arcs.

        join_style
            Specifies the shape of buffered line midpoints. BufferJoinStyle.round
            (`round`) results in rounded shapes. BufferJoinStyle.bevel (`bevel`) results
            in a beveled edge that touches the original vertex. BufferJoinStyle.mitre
            (`mitre`) results in a single vertex that is beveled depending on the
            mitre_limit parameter.

        mitre_limit
            Crops of `mitre`-style joins if the point is displaced from the buffered
            vertex by more than this limit.

        """
        return self._expr.map_batches(
            lambda s: s.spatial.offset_curve(
                distance,
                quad_segs=quad_segs,
                join_style=join_style,
                mitre_limit=mitre_limit,
            ),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def centroid(self) -> pl.Expr:
        """Compute the geometric center (center-of-mass) of a geometry.

        For multipoints this is computed as the mean of the input coordinates. For
        multilinestrings the centroid is weighted by the length of each line segment.
        For multipolygons the centroid is weighted by the area of each polygon.
        """
        return self._expr.map_batches(
            lambda s: s.spatial.centroid(),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def clip_by_rect(
        self,
        xmin: float,
        ymin: float,
        xmax: float,
        ymax: float,
    ) -> pl.Expr:
        """Return the portion of a geometry within a rectangle.

        The geometry is clipped in a fast but possibly dirty way. The output is not
        guaranteed to be valid. No exceptions will be raised for topological errors.

        Note: empty geometries or geometries that do not overlap with the specified
        bounds will result in GEOMETRYCOLLECTION EMPTY.

        Parameters
        ----------
        xmin
            Minimum x value of the rectangle.

        ymin
            Minimum y value of the rectangle.

        xmax
            Maximum x value of the rectangle.

        ymax
            Maximum y value of the rectangle.

        """
        return self._expr.map_batches(
            lambda s: s.spatial.clip_by_rect(
                xmin=xmin,
                ymin=ymin,
                xmax=xmax,
                ymax=ymax,
            ),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def concave_hull(self, ratio: float = 0.0, *, allow_holes: bool = False) -> pl.Expr:
        """Compute a concave geometry that encloses an input geometry.

        Parameters
        ----------
        ratio
            Number in the range [0, 1]. Higher numbers will include fewer vertices in
            the hull.

        allow_holes
            If set to True, the concave hull may have holes.

        """
        return self._expr.map_batches(
            lambda s: s.spatial.concave_hull(ratio=ratio, allow_holes=allow_holes),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def convex_hull(self) -> pl.Expr:
        """Compute the minimum convex geometry that encloses an input geometry."""
        return self._expr.map_batches(
            lambda s: s.spatial.convex_hull(),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def delaunay_triangles(
        self,
        tolerance: float = 0.0,
        *,
        only_edges: bool = False,
    ) -> pl.Expr:
        """Compute a Delaunay triangulation around the vertices of an input geometry.

        The output is a geometrycollection containing polygons (default) or linestrings
        (see only_edges). Returns an empty geometry for input geometries that contain
        less than 3 vertices.

        Parameters
        ----------
        tolerance
            Snap input vertices together if their distance is less than this value.

        only_edges
            If set to True, the triangulation will return a collection of linestrings
            instead of polygons.

        """
        return self._expr.map_batches(
            lambda s: s.spatial.delaunay_triangles(
                tolerance=tolerance,
                only_edges=only_edges,
            ),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def segmentize(self, max_segment_length: float) -> pl.Expr:
        """Add vertices to line segments based on maximum segment length.

        Additional vertices will be added to every line segment in an input geometry so
        that segments are no longer than the provided maximum segment length. New
        vertices will evenly subdivide each segment.

        Only linear components of input geometries are densified; other geometries are
        returned unmodified.

        Parameters
        ----------
        max_segment_length
            Additional vertices will be added so that all line segments are no longer
            than this value. Must be greater than 0.

        """
        return self._expr.map_batches(
            lambda s: s.spatial.segmentize(max_segment_length=max_segment_length),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def envelope(self) -> pl.Expr:
        """Compute the minimum bounding box that encloses an input geometry."""
        return self._expr.map_batches(
            lambda s: s.spatial.envelope(),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def extract_unique_points(self) -> pl.Expr:
        """Return all distinct vertices of an input geometry as a multipoint.

        Note that only 2 dimensions of the vertices are considered when testing for
        equality.
        """
        return self._expr.map_batches(
            lambda s: s.spatial.extract_unique_points(),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def build_area(self) -> pl.Expr:
        """Create an areal geometry formed by the constituent linework of given geometry.

        Equivalent of the PostGIS ST_BuildArea() function.
        """  # NOQA:E501
        return self._expr.map_batches(
            lambda s: s.spatial.build_area(),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def make_valid(
        self,
        method: Literal["linework", "structure"],
        *,
        keep_collapsed: bool = True,
    ) -> pl.Expr:
        """Repair invalid geometries.

        Two methods are available:

        the 'linework' algorithm tries to preserve every edge and vertex in the input.
        It combines all rings into a set of noded lines and then extracts valid polygons
        from that linework. An alternating even-odd strategy is used to assign areas as
        interior or exterior. A disadvantage is that for some relatively simple invalid
        geometries this produces rather complex results.
        the 'structure' algorithm tries to reason from the structure of the input to
        find the 'correct' repair: exterior rings bound area, interior holes exclude
        area. It first makes all rings valid, then shells are merged and holes are
        subtracted from the shells to generate valid result. It assumes that holes and
        shells are correctly categorized in the input geometry.
        """
        return self._expr.map_batches(
            lambda s: s.spatial.make_valid(
                method=method,
                keep_collapsed=keep_collapsed,
            ),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def normalize(self) -> pl.Expr:
        """Convert Geometry to strict normal form (or canonical form).

        In strict canonical form <canonical-form>, the coordinates, rings of a polygon
        and parts of multi geometries are ordered consistently. Typically useful for
        testing purposes (for example in combination with equals_exact).
        """
        return self._expr.map_batches(
            lambda s: s.spatial.normalize(),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def node(self) -> pl.Expr:
        """Return the fully noded version of the linear input as MultiLineString.

        Given a linear input geometry, this function returns a new MultiLineString in
        which no lines cross each other but only touch at and points. To obtain this,
        all intersections between segments are computed and added to the segments, and
        duplicate segments are removed.

        Non-linear input (points) will result in an empty MultiLineString.

        This function can for example be used to create a fully-noded linework suitable
        to passed as input to polygonize.
        """
        return self._expr.map_batches(
            lambda s: s.spatial.node(),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def point_on_surface(self) -> pl.Expr:
        """Return a point that intersects an input geometry."""
        return self._expr.map_batches(
            lambda s: s.spatial.point_on_surface(),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def polygonize(self) -> pl.Expr:
        """Create polygons formed from the linework of a set of Geometries.

        Polygonizes an array of Geometries that contain linework which represents the
        edges of a planar graph. Any type of Geometry may be provided as input; only the
        constituent lines and rings will be used to create the output polygons.

        Lines or rings that when combined do not completely close a polygon will result
        in an empty GeometryCollection. Duplicate segments are ignored.

        This function returns the polygons within a GeometryCollection. Individual
        Polygons can be obtained using get_geometry to get a single polygon or get_parts
        to get an array of polygons. MultiPolygons can be constructed from the output
        using shapely.multipolygons(shapely.get_parts(shapely.polygonize(geometries))).
        """
        return self._expr.map_batches(
            lambda s: s.spatial.polygonize(),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def remove_repeated_points(self, tolerance: float = 0.0) -> pl.Expr:
        """Return a copy of a Geometry with repeated points removed.

        From the start of the coordinate sequence, each next point within the tolerance
        is removed.

        Removing repeated points with a non-zero tolerance may result in an invalid
        geometry being returned.

        Parameters
        ----------
        tolerance
            Use 0.0 to remove only exactly repeated points.

        """
        return self._expr.map_batches(
            lambda s: s.spatial.remove_repeated_points(tolerance=tolerance),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def reverse(self) -> pl.Expr:
        """Return a copy of a Geometry with the order of coordinates reversed.

        If a Geometry is a polygon with interior rings, the interior rings are also
        reversed.

        Points are unchanged. None is returned where Geometry is None.
        """
        return self._expr.map_batches(
            lambda s: s.spatial.reverse(),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def simplify(
        self,
        tolerance: float = 0.0,
        *,
        preserve_topology: bool = True,
    ) -> pl.Expr:
        """Return a simplified version of an input geometry.

        The Douglas-Peucker algorithm is used to simplify the geometry.

        Parameters
        ----------
        tolerance
            The maximum allowed geometry displacement. The higher this value, the
            smaller the number of vertices in the resulting geometry.

        preserve_topology
            By default (True), the operation will avoid creating invalid geometries
            (checking for collapses, ring-intersections, etc), but this is
            computationally more expensive.

        """
        return self._expr.map_batches(
            lambda s: s.spatial.simplify(
                tolerance=tolerance,
                preserve_topology=preserve_topology,
            ),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def snap(
        self,
        reference: shapely.Geometry | None = None,
        tolerance: float | None = None,
    ) -> pl.Expr:
        """Snap the vertices and segments of the geometry to vertices of the reference.

        Vertices and segments of the input geometry are snapped to vertices of the
        reference geometry, returning a new geometry; the input geometries are not
        modified. The result geometry is the input geometry with the vertices and
        segments snapped. If no snapping occurs then the input geometry is returned
        unchanged. The tolerance is used to control where snapping is performed.

        Where possible, this operation tries to avoid creating invalid geometries;
        however, it does not guarantee that output geometries will be valid. It is the
        responsibility of the caller to check for and handle invalid geometries.

        Because too much snapping can result in invalid geometries being created,
        heuristics are used to determine the number and location of snapped vertices
        that are likely safe to snap. These heuristics may omit some potential snaps
        that are otherwise within the tolerance.

        Parameters
        ----------
        reference
            Geometry or geometries to snap to.

        tolerance
            The maximum distance between the input and reference geometries for snapping
            to occur. A value of 0 will snap only identical points.

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `reference` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if reference is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.difference(reference, tolerance),
                return_dtype=spatial_series_dtype,
                is_elementwise=True,
            )
        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: combined.struct[0].spatial.difference(
                combined.struct[1].spatial.to_shapely_array(),
                tolerance,
            ),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def oriented_envelope(self) -> pl.Expr:
        """Compute the oriented envelope (minimum rotated rectangle) of the input geometry.

        The oriented envelope encloses an input geometry, such that the resulting
        rectangle has minimum area.

        Unlike envelope this rectangle is not constrained to be parallel to the
        coordinate axes. If the convex hull of the object is a degenerate (line or
        point) this degenerate is returned.

        The starting point of the rectangle is not fixed. You can use ~shapely.normalize
        to reorganize the rectangle to strict canonical form <canonical-form> so the
        starting point is always the lower left point.

        minimum_rotated_rectangle is an alias for oriented_envelope.
        """  # NOQA:E501
        return self._expr.map_batches(
            lambda s: s.spatial.oriented_envelope(),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def minimum_rotated_rectangle(self) -> pl.Expr:
        """Compute the oriented envelope (minimum rotated rectangle) of the input geometry.

        The oriented envelope encloses an input geometry, such that the resulting
        rectangle has minimum area.

        Unlike envelope this rectangle is not constrained to be parallel to the
        coordinate axes. If the convex hull of the object is a degenerate (line or
        point) this degenerate is returned.

        The starting point of the rectangle is not fixed. You can use ~shapely.normalize
        to reorganize the rectangle to strict canonical form <canonical-form> so the
        starting point is always the lower left point.

        minimum_rotated_rectangle is an alias for oriented_envelope.
        """  # NOQA:E501
        return self._expr.map_batches(
            lambda s: s.spatial.minimum_rotated_rectangle(),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def minimum_bounding_circle(self) -> pl.Expr:
        """Compute the minimum bounding circle that encloses an input geometry."""
        return self._expr.map_batches(
            lambda s: s.spatial.minimum_bounding_circle(),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

__init__(expr)

For making polars expressions of Constructive Operations.

Source code in src\spatial_polars\spatialexpr.py
def __init__(self, expr: pl.Expr) -> None:
    """For making polars expressions of Constructive Operations."""
    self._expr = expr

boundary()

Return the topological boundary of a geometry.

This function will return None for geometrycollections.

Source code in src\spatial_polars\spatialexpr.py
def boundary(self) -> pl.Expr:
    """Return the topological boundary of a geometry.

    This function will return None for geometrycollections.
    """
    return self._expr.map_batches(
        lambda s: s.spatial.boundary(),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

buffer(distance, quad_segs=8, cap_style='round', join_style='round', mitre_limit=5.0, *, single_sided=False)

Compute the buffer of a geometry for positive and negative buffer distance.

The buffer of a geometry is defined as the Minkowski sum (or difference, for negative distance) of the geometry with a circle with radius equal to the absolute value of the buffer distance.

The buffer operation always returns a polygonal result. The negative or zero-distance buffer of lines and points is always empty.

Parameters:

Name Type Description Default
distance float

Specifies the circle radius in the Minkowski sum (or difference).

required
quad_segs int

Specifies the number of linear segments in a quarter circle in the approximation of circular arcs.

8
cap_style Literal['round', 'square', 'flat']

Specifies the shape of buffered line endings. BufferCapStyle.round (round) results in circular line endings (see quad_segs). Both BufferCapStyle.square (square) and BufferCapStyle.flat (flat) result in rectangular line endings, only BufferCapStyle.flat (flat) will end at the original vertex, while BufferCapStyle.square (square) involves adding the buffer width.

'round'
join_style Literal['round', 'bevel', 'mitre']

Specifies the shape of buffered line midpoints. BufferJoinStyle.round (round) results in rounded shapes. BufferJoinStyle.bevel (bevel) results in a beveled edge that touches the original vertex. BufferJoinStyle.mitre (mitre) results in a single vertex that is beveled depending on the mitre_limit parameter.

'round'
mitre_limit float

Crops of mitre-style joins if the point is displaced from the buffered vertex by more than this limit.

5.0
single_sided bool

Only buffer at one side of the geometry.

False
Source code in src\spatial_polars\spatialexpr.py
def buffer(
    self,
    distance: float,
    quad_segs: int = 8,
    cap_style: Literal["round", "square", "flat"] = "round",
    join_style: Literal["round", "bevel", "mitre"] = "round",
    mitre_limit: float = 5.0,
    *,
    single_sided: bool = False,
) -> pl.Expr:
    """Compute the buffer of a geometry for positive and negative buffer distance.

    The buffer of a geometry is defined as the Minkowski sum (or difference, for
    negative distance) of the geometry with a circle with radius equal to the
    absolute value of the buffer distance.

    The buffer operation always returns a polygonal result. The negative or
    zero-distance buffer of lines and points is always empty.

    Parameters
    ----------
    distance
        Specifies the circle radius in the Minkowski sum (or difference).

    quad_segs
        Specifies the number of linear segments in a quarter circle in the
        approximation of circular arcs.

    cap_style
        Specifies the shape of buffered line endings. BufferCapStyle.round (`round`)
        results in circular line endings (see quad_segs). Both BufferCapStyle.square
        (`square`) and BufferCapStyle.flat (`flat`) result in rectangular line
        endings, only BufferCapStyle.flat (`flat`) will end at the original vertex,
        while BufferCapStyle.square (`square`) involves adding the buffer width.

    join_style
        Specifies the shape of buffered line midpoints. BufferJoinStyle.round
        (`round`) results in rounded shapes. BufferJoinStyle.bevel (`bevel`) results
        in a beveled edge that touches the original vertex. BufferJoinStyle.mitre
        (`mitre`) results in a single vertex that is beveled depending on the
        mitre_limit parameter.

    mitre_limit
        Crops of `mitre`-style joins if the point is displaced from the buffered
        vertex by more than this limit.

    single_sided
        Only buffer at one side of the geometry.

    """
    return self._expr.map_batches(
        lambda s: s.spatial.buffer(
            distance,
            quad_segs=quad_segs,
            cap_style=cap_style,
            join_style=join_style,
            mitre_limit=mitre_limit,
            single_sided=single_sided,
        ),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

offset_curve(distance, quad_segs=8, join_style='round', mitre_limit=5.0)

Return a (Multi)LineString at a distance from the object.

For positive distance the offset will be at the left side of the input line. For a negative distance it will be at the right side. In general, this function tries to preserve the direction of the input.

Note: the behaviour regarding orientation of the resulting line depends on the GEOS version. With GEOS < 3.11, the line retains the same direction for a left offset (positive distance) or has opposite direction for a right offset (negative distance), and this behaviour was documented as such in previous Shapely versions. Starting with GEOS 3.11, the function tries to preserve the orientation of the original line.

Parameters:

Name Type Description Default
distance float

Specifies the circle radius in the Minkowski sum (or difference).

required
quad_segs int

Specifies the number of linear segments in a quarter circle in the approximation of circular arcs.

8
join_style Literal['round', 'bevel', 'mitre']

Specifies the shape of buffered line midpoints. BufferJoinStyle.round (round) results in rounded shapes. BufferJoinStyle.bevel (bevel) results in a beveled edge that touches the original vertex. BufferJoinStyle.mitre (mitre) results in a single vertex that is beveled depending on the mitre_limit parameter.

'round'
mitre_limit float

Crops of mitre-style joins if the point is displaced from the buffered vertex by more than this limit.

5.0
Source code in src\spatial_polars\spatialexpr.py
def offset_curve(
    self,
    distance: float,
    quad_segs: int = 8,
    join_style: Literal["round", "bevel", "mitre"] = "round",
    mitre_limit: float = 5.0,
) -> pl.Expr:
    """Return a (Multi)LineString at a distance from the object.

    For positive distance the offset will be at the left side of the input line. For
    a negative distance it will be at the right side. In general, this function
    tries to preserve the direction of the input.

    Note: the behaviour regarding orientation of the resulting line depends on the
    GEOS version. With GEOS < 3.11, the line retains the same direction for a left
    offset (positive distance) or has opposite direction for a right offset
    (negative distance), and this behaviour was documented as such in previous
    Shapely versions. Starting with GEOS 3.11, the function tries to preserve the
    orientation of the original line.

    Parameters
    ----------
    distance
        Specifies the circle radius in the Minkowski sum (or difference).

    quad_segs
        Specifies the number of linear segments in a quarter circle in the
        approximation of circular arcs.

    join_style
        Specifies the shape of buffered line midpoints. BufferJoinStyle.round
        (`round`) results in rounded shapes. BufferJoinStyle.bevel (`bevel`) results
        in a beveled edge that touches the original vertex. BufferJoinStyle.mitre
        (`mitre`) results in a single vertex that is beveled depending on the
        mitre_limit parameter.

    mitre_limit
        Crops of `mitre`-style joins if the point is displaced from the buffered
        vertex by more than this limit.

    """
    return self._expr.map_batches(
        lambda s: s.spatial.offset_curve(
            distance,
            quad_segs=quad_segs,
            join_style=join_style,
            mitre_limit=mitre_limit,
        ),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

centroid()

Compute the geometric center (center-of-mass) of a geometry.

For multipoints this is computed as the mean of the input coordinates. For multilinestrings the centroid is weighted by the length of each line segment. For multipolygons the centroid is weighted by the area of each polygon.

Source code in src\spatial_polars\spatialexpr.py
def centroid(self) -> pl.Expr:
    """Compute the geometric center (center-of-mass) of a geometry.

    For multipoints this is computed as the mean of the input coordinates. For
    multilinestrings the centroid is weighted by the length of each line segment.
    For multipolygons the centroid is weighted by the area of each polygon.
    """
    return self._expr.map_batches(
        lambda s: s.spatial.centroid(),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

clip_by_rect(xmin, ymin, xmax, ymax)

Return the portion of a geometry within a rectangle.

The geometry is clipped in a fast but possibly dirty way. The output is not guaranteed to be valid. No exceptions will be raised for topological errors.

Note: empty geometries or geometries that do not overlap with the specified bounds will result in GEOMETRYCOLLECTION EMPTY.

Parameters:

Name Type Description Default
xmin float

Minimum x value of the rectangle.

required
ymin float

Minimum y value of the rectangle.

required
xmax float

Maximum x value of the rectangle.

required
ymax float

Maximum y value of the rectangle.

required
Source code in src\spatial_polars\spatialexpr.py
def clip_by_rect(
    self,
    xmin: float,
    ymin: float,
    xmax: float,
    ymax: float,
) -> pl.Expr:
    """Return the portion of a geometry within a rectangle.

    The geometry is clipped in a fast but possibly dirty way. The output is not
    guaranteed to be valid. No exceptions will be raised for topological errors.

    Note: empty geometries or geometries that do not overlap with the specified
    bounds will result in GEOMETRYCOLLECTION EMPTY.

    Parameters
    ----------
    xmin
        Minimum x value of the rectangle.

    ymin
        Minimum y value of the rectangle.

    xmax
        Maximum x value of the rectangle.

    ymax
        Maximum y value of the rectangle.

    """
    return self._expr.map_batches(
        lambda s: s.spatial.clip_by_rect(
            xmin=xmin,
            ymin=ymin,
            xmax=xmax,
            ymax=ymax,
        ),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

concave_hull(ratio=0.0, *, allow_holes=False)

Compute a concave geometry that encloses an input geometry.

Parameters:

Name Type Description Default
ratio float

Number in the range [0, 1]. Higher numbers will include fewer vertices in the hull.

0.0
allow_holes bool

If set to True, the concave hull may have holes.

False
Source code in src\spatial_polars\spatialexpr.py
def concave_hull(self, ratio: float = 0.0, *, allow_holes: bool = False) -> pl.Expr:
    """Compute a concave geometry that encloses an input geometry.

    Parameters
    ----------
    ratio
        Number in the range [0, 1]. Higher numbers will include fewer vertices in
        the hull.

    allow_holes
        If set to True, the concave hull may have holes.

    """
    return self._expr.map_batches(
        lambda s: s.spatial.concave_hull(ratio=ratio, allow_holes=allow_holes),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

convex_hull()

Compute the minimum convex geometry that encloses an input geometry.

Source code in src\spatial_polars\spatialexpr.py
def convex_hull(self) -> pl.Expr:
    """Compute the minimum convex geometry that encloses an input geometry."""
    return self._expr.map_batches(
        lambda s: s.spatial.convex_hull(),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

delaunay_triangles(tolerance=0.0, *, only_edges=False)

Compute a Delaunay triangulation around the vertices of an input geometry.

The output is a geometrycollection containing polygons (default) or linestrings (see only_edges). Returns an empty geometry for input geometries that contain less than 3 vertices.

Parameters:

Name Type Description Default
tolerance float

Snap input vertices together if their distance is less than this value.

0.0
only_edges bool

If set to True, the triangulation will return a collection of linestrings instead of polygons.

False
Source code in src\spatial_polars\spatialexpr.py
def delaunay_triangles(
    self,
    tolerance: float = 0.0,
    *,
    only_edges: bool = False,
) -> pl.Expr:
    """Compute a Delaunay triangulation around the vertices of an input geometry.

    The output is a geometrycollection containing polygons (default) or linestrings
    (see only_edges). Returns an empty geometry for input geometries that contain
    less than 3 vertices.

    Parameters
    ----------
    tolerance
        Snap input vertices together if their distance is less than this value.

    only_edges
        If set to True, the triangulation will return a collection of linestrings
        instead of polygons.

    """
    return self._expr.map_batches(
        lambda s: s.spatial.delaunay_triangles(
            tolerance=tolerance,
            only_edges=only_edges,
        ),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

segmentize(max_segment_length)

Add vertices to line segments based on maximum segment length.

Additional vertices will be added to every line segment in an input geometry so that segments are no longer than the provided maximum segment length. New vertices will evenly subdivide each segment.

Only linear components of input geometries are densified; other geometries are returned unmodified.

Parameters:

Name Type Description Default
max_segment_length float

Additional vertices will be added so that all line segments are no longer than this value. Must be greater than 0.

required
Source code in src\spatial_polars\spatialexpr.py
def segmentize(self, max_segment_length: float) -> pl.Expr:
    """Add vertices to line segments based on maximum segment length.

    Additional vertices will be added to every line segment in an input geometry so
    that segments are no longer than the provided maximum segment length. New
    vertices will evenly subdivide each segment.

    Only linear components of input geometries are densified; other geometries are
    returned unmodified.

    Parameters
    ----------
    max_segment_length
        Additional vertices will be added so that all line segments are no longer
        than this value. Must be greater than 0.

    """
    return self._expr.map_batches(
        lambda s: s.spatial.segmentize(max_segment_length=max_segment_length),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

envelope()

Compute the minimum bounding box that encloses an input geometry.

Source code in src\spatial_polars\spatialexpr.py
def envelope(self) -> pl.Expr:
    """Compute the minimum bounding box that encloses an input geometry."""
    return self._expr.map_batches(
        lambda s: s.spatial.envelope(),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

extract_unique_points()

Return all distinct vertices of an input geometry as a multipoint.

Note that only 2 dimensions of the vertices are considered when testing for equality.

Source code in src\spatial_polars\spatialexpr.py
def extract_unique_points(self) -> pl.Expr:
    """Return all distinct vertices of an input geometry as a multipoint.

    Note that only 2 dimensions of the vertices are considered when testing for
    equality.
    """
    return self._expr.map_batches(
        lambda s: s.spatial.extract_unique_points(),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

build_area()

Create an areal geometry formed by the constituent linework of given geometry.

Equivalent of the PostGIS ST_BuildArea() function.

Source code in src\spatial_polars\spatialexpr.py
def build_area(self) -> pl.Expr:
    """Create an areal geometry formed by the constituent linework of given geometry.

    Equivalent of the PostGIS ST_BuildArea() function.
    """  # NOQA:E501
    return self._expr.map_batches(
        lambda s: s.spatial.build_area(),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

make_valid(method, *, keep_collapsed=True)

Repair invalid geometries.

Two methods are available:

the 'linework' algorithm tries to preserve every edge and vertex in the input. It combines all rings into a set of noded lines and then extracts valid polygons from that linework. An alternating even-odd strategy is used to assign areas as interior or exterior. A disadvantage is that for some relatively simple invalid geometries this produces rather complex results. the 'structure' algorithm tries to reason from the structure of the input to find the 'correct' repair: exterior rings bound area, interior holes exclude area. It first makes all rings valid, then shells are merged and holes are subtracted from the shells to generate valid result. It assumes that holes and shells are correctly categorized in the input geometry.

Source code in src\spatial_polars\spatialexpr.py
def make_valid(
    self,
    method: Literal["linework", "structure"],
    *,
    keep_collapsed: bool = True,
) -> pl.Expr:
    """Repair invalid geometries.

    Two methods are available:

    the 'linework' algorithm tries to preserve every edge and vertex in the input.
    It combines all rings into a set of noded lines and then extracts valid polygons
    from that linework. An alternating even-odd strategy is used to assign areas as
    interior or exterior. A disadvantage is that for some relatively simple invalid
    geometries this produces rather complex results.
    the 'structure' algorithm tries to reason from the structure of the input to
    find the 'correct' repair: exterior rings bound area, interior holes exclude
    area. It first makes all rings valid, then shells are merged and holes are
    subtracted from the shells to generate valid result. It assumes that holes and
    shells are correctly categorized in the input geometry.
    """
    return self._expr.map_batches(
        lambda s: s.spatial.make_valid(
            method=method,
            keep_collapsed=keep_collapsed,
        ),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

normalize()

Convert Geometry to strict normal form (or canonical form).

In strict canonical form , the coordinates, rings of a polygon and parts of multi geometries are ordered consistently. Typically useful for testing purposes (for example in combination with equals_exact).

Source code in src\spatial_polars\spatialexpr.py
def normalize(self) -> pl.Expr:
    """Convert Geometry to strict normal form (or canonical form).

    In strict canonical form <canonical-form>, the coordinates, rings of a polygon
    and parts of multi geometries are ordered consistently. Typically useful for
    testing purposes (for example in combination with equals_exact).
    """
    return self._expr.map_batches(
        lambda s: s.spatial.normalize(),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

node()

Return the fully noded version of the linear input as MultiLineString.

Given a linear input geometry, this function returns a new MultiLineString in which no lines cross each other but only touch at and points. To obtain this, all intersections between segments are computed and added to the segments, and duplicate segments are removed.

Non-linear input (points) will result in an empty MultiLineString.

This function can for example be used to create a fully-noded linework suitable to passed as input to polygonize.

Source code in src\spatial_polars\spatialexpr.py
def node(self) -> pl.Expr:
    """Return the fully noded version of the linear input as MultiLineString.

    Given a linear input geometry, this function returns a new MultiLineString in
    which no lines cross each other but only touch at and points. To obtain this,
    all intersections between segments are computed and added to the segments, and
    duplicate segments are removed.

    Non-linear input (points) will result in an empty MultiLineString.

    This function can for example be used to create a fully-noded linework suitable
    to passed as input to polygonize.
    """
    return self._expr.map_batches(
        lambda s: s.spatial.node(),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

point_on_surface()

Return a point that intersects an input geometry.

Source code in src\spatial_polars\spatialexpr.py
def point_on_surface(self) -> pl.Expr:
    """Return a point that intersects an input geometry."""
    return self._expr.map_batches(
        lambda s: s.spatial.point_on_surface(),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

polygonize()

Create polygons formed from the linework of a set of Geometries.

Polygonizes an array of Geometries that contain linework which represents the edges of a planar graph. Any type of Geometry may be provided as input; only the constituent lines and rings will be used to create the output polygons.

Lines or rings that when combined do not completely close a polygon will result in an empty GeometryCollection. Duplicate segments are ignored.

This function returns the polygons within a GeometryCollection. Individual Polygons can be obtained using get_geometry to get a single polygon or get_parts to get an array of polygons. MultiPolygons can be constructed from the output using shapely.multipolygons(shapely.get_parts(shapely.polygonize(geometries))).

Source code in src\spatial_polars\spatialexpr.py
def polygonize(self) -> pl.Expr:
    """Create polygons formed from the linework of a set of Geometries.

    Polygonizes an array of Geometries that contain linework which represents the
    edges of a planar graph. Any type of Geometry may be provided as input; only the
    constituent lines and rings will be used to create the output polygons.

    Lines or rings that when combined do not completely close a polygon will result
    in an empty GeometryCollection. Duplicate segments are ignored.

    This function returns the polygons within a GeometryCollection. Individual
    Polygons can be obtained using get_geometry to get a single polygon or get_parts
    to get an array of polygons. MultiPolygons can be constructed from the output
    using shapely.multipolygons(shapely.get_parts(shapely.polygonize(geometries))).
    """
    return self._expr.map_batches(
        lambda s: s.spatial.polygonize(),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

remove_repeated_points(tolerance=0.0)

Return a copy of a Geometry with repeated points removed.

From the start of the coordinate sequence, each next point within the tolerance is removed.

Removing repeated points with a non-zero tolerance may result in an invalid geometry being returned.

Parameters:

Name Type Description Default
tolerance float

Use 0.0 to remove only exactly repeated points.

0.0
Source code in src\spatial_polars\spatialexpr.py
def remove_repeated_points(self, tolerance: float = 0.0) -> pl.Expr:
    """Return a copy of a Geometry with repeated points removed.

    From the start of the coordinate sequence, each next point within the tolerance
    is removed.

    Removing repeated points with a non-zero tolerance may result in an invalid
    geometry being returned.

    Parameters
    ----------
    tolerance
        Use 0.0 to remove only exactly repeated points.

    """
    return self._expr.map_batches(
        lambda s: s.spatial.remove_repeated_points(tolerance=tolerance),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

reverse()

Return a copy of a Geometry with the order of coordinates reversed.

If a Geometry is a polygon with interior rings, the interior rings are also reversed.

Points are unchanged. None is returned where Geometry is None.

Source code in src\spatial_polars\spatialexpr.py
def reverse(self) -> pl.Expr:
    """Return a copy of a Geometry with the order of coordinates reversed.

    If a Geometry is a polygon with interior rings, the interior rings are also
    reversed.

    Points are unchanged. None is returned where Geometry is None.
    """
    return self._expr.map_batches(
        lambda s: s.spatial.reverse(),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

simplify(tolerance=0.0, *, preserve_topology=True)

Return a simplified version of an input geometry.

The Douglas-Peucker algorithm is used to simplify the geometry.

Parameters:

Name Type Description Default
tolerance float

The maximum allowed geometry displacement. The higher this value, the smaller the number of vertices in the resulting geometry.

0.0
preserve_topology bool

By default (True), the operation will avoid creating invalid geometries (checking for collapses, ring-intersections, etc), but this is computationally more expensive.

True
Source code in src\spatial_polars\spatialexpr.py
def simplify(
    self,
    tolerance: float = 0.0,
    *,
    preserve_topology: bool = True,
) -> pl.Expr:
    """Return a simplified version of an input geometry.

    The Douglas-Peucker algorithm is used to simplify the geometry.

    Parameters
    ----------
    tolerance
        The maximum allowed geometry displacement. The higher this value, the
        smaller the number of vertices in the resulting geometry.

    preserve_topology
        By default (True), the operation will avoid creating invalid geometries
        (checking for collapses, ring-intersections, etc), but this is
        computationally more expensive.

    """
    return self._expr.map_batches(
        lambda s: s.spatial.simplify(
            tolerance=tolerance,
            preserve_topology=preserve_topology,
        ),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

snap(reference=None, tolerance=None)

Snap the vertices and segments of the geometry to vertices of the reference.

Vertices and segments of the input geometry are snapped to vertices of the reference geometry, returning a new geometry; the input geometries are not modified. The result geometry is the input geometry with the vertices and segments snapped. If no snapping occurs then the input geometry is returned unchanged. The tolerance is used to control where snapping is performed.

Where possible, this operation tries to avoid creating invalid geometries; however, it does not guarantee that output geometries will be valid. It is the responsibility of the caller to check for and handle invalid geometries.

Because too much snapping can result in invalid geometries being created, heuristics are used to determine the number and location of snapped vertices that are likely safe to snap. These heuristics may omit some potential snaps that are otherwise within the tolerance.

Parameters:

Name Type Description Default
reference Geometry | None

Geometry or geometries to snap to.

None
tolerance float | None

The maximum distance between the input and reference geometries for snapping to occur. A value of 0 will snap only identical points.

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the reference parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def snap(
    self,
    reference: shapely.Geometry | None = None,
    tolerance: float | None = None,
) -> pl.Expr:
    """Snap the vertices and segments of the geometry to vertices of the reference.

    Vertices and segments of the input geometry are snapped to vertices of the
    reference geometry, returning a new geometry; the input geometries are not
    modified. The result geometry is the input geometry with the vertices and
    segments snapped. If no snapping occurs then the input geometry is returned
    unchanged. The tolerance is used to control where snapping is performed.

    Where possible, this operation tries to avoid creating invalid geometries;
    however, it does not guarantee that output geometries will be valid. It is the
    responsibility of the caller to check for and handle invalid geometries.

    Because too much snapping can result in invalid geometries being created,
    heuristics are used to determine the number and location of snapped vertices
    that are likely safe to snap. These heuristics may omit some potential snaps
    that are otherwise within the tolerance.

    Parameters
    ----------
    reference
        Geometry or geometries to snap to.

    tolerance
        The maximum distance between the input and reference geometries for snapping
        to occur. A value of 0 will snap only identical points.

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `reference` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if reference is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.difference(reference, tolerance),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )
    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: combined.struct[0].spatial.difference(
            combined.struct[1].spatial.to_shapely_array(),
            tolerance,
        ),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

oriented_envelope()

Compute the oriented envelope (minimum rotated rectangle) of the input geometry.

The oriented envelope encloses an input geometry, such that the resulting rectangle has minimum area.

Unlike envelope this rectangle is not constrained to be parallel to the coordinate axes. If the convex hull of the object is a degenerate (line or point) this degenerate is returned.

The starting point of the rectangle is not fixed. You can use ~shapely.normalize to reorganize the rectangle to strict canonical form so the starting point is always the lower left point.

minimum_rotated_rectangle is an alias for oriented_envelope.

Source code in src\spatial_polars\spatialexpr.py
def oriented_envelope(self) -> pl.Expr:
    """Compute the oriented envelope (minimum rotated rectangle) of the input geometry.

    The oriented envelope encloses an input geometry, such that the resulting
    rectangle has minimum area.

    Unlike envelope this rectangle is not constrained to be parallel to the
    coordinate axes. If the convex hull of the object is a degenerate (line or
    point) this degenerate is returned.

    The starting point of the rectangle is not fixed. You can use ~shapely.normalize
    to reorganize the rectangle to strict canonical form <canonical-form> so the
    starting point is always the lower left point.

    minimum_rotated_rectangle is an alias for oriented_envelope.
    """  # NOQA:E501
    return self._expr.map_batches(
        lambda s: s.spatial.oriented_envelope(),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

minimum_rotated_rectangle()

Compute the oriented envelope (minimum rotated rectangle) of the input geometry.

The oriented envelope encloses an input geometry, such that the resulting rectangle has minimum area.

Unlike envelope this rectangle is not constrained to be parallel to the coordinate axes. If the convex hull of the object is a degenerate (line or point) this degenerate is returned.

The starting point of the rectangle is not fixed. You can use ~shapely.normalize to reorganize the rectangle to strict canonical form so the starting point is always the lower left point.

minimum_rotated_rectangle is an alias for oriented_envelope.

Source code in src\spatial_polars\spatialexpr.py
def minimum_rotated_rectangle(self) -> pl.Expr:
    """Compute the oriented envelope (minimum rotated rectangle) of the input geometry.

    The oriented envelope encloses an input geometry, such that the resulting
    rectangle has minimum area.

    Unlike envelope this rectangle is not constrained to be parallel to the
    coordinate axes. If the convex hull of the object is a degenerate (line or
    point) this degenerate is returned.

    The starting point of the rectangle is not fixed. You can use ~shapely.normalize
    to reorganize the rectangle to strict canonical form <canonical-form> so the
    starting point is always the lower left point.

    minimum_rotated_rectangle is an alias for oriented_envelope.
    """  # NOQA:E501
    return self._expr.map_batches(
        lambda s: s.spatial.minimum_rotated_rectangle(),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

minimum_bounding_circle()

Compute the minimum bounding circle that encloses an input geometry.

Source code in src\spatial_polars\spatialexpr.py
def minimum_bounding_circle(self) -> pl.Expr:
    """Compute the minimum bounding circle that encloses an input geometry."""
    return self._expr.map_batches(
        lambda s: s.spatial.minimum_bounding_circle(),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

LinestringOperations

Expressions derived from shapely's Linestring Operations.

Source code in src\spatial_polars\spatialexpr.py
class LinestringOperations:
    """Expressions derived from shapely's [Linestring Operations](https://shapely.readthedocs.io/en/stable/linear.html)."""

    def __init__(self, expr: pl.Expr) -> None:
        """For making polars expressions of Linestring Operations."""
        self._expr = expr

    def line_interpolate_point(
        self,
        distance: float | None = None,
        *,
        normalized: bool = False,
    ) -> pl.Expr:
        """Return a point interpolated at given distance on a line.

        Parameters
        ----------
        distance
            Negative values measure distance from the end of the line. Out-of-range
            values will be clipped to the line endings.

        normalized
            If True, the distance is a fraction of the total line length instead of the
            absolute distance.

        Note
        ----
        **To compute between the values in the series and a scalar distance** provide
        the distance to the `distance` parameter.

        **To compute between the geometries and a column in the frame for the
        distance** wrap the geometry and other column of distances into a struct before
        using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if distance is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.line_interpolate_point(
                    distance=distance,
                    normalized=normalized,
                ),
                return_dtype=spatial_series_dtype,
                is_elementwise=True,
            )
        # expect struct geometry and number.
        return self._expr.map_batches(
            lambda combined: combined.struct[0].spatial.line_interpolate_point(
                combined.struct[1],
            ),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def line_locate_point(
        self,
        other: shapely.Geometry | None = None,
        *,
        normalized: bool = False,
    ) -> pl.Expr:
        """Return the distance to the line origin of given point.

        If given point does not intersect with the line, the point will first be
        projected onto the line after which the distance is taken.

        Parameters
        ----------
        other
            Point or points to calculate the distance from.

        normalized
            If True, the distance is a fraction of the total line length instead of
            the absolute distance.

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.line_locate_point(other, normalized=normalized),
                return_dtype=spatial_series_dtype,
                is_elementwise=True,
            )
        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: combined.struct[0].spatial.line_locate_point(
                combined.struct[1].spatial.to_shapely_array(),
                normalized=normalized,
            ),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def line_merge(self, *, directed: bool = False) -> pl.Expr:
        """Return (Multi)LineStrings formed by combining the lines in a MultiLineString.

        Lines are joined together at their endpoints in case two lines are intersecting.
        Lines are not joined when 3 or more lines are intersecting at the endpoints.
        Line elements that cannot be joined are kept as is in the resulting
        MultiLineString.

        The direction of each merged LineString will be that of the majority of the
        LineStrings from which it was derived. Except if directed=True is specified,
        then the operation will not change the order of points within lines and so only
        lines which can be joined with no change in direction are merged.

        Parameters
        ----------
        directed
            Only combine lines if possible without changing point order. Requires GEOS
            >= 3.11.0

        """
        return self._expr.map_batches(
            lambda s: s.spatial.line_merge(directed=directed),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def shortest_line(self, other: shapely.Geometry | None = None) -> pl.Expr:
        """Return the shortest line between two geometries.

        The resulting line consists of two points, representing the nearest points
        between the geometry pair. The line always starts in the first geometry a and
        ends in the second geometry b. The endpoints of the line will not necessarily be
        existing vertices of the input geometries a and b, but can also be a point along
        a line segment.

        Parameters
        ----------
        other
            A shapely geometry object

        Two geometry input
        ------------------
        **To compute between the values in the series and a scalar geometry** provide
        the other geometry to the `other` parameter.

        **To compute between two geometries in different columns of the frame** wrap
        both geometries into a struct before using the expression.
        See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

        """  # NOQA:E501
        if other is not None:
            return self._expr.map_batches(
                lambda s: s.spatial.shortest_line(other),
                return_dtype=spatial_series_dtype,
                is_elementwise=True,
            )
        # expect struct with two geometries.
        return self._expr.map_batches(
            lambda combined: combined.struct[0].spatial.shortest_line(
                combined.struct[1].spatial.to_shapely_array(),
            ),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

__init__(expr)

For making polars expressions of Linestring Operations.

Source code in src\spatial_polars\spatialexpr.py
def __init__(self, expr: pl.Expr) -> None:
    """For making polars expressions of Linestring Operations."""
    self._expr = expr

line_interpolate_point(distance=None, *, normalized=False)

Return a point interpolated at given distance on a line.

Parameters:

Name Type Description Default
distance float | None

Negative values measure distance from the end of the line. Out-of-range values will be clipped to the line endings.

None
normalized bool

If True, the distance is a fraction of the total line length instead of the absolute distance.

False
Note

To compute between the values in the series and a scalar distance provide the distance to the distance parameter.

To compute between the geometries and a column in the frame for the distance wrap the geometry and other column of distances into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def line_interpolate_point(
    self,
    distance: float | None = None,
    *,
    normalized: bool = False,
) -> pl.Expr:
    """Return a point interpolated at given distance on a line.

    Parameters
    ----------
    distance
        Negative values measure distance from the end of the line. Out-of-range
        values will be clipped to the line endings.

    normalized
        If True, the distance is a fraction of the total line length instead of the
        absolute distance.

    Note
    ----
    **To compute between the values in the series and a scalar distance** provide
    the distance to the `distance` parameter.

    **To compute between the geometries and a column in the frame for the
    distance** wrap the geometry and other column of distances into a struct before
    using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if distance is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.line_interpolate_point(
                distance=distance,
                normalized=normalized,
            ),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )
    # expect struct geometry and number.
    return self._expr.map_batches(
        lambda combined: combined.struct[0].spatial.line_interpolate_point(
            combined.struct[1],
        ),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

line_locate_point(other=None, *, normalized=False)

Return the distance to the line origin of given point.

If given point does not intersect with the line, the point will first be projected onto the line after which the distance is taken.

Parameters:

Name Type Description Default
other Geometry | None

Point or points to calculate the distance from.

None
normalized bool

If True, the distance is a fraction of the total line length instead of the absolute distance.

False
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def line_locate_point(
    self,
    other: shapely.Geometry | None = None,
    *,
    normalized: bool = False,
) -> pl.Expr:
    """Return the distance to the line origin of given point.

    If given point does not intersect with the line, the point will first be
    projected onto the line after which the distance is taken.

    Parameters
    ----------
    other
        Point or points to calculate the distance from.

    normalized
        If True, the distance is a fraction of the total line length instead of
        the absolute distance.

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.line_locate_point(other, normalized=normalized),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )
    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: combined.struct[0].spatial.line_locate_point(
            combined.struct[1].spatial.to_shapely_array(),
            normalized=normalized,
        ),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

line_merge(*, directed=False)

Return (Multi)LineStrings formed by combining the lines in a MultiLineString.

Lines are joined together at their endpoints in case two lines are intersecting. Lines are not joined when 3 or more lines are intersecting at the endpoints. Line elements that cannot be joined are kept as is in the resulting MultiLineString.

The direction of each merged LineString will be that of the majority of the LineStrings from which it was derived. Except if directed=True is specified, then the operation will not change the order of points within lines and so only lines which can be joined with no change in direction are merged.

Parameters:

Name Type Description Default
directed bool

Only combine lines if possible without changing point order. Requires GEOS

= 3.11.0

False
Source code in src\spatial_polars\spatialexpr.py
def line_merge(self, *, directed: bool = False) -> pl.Expr:
    """Return (Multi)LineStrings formed by combining the lines in a MultiLineString.

    Lines are joined together at their endpoints in case two lines are intersecting.
    Lines are not joined when 3 or more lines are intersecting at the endpoints.
    Line elements that cannot be joined are kept as is in the resulting
    MultiLineString.

    The direction of each merged LineString will be that of the majority of the
    LineStrings from which it was derived. Except if directed=True is specified,
    then the operation will not change the order of points within lines and so only
    lines which can be joined with no change in direction are merged.

    Parameters
    ----------
    directed
        Only combine lines if possible without changing point order. Requires GEOS
        >= 3.11.0

    """
    return self._expr.map_batches(
        lambda s: s.spatial.line_merge(directed=directed),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

shortest_line(other=None)

Return the shortest line between two geometries.

The resulting line consists of two points, representing the nearest points between the geometry pair. The line always starts in the first geometry a and ends in the second geometry b. The endpoints of the line will not necessarily be existing vertices of the input geometries a and b, but can also be a point along a line segment.

Parameters:

Name Type Description Default
other Geometry | None

A shapely geometry object

None
Two geometry input

To compute between the values in the series and a scalar geometry provide the other geometry to the other parameter.

To compute between two geometries in different columns of the frame wrap both geometries into a struct before using the expression. See Spatial expressions which use more than geometry

Source code in src\spatial_polars\spatialexpr.py
def shortest_line(self, other: shapely.Geometry | None = None) -> pl.Expr:
    """Return the shortest line between two geometries.

    The resulting line consists of two points, representing the nearest points
    between the geometry pair. The line always starts in the first geometry a and
    ends in the second geometry b. The endpoints of the line will not necessarily be
    existing vertices of the input geometries a and b, but can also be a point along
    a line segment.

    Parameters
    ----------
    other
        A shapely geometry object

    Two geometry input
    ------------------
    **To compute between the values in the series and a scalar geometry** provide
    the other geometry to the `other` parameter.

    **To compute between two geometries in different columns of the frame** wrap
    both geometries into a struct before using the expression.
    See [Spatial expressions which use more than geometry](index.md#spatial-expressions-which-use-more-than-geometry)

    """  # NOQA:E501
    if other is not None:
        return self._expr.map_batches(
            lambda s: s.spatial.shortest_line(other),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )
    # expect struct with two geometries.
    return self._expr.map_batches(
        lambda combined: combined.struct[0].spatial.shortest_line(
            combined.struct[1].spatial.to_shapely_array(),
        ),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

SpatialExpr

Bases: GeometryProperties, Measurement, Predicates, SetOperations, ConstructiveOperations, LinestringOperations

Spatial Polars Spatial expressions.

Source code in src\spatial_polars\spatialexpr.py
@pl.api.register_expr_namespace("spatial")
class SpatialExpr(
    GeometryProperties,
    Measurement,
    Predicates,
    SetOperations,
    ConstructiveOperations,
    LinestringOperations,
):
    """Spatial Polars Spatial expressions."""

    def __init__(self, expr: pl.Expr) -> None:
        """For making polars expressions of geometric functions."""
        self._expr = expr

    def to_shapely_array(self) -> pl.Expr:
        """Create an array of shapely geometries."""
        return self._expr.map_batches(
            lambda s: s.spatial.to_shapely_array(),
            return_dtype=pl.Object,
            is_elementwise=True,
        )

    def reproject(self, crs_to: Any) -> pl.Expr:  #  NOQA:ANN401
        """Reproject data to a different CRS.

        Parameters
        ----------
        crs_to
            The coordinate reference system to reproject the data into.

        """
        # using is_elementwise=True causes issues,
        # assuming something with the LRU caching or something like that.
        return self._expr.map_batches(
            lambda s: s.spatial.reproject(crs_to),
            return_dtype=spatial_series_dtype,
        )

    def min_max(self) -> pl.Expr:
        """Normalize a value in a column to be 0-1."""
        return (self._expr - self._expr.min()) / (self._expr.max() - self._expr.min())

    def to_geometrycollection(self) -> pl.Expr:
        """Take a list of geometry structs, return a geometry collection struct.

        This expression is intended to be used primarily to aggregate geometries after a
        group_by context.
        """
        return self._expr.map_batches(
            lambda s: s.spatial.to_geometrycollection(),
            return_dtype=spatial_series_dtype,
            is_elementwise=True,
        )

    def from_WKB(self, crs: Any = 4326) -> pl.Expr:  #  NOQA:ANN401, N802
        """Return a spatial series from a series of WKB.

        Parameters
        ----------
        crs
            The coordinate reference system of the data.

        """
        return self._expr.map_batches(
            lambda s: s.spatial.from_WKB(crs=crs),
            return_dtype=spatial_series_dtype,
        )

    def from_WKT(self, crs: Any = 4326) -> pl.Expr:  #  NOQA:ANN401, N802
        """Return a spatial series from a series of WKT.

        Parameters
        ----------
        crs
            The coordinate reference system of the data.

        """
        return self._expr.map_batches(
            lambda s: s.spatial.from_WKT(crs=crs),
            return_dtype=spatial_series_dtype,
        )

__init__(expr)

For making polars expressions of geometric functions.

Source code in src\spatial_polars\spatialexpr.py
def __init__(self, expr: pl.Expr) -> None:
    """For making polars expressions of geometric functions."""
    self._expr = expr

to_shapely_array()

Create an array of shapely geometries.

Source code in src\spatial_polars\spatialexpr.py
def to_shapely_array(self) -> pl.Expr:
    """Create an array of shapely geometries."""
    return self._expr.map_batches(
        lambda s: s.spatial.to_shapely_array(),
        return_dtype=pl.Object,
        is_elementwise=True,
    )

reproject(crs_to)

Reproject data to a different CRS.

Parameters:

Name Type Description Default
crs_to Any

The coordinate reference system to reproject the data into.

required
Source code in src\spatial_polars\spatialexpr.py
def reproject(self, crs_to: Any) -> pl.Expr:  #  NOQA:ANN401
    """Reproject data to a different CRS.

    Parameters
    ----------
    crs_to
        The coordinate reference system to reproject the data into.

    """
    # using is_elementwise=True causes issues,
    # assuming something with the LRU caching or something like that.
    return self._expr.map_batches(
        lambda s: s.spatial.reproject(crs_to),
        return_dtype=spatial_series_dtype,
    )

min_max()

Normalize a value in a column to be 0-1.

Source code in src\spatial_polars\spatialexpr.py
def min_max(self) -> pl.Expr:
    """Normalize a value in a column to be 0-1."""
    return (self._expr - self._expr.min()) / (self._expr.max() - self._expr.min())

to_geometrycollection()

Take a list of geometry structs, return a geometry collection struct.

This expression is intended to be used primarily to aggregate geometries after a group_by context.

Source code in src\spatial_polars\spatialexpr.py
def to_geometrycollection(self) -> pl.Expr:
    """Take a list of geometry structs, return a geometry collection struct.

    This expression is intended to be used primarily to aggregate geometries after a
    group_by context.
    """
    return self._expr.map_batches(
        lambda s: s.spatial.to_geometrycollection(),
        return_dtype=spatial_series_dtype,
        is_elementwise=True,
    )

from_WKB(crs=4326)

Return a spatial series from a series of WKB.

Parameters:

Name Type Description Default
crs Any

The coordinate reference system of the data.

4326
Source code in src\spatial_polars\spatialexpr.py
def from_WKB(self, crs: Any = 4326) -> pl.Expr:  #  NOQA:ANN401, N802
    """Return a spatial series from a series of WKB.

    Parameters
    ----------
    crs
        The coordinate reference system of the data.

    """
    return self._expr.map_batches(
        lambda s: s.spatial.from_WKB(crs=crs),
        return_dtype=spatial_series_dtype,
    )

from_WKT(crs=4326)

Return a spatial series from a series of WKT.

Parameters:

Name Type Description Default
crs Any

The coordinate reference system of the data.

4326
Source code in src\spatial_polars\spatialexpr.py
def from_WKT(self, crs: Any = 4326) -> pl.Expr:  #  NOQA:ANN401, N802
    """Return a spatial series from a series of WKT.

    Parameters
    ----------
    crs
        The coordinate reference system of the data.

    """
    return self._expr.map_batches(
        lambda s: s.spatial.from_WKT(crs=crs),
        return_dtype=spatial_series_dtype,
    )