Skip to content

Commit

Permalink
ENH: Added total_bounds() (pygeos/pygeos#107)
Browse files Browse the repository at this point in the history
  • Loading branch information
brendan-ward committed Mar 13, 2020
1 parent a4b3619 commit d71fe6b
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 18 deletions.
41 changes: 40 additions & 1 deletion pygeos/measurement.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from . import lib
from . import Geometry # NOQA

__all__ = ["area", "distance", "bounds", "length", "hausdorff_distance"]
__all__ = ["area", "distance", "bounds", "total_bounds", "length", "hausdorff_distance"]


def area(geometry, **kwargs):
Expand Down Expand Up @@ -78,6 +78,45 @@ def bounds(geometry, **kwargs):
return lib.bounds(geometry_arr, out=out, **kwargs)


def total_bounds(geometry, **kwargs):
"""Computes the total bounds (extent) of the geometry.
Parameters
----------
geometry : Geometry or array_like
Returns
-------
numpy ndarray of [xmin, ymin, xmax, ymax]
>>> total_bounds(Geometry("POINT (2 3)")).tolist()
[2.0, 3.0, 2.0, 3.0]
>>> total_bounds([Geometry("POINT (2 3)"), Geometry("POINT (4 5)")]).tolist()
[2.0, 3.0, 4.0, 5.0]
>>> total_bounds([Geometry("LINESTRING (0 1, 0 2, 3 2)"),Geometry("LINESTRING (4 4, 4 6, 6 7)")]).tolist()
[0.0, 1.0, 6.0, 7.0]
>>> total_bounds(Geometry("POLYGON EMPTY")).tolist()
[nan, nan, nan, nan]
>>> total_bounds([Geometry("POLYGON EMPTY"), Geometry("POINT (2 3)")]).tolist()
[2.0, 3.0, 2.0, 3.0]
>>> total_bounds(None).tolist()
[nan, nan, nan, nan]
"""
b = bounds(geometry, **kwargs)
if b.ndim == 1:
return b

return np.array(
[
np.nanmin(b[..., 0]),
np.nanmin(b[..., 1]),
np.nanmax(b[..., 2]),
np.nanmax(b[..., 3]),
]
)


def length(geometry, **kwargs):
"""Computes the length of a (multi)linestring or polygon perimeter.
Expand Down
73 changes: 56 additions & 17 deletions pygeos/test/test_measurement.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pygeos
import pytest
import numpy as np
from numpy.testing import assert_array_equal

from .common import point_polygon_testdata
from .common import point
Expand Down Expand Up @@ -49,32 +50,70 @@ def test_distance_missing():
@pytest.mark.parametrize(
"geom,expected",
[
(point, [2.0, 3.0, 2.0, 3.0]),
(pygeos.linestrings([[0, 0], [0, 1]]), [0.0, 0.0, 0.0, 1.0]),
(pygeos.linestrings([[0, 0], [1, 0]]), [0.0, 0.0, 1.0, 0.0]),
(multi_point, [0.0, 0.0, 1.0, 2.0]),
(multi_polygon, [0.0, 0.0, 2.2, 2.2]),
(geometry_collection, [49.0, -1.0, 52.0, 2.0]),
(point, [2, 3, 2, 3]),
([point, multi_point], [[2, 3, 2, 3], [0, 0, 1, 2]]),
(pygeos.linestrings([[0, 0], [0, 1]]), [0, 0, 0, 1]),
(pygeos.linestrings([[0, 0], [1, 0]]), [0, 0, 1, 0]),
(multi_point, [0, 0, 1, 2]),
(multi_polygon, [0, 0, 2.2, 2.2]),
(geometry_collection, [49, -1, 52, 2]),
(empty, [np.nan, np.nan, np.nan, np.nan]),
(None, [np.nan, np.nan, np.nan, np.nan]),
],
)
def test_bounds(geom, expected):
actual = pygeos.bounds(geom)
assert actual.tolist() == expected
assert_array_equal(pygeos.bounds(geom), expected)


def test_bounds_array():
actual = pygeos.bounds([[point, multi_point], [polygon, None]])
assert actual.shape == (2, 2, 4)
@pytest.mark.parametrize(
"geom,shape",
[
(point, (4,)),
(None, (4,)),
([point, multi_point], (2, 4)),
([[point, multi_point], [polygon, point]], (2, 2, 4)),
([[[point, multi_point]], [[polygon, point]]], (2, 1, 2, 4)),
],
)
def test_bounds_dimensions(geom, shape):
assert pygeos.bounds(geom).shape == shape


def test_bounds_missing():
actual = pygeos.bounds(None)
assert np.isnan(actual).all()
@pytest.mark.parametrize(
"geom,expected",
[
(point, [2, 3, 2, 3]),
(pygeos.linestrings([[0, 0], [0, 1]]), [0, 0, 0, 1]),
(pygeos.linestrings([[0, 0], [1, 0]]), [0, 0, 1, 0]),
(multi_point, [0, 0, 1, 2]),
(multi_polygon, [0, 0, 2.2, 2.2]),
(geometry_collection, [49, -1, 52, 2]),
(empty, [np.nan, np.nan, np.nan, np.nan]),
(None, [np.nan, np.nan, np.nan, np.nan]),
([empty, empty, None], [np.nan, np.nan, np.nan, np.nan]),
# mixed missing and non-missing coordinates
([point, None], [2, 3, 2, 3]),
([point, empty], [2, 3, 2, 3]),
([point, empty, None], [2, 3, 2, 3]),
([point, empty, None, multi_point], [0, 0, 2, 3]),
],
)
def test_total_bounds(geom, expected):
assert_array_equal(pygeos.total_bounds(geom), expected)


def test_bounds_empty():
actual = pygeos.bounds(empty)
assert np.isnan(actual).all()
@pytest.mark.parametrize(
"geom",
[
point,
None,
[point, multi_point],
[[point, multi_point], [polygon, point]],
[[[point, multi_point]], [[polygon, point]]],
],
)
def test_total_bounds_dimensions(geom):
assert pygeos.total_bounds(geom).shape == (4,)


def test_length():
Expand Down

0 comments on commit d71fe6b

Please sign in to comment.