summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/contrib/gis/geos/base.py50
-rw-r--r--django/contrib/gis/tests/test_geos.py30
2 files changed, 68 insertions, 12 deletions
diff --git a/django/contrib/gis/geos/base.py b/django/contrib/gis/geos/base.py
index fdb04d0b78..728e99e2be 100644
--- a/django/contrib/gis/geos/base.py
+++ b/django/contrib/gis/geos/base.py
@@ -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):
diff --git a/django/contrib/gis/tests/test_geos.py b/django/contrib/gis/tests/test_geos.py
index 19d28cef88..0fd45a3b4d 100644
--- a/django/contrib/gis/tests/test_geos.py
+++ b/django/contrib/gis/tests/test_geos.py
@@ -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))