Commit ceb52612 authored by Justin Bronn's avatar Justin Bronn
Browse files

[1.1.X] Fixed #12312 -- Set the coordinate dimension on each component of...

[1.1.X] Fixed #12312 -- Set the coordinate dimension on each component of geometry collections after transform (refines GDAL bug workaround introduced in r11629).  Thanks, yourcelf for bug report.

Backport of r12878 from trunk.


git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.1.X@12879 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent e53de431
Loading
Loading
Loading
Loading
+17 −5
Original line number Diff line number Diff line
@@ -48,11 +48,11 @@ from django.contrib.gis.gdal.base import GDALBase
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 more information, see the OGR C API source code:
#  http://www.gdal.org/ogr/ogr__api_8h.html
@@ -374,6 +374,7 @@ class OGRGeometry(GDALBase):
        # 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
        if GDAL_VERSION < (1, 7):
            orig_dim = self.coord_dim

        # Depending on the input type, use the appropriate OGR routine
@@ -386,9 +387,20 @@ class OGRGeometry(GDALBase):
            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 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

+35 −10
Original line number Diff line number Diff line
@@ -436,6 +436,31 @@ class OGRGeomTest(unittest.TestCase):
        self.assertEqual([1.0, 2.0, 3.0], ls_25d.z)
        self.assertEqual(3, ls_25d.coord_dim)

    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))