Commit cabc21ca authored by Justin Bronn's avatar Justin Bronn
Browse files

Fixed #14318 -- Added `GEOSGeometry.valid_reason` property. Thanks, Rob Coup.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@14447 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 877033b4
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
@@ -275,6 +275,15 @@ class GEOSGeometry(GEOSBase, ListMixin):
        "This property tests the validity of this Geometry."
        return capi.geos_isvalid(self.ptr)

    @property
    def valid_reason(self):
        """
        Returns a string containing the reason for any invalidity.
        """
        if not GEOS_PREPARE:
            raise GEOSException('Upgrade GEOS to 3.1 to get validity reason.')
        return capi.geos_isvalidreason(self.ptr)

    #### Binary predicates. ####
    def contains(self, other):
        "Returns true if other.within(this) returns true."
+1 −1
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ from django.contrib.gis.geos.prototypes.geom import from_hex, from_wkb, from_wkt
    to_hex, to_wkb, to_wkt

# Miscellaneous routines.
from django.contrib.gis.geos.prototypes.misc import geos_area, geos_distance, geos_length
from django.contrib.gis.geos.prototypes.misc import *

# Predicates
from django.contrib.gis.geos.prototypes.predicates import geos_hasz, geos_isempty, \
+13 −2
Original line number Diff line number Diff line
@@ -3,10 +3,13 @@
 ones that return the area, distance, and length.
"""
from ctypes import c_int, c_double, POINTER
from django.contrib.gis.geos.libgeos import GEOM_PTR
from django.contrib.gis.geos.prototypes.errcheck import check_dbl
from django.contrib.gis.geos.libgeos import GEOM_PTR, GEOS_PREPARE
from django.contrib.gis.geos.prototypes.errcheck import check_dbl, check_string
from django.contrib.gis.geos.prototypes.geom import geos_char_p
from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc

__all__ = ['geos_area', 'geos_distance', 'geos_length']

### ctypes generator function ###
def dbl_from_geom(func, num_geom=1):
    """
@@ -26,3 +29,11 @@ def dbl_from_geom(func, num_geom=1):
geos_area = dbl_from_geom(GEOSFunc('GEOSArea'))
geos_distance = dbl_from_geom(GEOSFunc('GEOSDistance'), num_geom=2)
geos_length = dbl_from_geom(GEOSFunc('GEOSLength'))

# Validity reason; only in GEOS 3.1+
if GEOS_PREPARE:
    geos_isvalidreason = GEOSFunc('GEOSisValidReason')
    geos_isvalidreason.argtypes = [GEOM_PTR]
    geos_isvalidreason.restype = geos_char_p
    geos_isvalidreason.errcheck = check_string
    __all__.append('geos_isvalidreason')
+21 −0
Original line number Diff line number Diff line
import ctypes, random, unittest, sys
from django.contrib.gis.geos import *
from django.contrib.gis.geos.base import gdal, numpy, GEOSBase
from django.contrib.gis.geos.libgeos import GEOS_PREPARE
from django.contrib.gis.geometry.test_data import TestDataMixin

class GEOSTest(unittest.TestCase, TestDataMixin):
@@ -917,6 +918,26 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
        for geom, merged in zip(ref_geoms, ref_merged):
            self.assertEqual(merged, geom.merged)

    def test27_valid_reason(self):
        "Testing IsValidReason support"
        # Skipping tests if GEOS < v3.1.
        if not GEOS_PREPARE: return

        g = GEOSGeometry("POINT(0 0)")
        self.assert_(g.valid)
        self.assert_(isinstance(g.valid_reason, basestring))
        self.assertEqual(g.valid_reason, "Valid Geometry")

        print "\nBEGIN - expecting GEOS_NOTICE; safe to ignore.\n"

        g = GEOSGeometry("LINESTRING(0 0, 0 0)")

        self.assert_(not g.valid)
        self.assert_(isinstance(g.valid_reason, basestring))
        self.assertEqual(g.valid_reason, "Too few points in geometry component[0 0]")

        print "\nEND - expecting GEOS_NOTICE; safe to ignore.\n"

def suite():
    s = unittest.TestSuite()
    s.addTest(unittest.makeSuite(GEOSTest))
+6 −0
Original line number Diff line number Diff line
@@ -219,6 +219,12 @@ definition.

Returns a boolean indicating whether the geometry is valid.

.. attribute:: GEOSGeometry.valid_reason 

.. versionadded:: 1.3 

Returns a string describing the reason why a geometry is invalid. 

.. attribute:: GEOSGeometry.srid

Property that may be used to retrieve or set the SRID associated with the