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: else:
raise GEOSException('Could not initialize GEOS Geometry with given input.') 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. # Setting the SRID, if given.
if srid and isinstance(srid, int): self.srid = srid if srid and isinstance(srid, int): self.srid = srid
# Setting the class type (e.g., Point, Polygon, etc.) # Setting the class type (e.g., Point, Polygon, etc.)
self.__class__ = GEOS_CLASSES[self.geom_typeid] self.__class__ = GEOS_CLASSES[self.geom_typeid]
# Setting the coordinate sequence for the geometry (will be None on # 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() self._set_cs()
@property @property
def ptr(self): def ptr(self):
""" """
@ -139,6 +144,20 @@ class GEOSGeometry(object):
"Short-hand representation because WKT may be very large." "Short-hand representation because WKT may be very large."
return '<%s object at %s>' % (self.geom_type, hex(addressof(self.ptr))) 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 # Comparison operators
def __eq__(self, other): def __eq__(self, other):
""" """
@ -413,23 +432,32 @@ class GEOSGeometry(object):
"Alias for `srs` property." "Alias for `srs` property."
return self.srs return self.srs
def transform(self, ct): def transform(self, ct, clone=False):
"Transforms this Geometry; only works with GDAL." """
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 srid = self.srid
if HAS_GDAL and srid: if HAS_GDAL and srid:
g = OGRGeometry(self.wkb, srid) g = OGRGeometry(self.wkb, srid)
g.transform(ct) g.transform(ct)
wkb = str(g.wkb) wkb = str(g.wkb)
ptr = from_wkb(wkb, len(wkb)) ptr = from_wkb(wkb, len(wkb))
if clone:
# User wants a cloned transformed geometry returned.
return GEOSGeometry(ptr, srid=g.srid)
if ptr: 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) destroy_geom(self.ptr)
self._ptr = ptr self._ptr = ptr
self._set_cs() self._post_init(g.srid)
else:
# Some coordinate transformations do not have an SRID associated raise GEOSException('Transformed WKB was invalid.')
# with them; only set if one exists.
if g.srid: self.srid = g.srid
#### Topology Routines #### #### Topology Routines ####
def _topology(self, gptr): def _topology(self, gptr):

View File

@ -703,8 +703,15 @@ class GEOSTest(unittest.TestCase):
t2.transform(SpatialReference('EPSG:2774')) t2.transform(SpatialReference('EPSG:2774'))
ct = CoordTransform(SpatialReference('WGS84'), SpatialReference(2774)) ct = CoordTransform(SpatialReference('WGS84'), SpatialReference(2774))
t3.transform(ct) 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 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.x, p.x, prec)
self.assertAlmostEqual(trans.y, p.y, prec) self.assertAlmostEqual(trans.y, p.y, prec)
@ -724,6 +731,27 @@ class GEOSTest(unittest.TestCase):
xmax, ymax = max(x), max(y) xmax, ymax = max(x), max(y)
self.assertEqual((xmin, ymin, xmax, ymax), poly.extent) 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(): def suite():
s = unittest.TestSuite() s = unittest.TestSuite()
s.addTest(unittest.makeSuite(GEOSTest)) s.addTest(unittest.makeSuite(GEOSTest))