Author: jbronn Date: 2009-10-17 12:32:25 -0500 (Sat, 17 Oct 2009) New Revision: 11628
Modified: django/trunk/django/contrib/gis/gdal/geometries.py django/trunk/django/contrib/gis/gdal/prototypes/geom.py django/trunk/django/contrib/gis/gdal/tests/test_geom.py Log: The `OGRGeometry.coord_dim` property may now be set; implemented a work-around for an OGR bug that changed geometries to 3D after transformation. Refs #11433. Modified: django/trunk/django/contrib/gis/gdal/geometries.py =================================================================== --- django/trunk/django/contrib/gis/gdal/geometries.py 2009-10-15 20:25:20 UTC (rev 11627) +++ django/trunk/django/contrib/gis/gdal/geometries.py 2009-10-17 17:32:25 UTC (rev 11628) @@ -29,7 +29,7 @@ +proj=longlat +ellps=clrk66 +datum=NAD27 +no_defs >>> print mpnt MULTIPOINT (-89.999930378602485 29.999797886557641,-89.999930378602485 29.999797886557641) - + The OGRGeomType class is to make it easy to specify an OGR geometry type: >>> from django.contrib.gis.gdal import OGRGeomType >>> gt1 = OGRGeomType(3) # Using an integer for the type @@ -78,7 +78,7 @@ geom_input = buffer(a2b_hex(geom_input.upper())) str_instance = False - # Constructing the geometry, + # Constructing the geometry, if str_instance: # Checking if unicode if isinstance(geom_input, unicode): @@ -130,12 +130,12 @@ self.__class__ = GEO_CLASSES[self.geom_type.num] @classmethod - def from_bbox(cls, bbox): + def from_bbox(cls, bbox): "Constructs a Polygon from a bounding box (4-tuple)." x0, y0, x1, y1 = bbox return OGRGeometry( 'POLYGON((%s %s, %s %s, %s %s, %s %s, %s %s))' % ( x0, y0, x0, y1, x1, y1, x1, y0, x0, y0) ) - + def __del__(self): "Deletes this Geometry." if self._ptr: capi.destroy_geom(self._ptr) @@ -179,11 +179,18 @@ "Returns 0 for points, 1 for lines, and 2 for surfaces." return capi.get_dims(self.ptr) - @property - def coord_dim(self): + def _get_coord_dim(self): "Returns the coordinate dimension of the Geometry." - return capi.get_coord_dims(self.ptr) + return capi.get_coord_dim(self.ptr) + def _set_coord_dim(self, dim): + "Sets the coordinate dimension of this Geometry." + if not dim in (2, 3): + raise ValueError('Geometry dimension must be either 2 or 3') + capi.set_coord_dim(self.ptr, dim) + + coord_dim = property(_get_coord_dim, _set_coord_dim) + @property def geom_count(self): "The number of elements in this Geometry." @@ -237,7 +244,7 @@ return self.envelope.tuple #### SpatialReference-related Properties #### - + # The SRS property def _get_srs(self): "Returns the Spatial Reference for this Geometry." @@ -298,7 +305,7 @@ Returns the GeoJSON representation of this Geometry (requires GDAL 1.5+). """ - if GEOJSON: + if GEOJSON: return capi.to_json(self.ptr) else: raise NotImplementedError('GeoJSON output only supported on GDAL 1.5+.') @@ -335,7 +342,7 @@ def wkt(self): "Returns the WKT representation of the Geometry." return capi.to_wkt(self.ptr, byref(c_char_p())) - + #### Geometry Methods #### def clone(self): "Clones this OGR Geometry." @@ -363,6 +370,16 @@ klone = self.clone() klone.transform(coord_trans) return klone + + # Have to get the coordinate dimension of the original geometry + # so it can be used to reset the transformed geometry's dimension + # 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 + + # Depending on the input type, use the appropriate OGR routine + # to perform the transformation. if isinstance(coord_trans, CoordTransform): capi.geom_transform(self.ptr, coord_trans.ptr) elif isinstance(coord_trans, SpatialReference): @@ -373,6 +390,10 @@ else: 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 + def transform_to(self, srs): "For backwards-compatibility." self.transform(srs) @@ -391,7 +412,7 @@ def intersects(self, other): "Returns True if this geometry intersects with the other." return self._topology(capi.ogr_intersects, other) - + def equals(self, other): "Returns True if this geometry is equivalent to the other." return self._topology(capi.ogr_equals, other) @@ -436,7 +457,7 @@ @property def convex_hull(self): """ - Returns the smallest convex Polygon that contains all the points in + Returns the smallest convex Polygon that contains all the points in this Geometry. """ return self._geomgen(capi.geom_convex_hull) @@ -456,7 +477,7 @@ return self._geomgen(capi.geom_intersection, other) def sym_difference(self, other): - """ + """ Returns a new geometry which is the symmetric difference of this geometry and the other. """ @@ -545,7 +566,7 @@ def y(self): "Returns the Y coordinates in a list." return self._listarr(capi.gety) - + @property def z(self): "Returns the Z coordinates in a list." @@ -610,7 +631,7 @@ raise OGRIndexError('index out of range: %s' % index) else: return OGRGeometry(capi.clone_geom(capi.get_geom_ref(self.ptr, index)), self.srs) - + def __iter__(self): "Iterates over each Geometry." for i in xrange(self.geom_count): @@ -658,5 +679,5 @@ 5 : MultiLineString, 6 : MultiPolygon, 7 : GeometryCollection, - 101: LinearRing, + 101: LinearRing, } Modified: django/trunk/django/contrib/gis/gdal/prototypes/geom.py =================================================================== --- django/trunk/django/contrib/gis/gdal/prototypes/geom.py 2009-10-15 20:25:20 UTC (rev 11627) +++ django/trunk/django/contrib/gis/gdal/prototypes/geom.py 2009-10-17 17:32:25 UTC (rev 11628) @@ -83,7 +83,8 @@ get_area = double_output(lgdal.OGR_G_GetArea, [c_void_p]) get_centroid = void_output(lgdal.OGR_G_Centroid, [c_void_p, c_void_p]) get_dims = int_output(lgdal.OGR_G_GetDimension, [c_void_p]) -get_coord_dims = int_output(lgdal.OGR_G_GetCoordinateDimension, [c_void_p]) +get_coord_dim = int_output(lgdal.OGR_G_GetCoordinateDimension, [c_void_p]) +set_coord_dim = void_output(lgdal.OGR_G_SetCoordinateDimension, [c_void_p, c_int], errcheck=False) get_geom_count = int_output(lgdal.OGR_G_GetGeometryCount, [c_void_p]) get_geom_name = const_string_output(lgdal.OGR_G_GetGeometryName, [c_void_p]) Modified: django/trunk/django/contrib/gis/gdal/tests/test_geom.py =================================================================== --- django/trunk/django/contrib/gis/gdal/tests/test_geom.py 2009-10-15 20:25:20 UTC (rev 11627) +++ django/trunk/django/contrib/gis/gdal/tests/test_geom.py 2009-10-17 17:32:25 UTC (rev 11628) @@ -319,6 +319,18 @@ self.assertAlmostEqual(trans.x, p.x, prec) self.assertAlmostEqual(trans.y, p.y, prec) + def test09c_transform_dim(self): + "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. + self.assertEqual(2, ls_orig.coord_dim) + self.assertAlmostEqual(ls_trans.x[0], ls_orig.x[0], prec) + self.assertAlmostEqual(ls_trans.y[0], ls_orig.y[0], prec) + def test10_difference(self): "Testing difference()." for i in xrange(len(topology_geoms)): --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django updates" group. To post to this group, send email to django-updates@googlegroups.com To unsubscribe from this group, send email to django-updates+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-updates?hl=en -~----------~----~----~----~------~----~------~--~---