summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Fedoseev <fedoseev.sergey@gmail.com>2015-11-20 15:11:25 +0500
committerTim Graham <timograham@gmail.com>2015-11-20 12:36:03 -0500
commitccc8f67b7760dd12faf6007f12a672a8e03f4d88 (patch)
treefb9239ba533a82717f7f3b808614aad9ebb42c2d
parent73a6ab6382809d5452907dcff5767403d8d66985 (diff)
Fixed #25722 -- Added the GEOSGeometry.covers() method.
-rw-r--r--django/contrib/gis/geos/geometry.py8
-rw-r--r--django/contrib/gis/geos/prototypes/__init__.py7
-rw-r--r--django/contrib/gis/geos/prototypes/predicates.py1
-rw-r--r--docs/ref/contrib/gis/geos.txt22
-rw-r--r--docs/releases/1.10.txt3
-rw-r--r--tests/gis_tests/geos_tests/test_geos.py10
6 files changed, 45 insertions, 6 deletions
diff --git a/django/contrib/gis/geos/geometry.py b/django/contrib/gis/geos/geometry.py
index d0d0d9f008..c0808f2e59 100644
--- a/django/contrib/gis/geos/geometry.py
+++ b/django/contrib/gis/geos/geometry.py
@@ -294,6 +294,14 @@ class GEOSGeometry(GEOSBase, ListMixin):
"Returns true if other.within(this) returns true."
return capi.geos_contains(self.ptr, other.ptr)
+ def covers(self, other):
+ """
+ Return True if the DE-9IM Intersection Matrix for the two geometries is
+ T*****FF*, *T****FF*, ***T**FF*, or ****T*FF*. If either geometry is
+ empty, return False.
+ """
+ return capi.geos_covers(self.ptr, other.ptr)
+
def crosses(self, other):
"""
Returns true if the DE-9IM intersection matrix for the two Geometries
diff --git a/django/contrib/gis/geos/prototypes/__init__.py b/django/contrib/gis/geos/prototypes/__init__.py
index d2950d0d97..595555897d 100644
--- a/django/contrib/gis/geos/prototypes/__init__.py
+++ b/django/contrib/gis/geos/prototypes/__init__.py
@@ -17,8 +17,9 @@ from django.contrib.gis.geos.prototypes.geom import ( # NOQA
)
from django.contrib.gis.geos.prototypes.misc import * # NOQA
from django.contrib.gis.geos.prototypes.predicates import ( # NOQA
- geos_contains, geos_crosses, geos_disjoint, geos_equals, geos_equalsexact,
- geos_hasz, geos_intersects, geos_isempty, geos_isring, geos_issimple,
- geos_isvalid, geos_overlaps, geos_relatepattern, geos_touches, geos_within,
+ geos_contains, geos_covers, geos_crosses, geos_disjoint, geos_equals,
+ geos_equalsexact, geos_hasz, geos_intersects, geos_isempty, geos_isring,
+ geos_issimple, geos_isvalid, geos_overlaps, geos_relatepattern,
+ geos_touches, geos_within,
)
from django.contrib.gis.geos.prototypes.topology import * # NOQA
diff --git a/django/contrib/gis/geos/prototypes/predicates.py b/django/contrib/gis/geos/prototypes/predicates.py
index e1b85f4e35..8d335fa187 100644
--- a/django/contrib/gis/geos/prototypes/predicates.py
+++ b/django/contrib/gis/geos/prototypes/predicates.py
@@ -30,6 +30,7 @@ geos_isvalid = UnaryPredicate('GEOSisValid')
# ## Binary Predicates ##
geos_contains = BinaryPredicate('GEOSContains')
+geos_covers = BinaryPredicate('GEOSCovers')
geos_crosses = BinaryPredicate('GEOSCrosses')
geos_disjoint = BinaryPredicate('GEOSDisjoint')
geos_equals = BinaryPredicate('GEOSEquals')
diff --git a/docs/ref/contrib/gis/geos.txt b/docs/ref/contrib/gis/geos.txt
index fffaf61fe7..43727a1ed7 100644
--- a/docs/ref/contrib/gis/geos.txt
+++ b/docs/ref/contrib/gis/geos.txt
@@ -349,6 +349,28 @@ return a boolean.
Returns ``True`` if :meth:`other.within(this) <GEOSGeometry.within>` returns
``True``.
+.. method:: GEOSGeometry.covers(other)
+
+.. versionadded:: 1.10
+
+Returns ``True`` if this geometry covers the specified geometry.
+
+The ``covers`` predicate has the following equivalent definitions:
+
+* Every point of the other geometry is a point of this geometry.
+* The DE-9IM Intersection Matrix for the two geometries is
+ ``T*****FF*``, ``*T****FF*``, ``***T**FF*``, or ``****T*FF*``.
+
+If either geometry is empty, returns ``False``.
+
+This predicate is similar to :meth:`GEOSGeometry.contains`, but is more
+inclusive (i.e. returns ``True`` for more cases). In particular, unlike
+:meth:`~GEOSGeometry.contains` it does not distinguish between points in the
+boundary and in the interior of geometries. For most situations, ``covers()``
+should be preferred to :meth:`~GEOSGeometry.contains`. As an added benefit,
+``covers()`` is more amenable to optimization and hence should outperform
+:meth:`~GEOSGeometry.contains`.
+
.. method:: GEOSGeometry.crosses(other)
Returns ``True`` if the DE-9IM intersection matrix for the two Geometries
diff --git a/docs/releases/1.10.txt b/docs/releases/1.10.txt
index 9eb6e1d93a..26e8849f3f 100644
--- a/docs/releases/1.10.txt
+++ b/docs/releases/1.10.txt
@@ -71,6 +71,9 @@ Minor features
<django.contrib.gis.geos.GEOSGeometry.unary_union>` property computes the
union of all the elements of this geometry.
+* Added the :meth:`GEOSGeometry.covers()
+ <django.contrib.gis.geos.GEOSGeometry.covers>` binary predicate.
+
:mod:`django.contrib.messages`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/gis_tests/geos_tests/test_geos.py b/tests/gis_tests/geos_tests/test_geos.py
index b68720c89e..301d406317 100644
--- a/tests/gis_tests/geos_tests/test_geos.py
+++ b/tests/gis_tests/geos_tests/test_geos.py
@@ -643,6 +643,11 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
self.assertAlmostEqual(exp_ring[k][0], buf_ring[k][0], 9)
self.assertAlmostEqual(exp_ring[k][1], buf_ring[k][1], 9)
+ def test_covers(self):
+ poly = Polygon(((0, 0), (0, 10), (10, 10), (10, 0), (0, 0)))
+ self.assertTrue(poly.covers(Point(5, 5)))
+ self.assertFalse(poly.covers(Point(100, 100)))
+
def test_srid(self):
"Testing the SRID property and keyword."
# Testing SRID keyword on Point
@@ -1084,12 +1089,11 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
# A set of test points.
pnts = [Point(5, 5), Point(7.5, 7.5), Point(2.5, 7.5)]
- covers = [True, True, False] # No `covers` op for regular GEOS geoms.
- for pnt, c in zip(pnts, covers):
+ for pnt in pnts:
# Results should be the same (but faster)
self.assertEqual(mpoly.contains(pnt), prep.contains(pnt))
self.assertEqual(mpoly.intersects(pnt), prep.intersects(pnt))
- self.assertEqual(c, prep.covers(pnt))
+ self.assertEqual(mpoly.covers(pnt), prep.covers(pnt))
self.assertTrue(prep.crosses(fromstr('LINESTRING(1 1, 15 15)')))
self.assertTrue(prep.disjoint(Point(-5, -5)))