Skip to content

Commit ceb5261

Browse files
committed
[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
1 parent e53de43 commit ceb5261

File tree

2 files changed

+52
-15
lines changed

2 files changed

+52
-15
lines changed

django/contrib/gis/gdal/geometries.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@
4848
from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope
4949
from django.contrib.gis.gdal.error import OGRException, OGRIndexError, SRSException
5050
from django.contrib.gis.gdal.geomtype import OGRGeomType
51+
from django.contrib.gis.gdal.libgdal import GEOJSON, GDAL_VERSION
5152
from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform
5253

5354
# Getting the ctypes prototype functions that interface w/the GDAL C library.
5455
from django.contrib.gis.gdal.prototypes import geom as capi, srs as srs_api
55-
GEOJSON = capi.GEOJSON
5656

5757
# For more information, see the OGR C API source code:
5858
# http://www.gdal.org/ogr/ogr__api_8h.html
@@ -374,7 +374,8 @@ def transform(self, coord_trans, clone=False):
374374
# afterwards. This is done because of GDAL bug (in versions prior
375375
# to 1.7) that turns geometries 3D after transformation, see:
376376
# http://trac.osgeo.org/gdal/changeset/17792
377-
orig_dim = self.coord_dim
377+
if GDAL_VERSION < (1, 7):
378+
orig_dim = self.coord_dim
378379

379380
# Depending on the input type, use the appropriate OGR routine
380381
# to perform the transformation.
@@ -386,11 +387,22 @@ def transform(self, coord_trans, clone=False):
386387
sr = SpatialReference(coord_trans)
387388
capi.geom_transform_to(self.ptr, sr.ptr)
388389
else:
389-
raise TypeError('Transform only accepts CoordTransform, SpatialReference, string, and integer objects.')
390+
raise TypeError('Transform only accepts CoordTransform, '
391+
'SpatialReference, string, and integer objects.')
390392

391393
# Setting with original dimension, see comment above.
392-
if self.coord_dim != orig_dim:
393-
self.coord_dim = orig_dim
394+
if GDAL_VERSION < (1, 7):
395+
if isinstance(self, GeometryCollection):
396+
# With geometry collections have to set dimension on
397+
# each internal geometry reference, as the collection
398+
# dimension isn't affected.
399+
for i in xrange(len(self)):
400+
internal_ptr = capi.get_geom_ref(self.ptr, i)
401+
if orig_dim != capi.get_coord_dim(internal_ptr):
402+
capi.set_coord_dim(internal_ptr, orig_dim)
403+
else:
404+
if self.coord_dim != orig_dim:
405+
self.coord_dim = orig_dim
394406

395407
def transform_to(self, srs):
396408
"For backwards-compatibility."

django/contrib/gis/gdal/tests/test_geom.py

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ def test03_multipoints(self):
125125
self.assertEqual(mgeom1, mgeom3)
126126
self.assertEqual(mp.points, mgeom2.tuple)
127127
self.assertEqual(mp.n_p, mgeom2.point_count)
128-
128+
129129
def test04_linestring(self):
130130
"Testing LineString objects."
131131
prev = OGRGeometry('POINT(0 0)')
@@ -161,7 +161,7 @@ def test05_multilinestring(self):
161161
for ls in mlinestr:
162162
self.assertEqual(2, ls.geom_type)
163163
self.assertEqual('LINESTRING', ls.geom_name)
164-
self.assertRaises(OGRIndexError, mlinestr.__getitem__, len(mlinestr))
164+
self.assertRaises(OGRIndexError, mlinestr.__getitem__, len(mlinestr))
165165

166166
def test06_linearring(self):
167167
"Testing LinearRing objects."
@@ -179,7 +179,7 @@ def test07a_polygons(self):
179179
"Testing Polygon objects."
180180

181181
# Testing `from_bbox` class method
182-
bbox = (-180,-90,180,90)
182+
bbox = (-180,-90,180,90)
183183
p = OGRGeometry.from_bbox( bbox )
184184
self.assertEqual(bbox, p.extent)
185185

@@ -200,13 +200,13 @@ def test07a_polygons(self):
200200
# Testing equivalence
201201
self.assertEqual(True, poly == OGRGeometry(p.wkt))
202202
self.assertEqual(True, poly != prev)
203-
203+
204204
if p.ext_ring_cs:
205205
ring = poly[0]
206206
self.assertEqual(p.ext_ring_cs, ring.tuple)
207207
self.assertEqual(p.ext_ring_cs, poly[0].tuple)
208208
self.assertEqual(len(p.ext_ring_cs), ring.point_count)
209-
209+
210210
for r in poly:
211211
self.assertEqual('LINEARRING', r.geom_name)
212212

@@ -258,11 +258,11 @@ def test09a_srs(self):
258258
sr = SpatialReference('WGS84')
259259
mpoly = OGRGeometry(mp.wkt, sr)
260260
self.assertEqual(sr.wkt, mpoly.srs.wkt)
261-
261+
262262
# Ensuring that SRS is propagated to clones.
263263
klone = mpoly.clone()
264264
self.assertEqual(sr.wkt, klone.srs.wkt)
265-
265+
266266
# Ensuring all children geometries (polygons and their rings) all
267267
# return the assigned spatial reference as well.
268268
for poly in mpoly:
@@ -284,7 +284,7 @@ def test09a_srs(self):
284284
mpoly.srs = SpatialReference(4269)
285285
self.assertEqual(4269, mpoly.srid)
286286
self.assertEqual('NAD83', mpoly.srs.name)
287-
287+
288288
# Incrementing through the multipolyogn after the spatial reference
289289
# has been re-assigned.
290290
for poly in mpoly:
@@ -330,7 +330,7 @@ def test09c_transform_dim(self):
330330
"Testing coordinate dimension is the same on transformed geometries."
331331
ls_orig = OGRGeometry('LINESTRING(-104.609 38.255)', 4326)
332332
ls_trans = OGRGeometry('LINESTRING(992385.4472045 481455.4944650)', 2774)
333-
333+
334334
prec = 3
335335
ls_orig.transform(ls_trans.srs)
336336
# Making sure the coordinate dimension is still 2D.
@@ -377,7 +377,7 @@ def test12_symdifference(self):
377377
self.assertEqual(d1, a ^ b) # __xor__ is symmetric difference operator
378378
a ^= b # testing __ixor__
379379
self.assertEqual(d1, a)
380-
380+
381381
def test13_union(self):
382382
"Testing union()."
383383
for i in xrange(len(topology_geoms)):
@@ -436,6 +436,31 @@ def test16_25D(self):
436436
self.assertEqual([1.0, 2.0, 3.0], ls_25d.z)
437437
self.assertEqual(3, ls_25d.coord_dim)
438438

439+
def test18_ogrgeometry_transform_workaround(self):
440+
"Testing coordinate dimensions on geometries after transformation."
441+
# A bug in GDAL versions prior to 1.7 changes the coordinate
442+
# dimension of a geometry after it has been transformed.
443+
# This test ensures that the bug workarounds employed within
444+
# `OGRGeometry.transform` indeed work.
445+
wkt_2d = "MULTILINESTRING ((0 0,1 1,2 2))"
446+
wkt_3d = "MULTILINESTRING ((0 0 0,1 1 1,2 2 2))"
447+
srid = 4326
448+
449+
# For both the 2D and 3D MultiLineString, ensure _both_ the dimension
450+
# of the collection and the component LineString have the expected
451+
# coordinate dimension after transform.
452+
geom = OGRGeometry(wkt_2d, srid)
453+
geom.transform(srid)
454+
self.assertEqual(2, geom.coord_dim)
455+
self.assertEqual(2, geom[0].coord_dim)
456+
self.assertEqual(wkt_2d, geom.wkt)
457+
458+
geom = OGRGeometry(wkt_3d, srid)
459+
geom.transform(srid)
460+
self.assertEqual(3, geom.coord_dim)
461+
self.assertEqual(3, geom[0].coord_dim)
462+
self.assertEqual(wkt_3d, geom.wkt)
463+
439464
def suite():
440465
s = unittest.TestSuite()
441466
s.addTest(unittest.makeSuite(OGRGeomTest))

0 commit comments

Comments
 (0)