1
0
mirror of https://github.com/django/django.git synced 2025-07-03 17:29:12 +00:00

gis: geos: GEOSGeometry objects may now be pickled; added the clone keyword to transform which returns a cloned transformed geometry rather than transforming in-place.

git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@7404 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Justin Bronn 2008-04-07 20:15:04 +00:00
parent 4a636ec3a3
commit 147bd6ac36
2 changed files with 68 additions and 12 deletions

View File

@ -87,16 +87,21 @@ class GEOSGeometry(object):
else:
raise GEOSException('Could not initialize GEOS Geometry with given input.')
# Post-initialization setup.
self._post_init(srid)
def _post_init(self, srid):
"Helper routine for performing post-initialization setup."
# Setting the SRID, if given.
if srid and isinstance(srid, int): self.srid = srid
# Setting the class type (e.g., Point, Polygon, etc.)
self.__class__ = GEOS_CLASSES[self.geom_typeid]
# Setting the coordinate sequence for the geometry (will be None on
# geometries that do not have coordinate sequences)
# geometries that do not have coordinate sequences)
self._set_cs()
@property
def ptr(self):
"""
@ -139,6 +144,20 @@ class GEOSGeometry(object):
"Short-hand representation because WKT may be very large."
return '<%s object at %s>' % (self.geom_type, hex(addressof(self.ptr)))
# Pickling support
def __getstate__(self):
# The pickled state is simply a tuple of the WKB (in string form)
# and the SRID.
return str(self.wkb), self.srid
def __setstate__(self, state):
# Instantiating from the tuple state that was pickled.
wkb, srid = state
ptr = from_wkb(wkb, len(wkb))
if not ptr: raise GEOSException('Invalid Geometry loaded from pickled state.')
self._ptr = ptr
self._post_init(srid)
# Comparison operators
def __eq__(self, other):
"""
@ -413,23 +432,32 @@ class GEOSGeometry(object):
"Alias for `srs` property."
return self.srs
def transform(self, ct):
"Transforms this Geometry; only works with GDAL."
def transform(self, ct, clone=False):
"""
Requires GDAL. Transforms the geometry according to the given
transformation object, which may be an integer SRID, and WKT or
PROJ.4 string. By default, the geometry is transformed in-place and
nothing is returned. However if the `clone` keyword is set, then this
geometry will not be modified and a transformed clone will be returned
instead.
"""
srid = self.srid
if HAS_GDAL and srid:
g = OGRGeometry(self.wkb, srid)
g.transform(ct)
wkb = str(g.wkb)
ptr = from_wkb(wkb, len(wkb))
if clone:
# User wants a cloned transformed geometry returned.
return GEOSGeometry(ptr, srid=g.srid)
if ptr:
# Reassigning pointer, and getting the new coordinate sequence pointer.
# Reassigning pointer, and performing post-initialization setup
# again due to the reassignment.
destroy_geom(self.ptr)
self._ptr = ptr
self._set_cs()
# Some coordinate transformations do not have an SRID associated
# with them; only set if one exists.
if g.srid: self.srid = g.srid
self._post_init(g.srid)
else:
raise GEOSException('Transformed WKB was invalid.')
#### Topology Routines ####
def _topology(self, gptr):

View File

@ -703,8 +703,15 @@ class GEOSTest(unittest.TestCase):
t2.transform(SpatialReference('EPSG:2774'))
ct = CoordTransform(SpatialReference('WGS84'), SpatialReference(2774))
t3.transform(ct)
# Testing use of the `clone` keyword.
k1 = orig.clone()
k2 = k1.transform(trans.srid, clone=True)
self.assertEqual(k1, orig)
self.assertNotEqual(k1, k2)
prec = 3
for p in (t1, t2, t3):
for p in (t1, t2, t3, k2):
self.assertAlmostEqual(trans.x, p.x, prec)
self.assertAlmostEqual(trans.y, p.y, prec)
@ -724,6 +731,27 @@ class GEOSTest(unittest.TestCase):
xmax, ymax = max(x), max(y)
self.assertEqual((xmin, ymin, xmax, ymax), poly.extent)
def test25_pickle(self):
"Testing pickling and unpickling support."
# Using both pickle and cPickle -- just 'cause.
import pickle, cPickle
# Creating a list of test geometries for pickling,
# and setting the SRID on some of them.
def get_geoms(lst, srid=None):
return [GEOSGeometry(tg.wkt, srid) for tg in lst]
tgeoms = get_geoms(points)
tgeoms.extend(get_geoms(multilinestrings, 4326))
tgeoms.extend(get_geoms(polygons, 3084))
tgeoms.extend(get_geoms(multipolygons, 900913))
for geom in tgeoms:
s1, s2 = cPickle.dumps(geom), pickle.dumps(geom)
g1, g2 = cPickle.loads(s1), pickle.loads(s2)
for tmpg in (g1, g2):
self.assertEqual(geom, tmpg)
self.assertEqual(geom.srid, tmpg.srid)
def suite():
s = unittest.TestSuite()
s.addTest(unittest.makeSuite(GEOSTest))