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
This commit is contained in:
parent
877033b479
commit
cabc21ca60
|
@ -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."
|
||||
|
@ -376,7 +385,7 @@ class GEOSGeometry(GEOSBase, ListMixin):
|
|||
"""
|
||||
Returns the WKB of this Geometry in hexadecimal form. Please note
|
||||
that the SRID and Z values are not included in this representation
|
||||
because it is not a part of the OGC specification (use the `hexewkb`
|
||||
because it is not a part of the OGC specification (use the `hexewkb`
|
||||
property instead).
|
||||
"""
|
||||
# A possible faster, all-python, implementation:
|
||||
|
@ -386,14 +395,14 @@ class GEOSGeometry(GEOSBase, ListMixin):
|
|||
@property
|
||||
def hexewkb(self):
|
||||
"""
|
||||
Returns the EWKB of this Geometry in hexadecimal form. This is an
|
||||
extension of the WKB specification that includes SRID and Z values
|
||||
Returns the EWKB of this Geometry in hexadecimal form. This is an
|
||||
extension of the WKB specification that includes SRID and Z values
|
||||
that are a part of this geometry.
|
||||
"""
|
||||
if self.hasz:
|
||||
if not GEOS_PREPARE:
|
||||
# See: http://trac.osgeo.org/geos/ticket/216
|
||||
raise GEOSException('Upgrade GEOS to 3.1 to get valid 3D HEXEWKB.')
|
||||
raise GEOSException('Upgrade GEOS to 3.1 to get valid 3D HEXEWKB.')
|
||||
return ewkb_w3d().write_hex(self)
|
||||
else:
|
||||
return ewkb_w().write_hex(self)
|
||||
|
|
|
@ -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, \
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
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))
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue