Author: jbronn
Date: 2010-03-29 12:33:59 -0500 (Mon, 29 Mar 2010)
New Revision: 12878

Modified:
   django/trunk/django/contrib/gis/gdal/geometries.py
   django/trunk/django/contrib/gis/gdal/tests/test_geom.py
Log:
Fixed #12312 -- Set the coordinate dimension on each component of geometry 
collections after transform (refines GDAL bug workaround introduced in r11628). 
 Thanks, yourcelf for bug report.


Modified: django/trunk/django/contrib/gis/gdal/geometries.py
===================================================================
--- django/trunk/django/contrib/gis/gdal/geometries.py  2010-03-29 16:48:38 UTC 
(rev 12877)
+++ django/trunk/django/contrib/gis/gdal/geometries.py  2010-03-29 17:33:59 UTC 
(rev 12878)
@@ -48,11 +48,11 @@
 from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope
 from django.contrib.gis.gdal.error import OGRException, OGRIndexError, 
SRSException
 from django.contrib.gis.gdal.geomtype import OGRGeomType
+from django.contrib.gis.gdal.libgdal import GEOJSON, GDAL_VERSION
 from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform
 
 # Getting the ctypes prototype functions that interface w/the GDAL C library.
 from django.contrib.gis.gdal.prototypes import geom as capi, srs as srs_api
-GEOJSON = capi.GEOJSON
 
 # For recognizing geometry input.
 from django.contrib.gis.geometry.regex import hex_regex, wkt_regex, json_regex
@@ -400,7 +400,8 @@
         # afterwards.  This is done because of GDAL bug (in versions prior
         # to 1.7) that turns geometries 3D after transformation, see:
         #  http://trac.osgeo.org/gdal/changeset/17792
-        orig_dim = self.coord_dim
+        if GDAL_VERSION < (1, 7):
+            orig_dim = self.coord_dim
 
         # Depending on the input type, use the appropriate OGR routine
         # to perform the transformation.
@@ -412,11 +413,22 @@
             sr = SpatialReference(coord_trans)
             capi.geom_transform_to(self.ptr, sr.ptr)
         else:
-            raise TypeError('Transform only accepts CoordTransform, 
SpatialReference, string, and integer objects.')
+            raise TypeError('Transform only accepts CoordTransform, '
+                            'SpatialReference, string, and integer objects.')
 
         # Setting with original dimension, see comment above.
-        if self.coord_dim != orig_dim:
-            self.coord_dim = orig_dim
+        if GDAL_VERSION < (1, 7):
+            if isinstance(self, GeometryCollection):
+                # With geometry collections have to set dimension on
+                # each internal geometry reference, as the collection
+                # dimension isn't affected.
+                for i in xrange(len(self)):
+                    internal_ptr = capi.get_geom_ref(self.ptr, i)
+                    if orig_dim != capi.get_coord_dim(internal_ptr):
+                        capi.set_coord_dim(internal_ptr, orig_dim)
+            else:
+                if self.coord_dim != orig_dim:
+                    self.coord_dim = orig_dim
 
     def transform_to(self, srs):
         "For backwards-compatibility."

Modified: django/trunk/django/contrib/gis/gdal/tests/test_geom.py
===================================================================
--- django/trunk/django/contrib/gis/gdal/tests/test_geom.py     2010-03-29 
16:48:38 UTC (rev 12877)
+++ django/trunk/django/contrib/gis/gdal/tests/test_geom.py     2010-03-29 
17:33:59 UTC (rev 12878)
@@ -136,7 +136,7 @@
             self.assertEqual(mgeom1, mgeom3)
             self.assertEqual(mp.points, mgeom2.tuple)
             self.assertEqual(mp.n_p, mgeom2.point_count)
-                                                                            
+
     def test04_linestring(self):
         "Testing LineString objects."
         prev = OGRGeometry('POINT(0 0)')
@@ -172,7 +172,7 @@
             for ls in mlinestr:
                 self.assertEqual(2, ls.geom_type)
                 self.assertEqual('LINESTRING', ls.geom_name)
-            self.assertRaises(OGRIndexError, mlinestr.__getitem__, 
len(mlinestr)) 
+            self.assertRaises(OGRIndexError, mlinestr.__getitem__, 
len(mlinestr))
 
     def test06_linearring(self):
         "Testing LinearRing objects."
@@ -190,7 +190,7 @@
         "Testing Polygon objects."
 
         # Testing `from_bbox` class method
-        bbox =  (-180,-90,180,90) 
+        bbox =  (-180,-90,180,90)
         p = OGRGeometry.from_bbox( bbox )
         self.assertEqual(bbox, p.extent)
 
@@ -211,13 +211,13 @@
             # Testing equivalence
             self.assertEqual(True, poly == OGRGeometry(p.wkt))
             self.assertEqual(True, poly != prev)
-            
+
             if p.ext_ring_cs:
                 ring = poly[0]
                 self.assertEqual(p.ext_ring_cs, ring.tuple)
                 self.assertEqual(p.ext_ring_cs, poly[0].tuple)
                 self.assertEqual(len(p.ext_ring_cs), ring.point_count)
-            
+
             for r in poly:
                 self.assertEqual('LINEARRING', r.geom_name)
 
@@ -269,11 +269,11 @@
             sr = SpatialReference('WGS84')
             mpoly = OGRGeometry(mp.wkt, sr)
             self.assertEqual(sr.wkt, mpoly.srs.wkt)
-          
+
             # Ensuring that SRS is propagated to clones.
             klone = mpoly.clone()
             self.assertEqual(sr.wkt, klone.srs.wkt)
-  
+
             # Ensuring all children geometries (polygons and their rings) all
             # return the assigned spatial reference as well.
             for poly in mpoly:
@@ -295,7 +295,7 @@
             mpoly.srs = SpatialReference(4269)
             self.assertEqual(4269, mpoly.srid)
             self.assertEqual('NAD83', mpoly.srs.name)
-          
+
             # Incrementing through the multipolyogn after the spatial reference
             # has been re-assigned.
             for poly in mpoly:
@@ -341,7 +341,7 @@
         "Testing coordinate dimension is the same on transformed geometries."
         ls_orig = OGRGeometry('LINESTRING(-104.609 38.255)', 4326)
         ls_trans = OGRGeometry('LINESTRING(992385.4472045 481455.4944650)', 
2774)
-        
+
         prec = 3
         ls_orig.transform(ls_trans.srs)
         # Making sure the coordinate dimension is still 2D.
@@ -388,7 +388,7 @@
             self.assertEqual(d1, a ^ b) # __xor__ is symmetric difference 
operator
             a ^= b # testing __ixor__
             self.assertEqual(d1, a)
-            
+
     def test13_union(self):
         "Testing union()."
         for i in xrange(len(topology_geoms)):
@@ -455,8 +455,32 @@
         self.assertEqual(g1, g2)
         self.assertEqual(4326, g2.srs.srid)
         self.assertEqual(g1.srs.wkt, g2.srs.wkt)
-        
 
+    def test18_ogrgeometry_transform_workaround(self):
+        "Testing coordinate dimensions on geometries after transformation."
+        # A bug in GDAL versions prior to 1.7 changes the coordinate
+        # dimension of a geometry after it has been transformed.
+        # This test ensures that the bug workarounds employed within
+        # `OGRGeometry.transform` indeed work.
+        wkt_2d = "MULTILINESTRING ((0 0,1 1,2 2))"
+        wkt_3d = "MULTILINESTRING ((0 0 0,1 1 1,2 2 2))"
+        srid = 4326
+
+        # For both the 2D and 3D MultiLineString, ensure _both_ the dimension
+        # of the collection and the component LineString have the expected
+        # coordinate dimension after transform.
+        geom = OGRGeometry(wkt_2d, srid)
+        geom.transform(srid)
+        self.assertEqual(2, geom.coord_dim)
+        self.assertEqual(2, geom[0].coord_dim)
+        self.assertEqual(wkt_2d, geom.wkt)
+
+        geom = OGRGeometry(wkt_3d, srid)
+        geom.transform(srid)
+        self.assertEqual(3, geom.coord_dim)
+        self.assertEqual(3, geom[0].coord_dim)
+        self.assertEqual(wkt_3d, geom.wkt)
+
 def suite():
     s = unittest.TestSuite()
     s.addTest(unittest.makeSuite(OGRGeomTest))

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to