Commit 9267fb88 authored by Claude Paroz's avatar Claude Paroz
Browse files

Added more spatial predicates for prepared geometries

GEOS 3.3 added crosses, disjoint, overlaps, touches and within
predicates on prepared geometries.
parent d17404aa
Loading
Loading
Loading
Loading
+31 −3
Original line number Diff line number Diff line
from django.contrib.gis.geos.base import GEOSBase
from django.contrib.gis.geos.geometry import GEOSGeometry
from django.contrib.gis.geos.prototypes import prepared as capi
from .base import GEOSBase
from .geometry import GEOSGeometry
from .libgeos import geos_version_info
from .prototypes import prepared as capi


class PreparedGeometry(GEOSBase):
@@ -35,3 +36,30 @@ class PreparedGeometry(GEOSBase):

    def intersects(self, other):
        return capi.prepared_intersects(self.ptr, other.ptr)

    # Added in GEOS 3.3:

    def crosses(self, other):
        if geos_version_info()['version'] < '3.3.0':
            raise GEOSException("crosses on prepared geometries requires GEOS >= 3.3.0")
        return capi.prepared_crosses(self.ptr, other.ptr)

    def disjoint(self, other):
        if geos_version_info()['version'] < '3.3.0':
            raise GEOSException("disjoint on prepared geometries requires GEOS >= 3.3.0")
        return capi.prepared_disjoint(self.ptr, other.ptr)

    def overlaps(self, other):
        if geos_version_info()['version'] < '3.3.0':
            raise GEOSException("overlaps on prepared geometries requires GEOS >= 3.3.0")
        return capi.prepared_overlaps(self.ptr, other.ptr)

    def touches(self, other):
        if geos_version_info()['version'] < '3.3.0':
            raise GEOSException("touches on prepared geometries requires GEOS >= 3.3.0")
        return capi.prepared_touches(self.ptr, other.ptr)

    def within(self, other):
        if geos_version_info()['version'] < '3.3.0':
            raise GEOSException("within on prepared geometries requires GEOS >= 3.3.0")
        return capi.prepared_within(self.ptr, other.ptr)
+8 −1
Original line number Diff line number Diff line
from ctypes import c_char
from django.contrib.gis.geos.libgeos import GEOM_PTR, PREPGEOM_PTR
from django.contrib.gis.geos.libgeos import GEOM_PTR, PREPGEOM_PTR, geos_version_info
from django.contrib.gis.geos.prototypes.errcheck import check_predicate
from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc

@@ -24,3 +24,10 @@ prepared_contains = prepared_predicate(GEOSFunc('GEOSPreparedContains'))
prepared_contains_properly = prepared_predicate(GEOSFunc('GEOSPreparedContainsProperly'))
prepared_covers = prepared_predicate(GEOSFunc('GEOSPreparedCovers'))
prepared_intersects = prepared_predicate(GEOSFunc('GEOSPreparedIntersects'))

if geos_version_info()['version'] > '3.3.0':
    prepared_crosses = prepared_predicate(GEOSFunc('GEOSPreparedCrosses'))
    prepared_disjoint = prepared_predicate(GEOSFunc('GEOSPreparedDisjoint'))
    prepared_overlaps = prepared_predicate(GEOSFunc('GEOSPreparedOverlaps'))
    prepared_touches = prepared_predicate(GEOSFunc('GEOSPreparedTouches'))
    prepared_within = prepared_predicate(GEOSFunc('GEOSPreparedWithin'))
+10 −0
Original line number Diff line number Diff line
@@ -1032,6 +1032,16 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
            self.assertEqual(mpoly.intersects(pnt), prep.intersects(pnt))
            self.assertEqual(c, prep.covers(pnt))

        if geos_version_info()['version'] > '3.3.0':
            self.assertTrue(prep.crosses(fromstr('LINESTRING(1 1, 15 15)')))
            self.assertTrue(prep.disjoint(Point(-5, -5)))
            poly = Polygon(((-1, -1), (1, 1), (1, 0), (-1, -1)))
            self.assertTrue(prep.overlaps(poly))
            poly = Polygon(((-5, 0), (-5, 5), (0, 5), (-5, 0)))
            self.assertTrue(prep.touches(poly))
            poly = Polygon(((-1, -1), (-1, 11), (11, 11), (11, -1), (-1, -1)))
            self.assertTrue(prep.within(poly))

        # Original geometry deletion should not crash the prepared one (#21662)
        del mpoly
        self.assertTrue(prep.covers(Point(5, 5)))
+42 −2
Original line number Diff line number Diff line
@@ -527,8 +527,8 @@ a :class:`Polygon`).

Returns a GEOS ``PreparedGeometry`` for the contents of this geometry.
``PreparedGeometry`` objects are optimized for the contains, intersects,
and covers operations.  Refer to the :ref:`prepared-geometries` documentation
for more information.
covers, crosses, disjoint, overlaps, touches and within operations. Refer to
the :ref:`prepared-geometries` documentation for more information.

.. attribute:: GEOSGeometry.srs

@@ -746,8 +746,48 @@ For example::

  .. method:: covers(other)

  .. method:: crosses(other)

    .. versionadded:: 1.7

    .. note::

       GEOS 3.3 is *required* to use this predicate.

  .. method:: disjoint(other)

    .. versionadded:: 1.7

    .. note::

       GEOS 3.3 is *required* to use this predicate.

  .. method:: intersects(other)

  .. method:: overlaps(other)

    .. versionadded:: 1.7

    .. note::

       GEOS 3.3 is *required* to use this predicate.

  .. method:: touches(other)

    .. versionadded:: 1.7

    .. note::

       GEOS 3.3 is *required* to use this predicate.

  .. method:: within(other)

    .. versionadded:: 1.7

    .. note::

       GEOS 3.3 is *required* to use this predicate.

Geometry Factories
==================

+4 −0
Original line number Diff line number Diff line
@@ -211,6 +211,10 @@ Minor features
* The default OpenLayers library version included in widgets has been updated
  from 2.11 to 2.13.

* Prepared geometries now also support the ``crosses``, ``disjoint``,
  ``overlaps``, ``touches`` and ``within`` predicates, if GEOS 3.3 or later is
  installed.

:mod:`django.contrib.messages`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^