From 18dca3ffcf065307dcf0393b1e824ebc896d1a7b Mon Sep 17 00:00:00 2001 From: Bhavika Tekwani <4955119+bhavika@users.noreply.github.com> Date: Tue, 9 Jun 2020 02:26:12 -0400 Subject: [PATCH] ENH: add covered_by() method for GeoSeries (#1462) --- geopandas/_vectorized.py | 9 +++++++++ geopandas/array.py | 3 +++ geopandas/base.py | 19 +++++++++++++++++++ geopandas/tests/test_geom_methods.py | 13 +++++++++++-- 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/geopandas/_vectorized.py b/geopandas/_vectorized.py index 2369fd1..4d37d56 100644 --- a/geopandas/_vectorized.py +++ b/geopandas/_vectorized.py @@ -625,6 +625,15 @@ def covers(data, other): return _binary_predicate("covers", data, other) +def covered_by(data, other): + if compat.USE_PYGEOS: + return _binary_method("covered_by", data, other) + else: + raise NotImplementedError( + "covered_by is only implemented for pygeos, not shapely" + ) + + def contains(data, other): if compat.USE_PYGEOS: return _binary_method("contains", data, other) diff --git a/geopandas/array.py b/geopandas/array.py index d886a1f..3391392 100644 --- a/geopandas/array.py +++ b/geopandas/array.py @@ -463,6 +463,9 @@ class GeometryArray(ExtensionArray): def covers(self, other): return self._binary_method("covers", self, other) + def covered_by(self, other): + return self._binary_method("covered_by", self, other) + def contains(self, other): return self._binary_method("contains", self, other) diff --git a/geopandas/base.py b/geopandas/base.py index 4e8c9c2..b726565 100644 --- a/geopandas/base.py +++ b/geopandas/base.py @@ -451,6 +451,25 @@ class GeoPandasBase(object): """ return _binary_geo("covers", self, other) + def covered_by(self, other): + """ + Returns a ``Series`` of ``dtype('bool')`` with value ``True`` for + each geometry that is entirely covered by `other`. + + An object A is said to cover another object B if no points of B lie + in the exterior of A. + + See + https://lin-ear-th-inking.blogspot.com/2007/06/subtleties-of-ogc-covers-spatial.html + for reference. + + Parameters + ---------- + other : Geoseries or geometric object + The Geoseries (elementwise) or geometric object to check is being covered. + """ + return _binary_geo("covered_by", self, other) + def distance(self, other): """Returns a ``Series`` containing the distance to `other`. diff --git a/geopandas/tests/test_geom_methods.py b/geopandas/tests/test_geom_methods.py index 113028a..e020593 100644 --- a/geopandas/tests/test_geom_methods.py +++ b/geopandas/tests/test_geom_methods.py @@ -12,7 +12,7 @@ from geopandas import GeoDataFrame, GeoSeries from geopandas.base import GeoPandasBase from geopandas.tests.util import assert_geoseries_equal, geom_almost_equals, geom_equals -from geopandas._compat import PANDAS_GE_024 +from geopandas import _compat as compat from pandas.testing import assert_frame_equal, assert_series_equal import pytest @@ -422,6 +422,15 @@ class TestGeomMethods: exp = Series([False, False]) assert_series_equal(res, exp) + @pytest.mark.skipif( + not compat.USE_PYGEOS, + reason="covered_by is only implemented for pygeos, not shapely", + ) + def test_covered_by(self): + res = self.g1.covered_by(self.g1) + exp = Series([True, True]) + assert_series_equal(res, exp) + def test_is_valid(self): expected = Series(np.array([True] * len(self.g1)), self.g1.index) self._test_unary_real("is_valid", expected, self.g1) @@ -696,7 +705,7 @@ class TestGeomMethods: names=[index_name, None], ) expected_df = expected_df.set_index(expected_index) - if not PANDAS_GE_024: + if not compat.PANDAS_GE_024: expected_df = expected_df[["level_1", "geometry"]] assert_frame_equal(test_df, expected_df)