1
0
mirror of https://github.com/django/django.git synced 2025-07-04 09:49:12 +00:00

gis: Fixed #5440 with patches from rcoup; cleaned up notice handler in libgeos.

git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@6314 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Justin Bronn 2007-09-15 18:56:35 +00:00
parent 483a807c06
commit 101446dbda
4 changed files with 65 additions and 10 deletions

View File

@ -6,7 +6,7 @@
from ctypes import \ from ctypes import \
byref, string_at, create_string_buffer, pointer, \ byref, string_at, create_string_buffer, pointer, \
c_char_p, c_double, c_int, c_size_t c_char_p, c_double, c_int, c_size_t
from types import StringType, UnicodeType, IntType, FloatType from types import StringType, UnicodeType, IntType, FloatType, BufferType
# Python and GEOS-related dependencies. # Python and GEOS-related dependencies.
import re import re
@ -30,9 +30,13 @@ class GEOSGeometry(object):
#### Python 'magic' routines #### #### Python 'magic' routines ####
def __init__(self, geo_input, srid=None): def __init__(self, geo_input, srid=None):
""" """
The base constructor for GEOS geometry objects, and may take the following The base constructor for GEOS geometry objects, and may take the
string inputs: WKT and HEXEWKB (a PostGIS-specific canonical form). following inputs:
* string: WKT
* string: HEXEWKB (a PostGIS-specific canonical form)
* buffer: WKB
The `srid` keyword is used to specify the Source Reference Identifier The `srid` keyword is used to specify the Source Reference Identifier
(SRID) number for this Geometry. If not set, the SRID will be None. (SRID) number for this Geometry. If not set, the SRID will be None.
""" """
@ -55,6 +59,11 @@ class GEOSGeometry(object):
# When the input is either a memory address (an integer), or a # When the input is either a memory address (an integer), or a
# GEOSPointer object. # GEOSPointer object.
g = geo_input g = geo_input
elif isinstance(geo_input, BufferType):
# When the input is a buffer (WKB).
wkb_input = str(geo_input)
sz = c_size_t(len(wkb_input))
g = lgeos.GEOSGeomFromWKB_buf(c_char_p(wkb_input), sz)
else: else:
# Invalid geometry type. # Invalid geometry type.
raise TypeError, 'Improper geometry input type: %s' % str(type(geo_input)) raise TypeError, 'Improper geometry input type: %s' % str(type(geo_input))
@ -413,6 +422,13 @@ class GEOSGeometry(object):
h = lgeos.GEOSGeomToHEX_buf(self._ptr(), byref(sz)) h = lgeos.GEOSGeomToHEX_buf(self._ptr(), byref(sz))
return string_at(h, sz.value) return string_at(h, sz.value)
@property
def wkb(self):
"Returns the WKB of the Geometry as a buffer."
sz = c_size_t()
h = lgeos.GEOSGeomToWKB_buf(self._ptr(), byref(sz))
return buffer(string_at(h, sz.value))
@property @property
def kml(self): def kml(self):
"Returns the KML representation of this Geometry." "Returns the KML representation of this Geometry."

View File

@ -52,8 +52,12 @@ lgeos = CDLL(lib_name)
# Supposed to mimic the GEOS message handler (C below): # Supposed to mimic the GEOS message handler (C below):
# "typedef void (*GEOSMessageHandler)(const char *fmt, ...);" # "typedef void (*GEOSMessageHandler)(const char *fmt, ...);"
NOTICEFUNC = CFUNCTYPE(None, c_char_p, c_char_p) NOTICEFUNC = CFUNCTYPE(None, c_char_p, c_char_p)
def notice_h(fmt, list, output_h=sys.stdout): def notice_h(fmt, lst, output_h=sys.stdout):
output_h.write('GEOS_NOTICE: %s\n' % (fmt % list)) try:
warn_msg = fmt % lst
except:
warn_msg = fmt
output_h.write('GEOS_NOTICE: %s\n' % warn_msg)
notice_h = NOTICEFUNC(notice_h) notice_h = NOTICEFUNC(notice_h)
ERRORFUNC = CFUNCTYPE(None, c_char_p, c_char_p) ERRORFUNC = CFUNCTYPE(None, c_char_p, c_char_p)

View File

@ -49,6 +49,7 @@ errors = (TestGeom('GEOMETR##!@#%#............a32515', bad=True, hex=False),
TestGeom('POINT (5, 23)', bad=True, hex=False), TestGeom('POINT (5, 23)', bad=True, hex=False),
TestGeom('AAABBBDDDAAD##@#1113511111-098111111111111111533333333333333', bad=True, hex=True), TestGeom('AAABBBDDDAAD##@#1113511111-098111111111111111533333333333333', bad=True, hex=True),
TestGeom('FFFFFFFFFFFFFFFFF1355555555555555555565111', bad=True, hex=True), TestGeom('FFFFFFFFFFFFFFFFF1355555555555555555565111', bad=True, hex=True),
TestGeom('', bad=True, hex=False),
) )
# Polygons # Polygons

View File

@ -31,14 +31,48 @@ class GEOSTest(unittest.TestCase):
def test01d_errors(self): def test01d_errors(self):
"Testing the Error handlers." "Testing the Error handlers."
# string-based
print "\nBEGIN - expecting GEOS_ERROR; safe to ignore.\n" print "\nBEGIN - expecting GEOS_ERROR; safe to ignore.\n"
for err in errors: for err in errors:
if err.hex: self.assertRaises(GEOSException, fromstr, err.wkt)
self.assertRaises(GEOSException, fromstr, err.wkt)
else:
self.assertRaises(GEOSException, fromstr, err.wkt)
print "\nEND - expecting GEOS_ERROR; safe to ignore.\n" print "\nEND - expecting GEOS_ERROR; safe to ignore.\n"
class NotAGeometry(object):
pass
# Some other object
self.assertRaises(TypeError, GEOSGeometry, NotAGeometry())
# None
self.assertRaises(TypeError, GEOSGeometry, None)
# Bad WKB
self.assertRaises(GEOSException, GEOSGeometry, buffer('0'))
def test01e_wkb(self):
"Testing WKB output."
from binascii import b2a_hex
for g in hex_wkt:
geom = fromstr(g.wkt)
wkb = geom.wkb
self.assertEqual(b2a_hex(wkb).upper(), g.hex)
def test01f_create_hex(self):
"Testing creation from HEX."
for g in hex_wkt:
geom_h = GEOSGeometry(g.hex)
# we need to do this so decimal places get normalised
geom_t = fromstr(g.wkt)
self.assertEqual(geom_t.wkt, geom_h.wkt)
def test01g_create_wkb(self):
"Testing creation from WKB."
from binascii import a2b_hex
for g in hex_wkt:
wkb = buffer(a2b_hex(g.hex))
geom_h = GEOSGeometry(wkb)
# we need to do this so decimal places get normalised
geom_t = fromstr(g.wkt)
self.assertEqual(geom_t.wkt, geom_h.wkt)
def test02a_points(self): def test02a_points(self):
"Testing Point objects." "Testing Point objects."
prev = fromstr('POINT(0 0)') prev = fromstr('POINT(0 0)')