diff --git a/django/contrib/gis/gdal/__init__.py b/django/contrib/gis/gdal/__init__.py index 2fc4d4f7e5..e3eddc80ef 100644 --- a/django/contrib/gis/gdal/__init__.py +++ b/django/contrib/gis/gdal/__init__.py @@ -28,10 +28,10 @@ try: from django.contrib.gis.gdal.datasource import DataSource from django.contrib.gis.gdal.libgdal import gdal_version, gdal_full_version, gdal_release_date from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform - from django.contrib.gis.gdal.geometries import OGRGeometry + from django.contrib.gis.gdal.geometries import OGRGeometry, GEOJSON HAS_GDAL = True except: - HAS_GDAL = False + HAS_GDAL, GEOJSON = False, False # The envelope, error, and geomtype modules do not actually require the # GDAL library. diff --git a/django/contrib/gis/gdal/geometries.py b/django/contrib/gis/gdal/geometries.py index 7c01ce10e9..21b8a1a27c 100644 --- a/django/contrib/gis/gdal/geometries.py +++ b/django/contrib/gis/gdal/geometries.py @@ -216,8 +216,14 @@ class OGRGeometry(object): @property def envelope(self): "Returns the envelope for this Geometry." + # TODO: Fix Envelope() for Point geometries. return Envelope(get_envelope(self._ptr, byref(OGREnvelope()))) + @property + def extent(self): + "Returns the envelope as a 4-tuple, instead of as an Envelope object." + return self.envelope.tuple + #### SpatialReference-related Properties #### # The SRS property @@ -446,7 +452,8 @@ class Point(OGRGeometry): @property def z(self): "Returns the Z coordinate for this Point." - return getz(self._ptr, 0) + if self.coord_dim == 3: + return getz(self._ptr, 0) @property def tuple(self): @@ -455,6 +462,7 @@ class Point(OGRGeometry): return (self.x, self.y) elif self.coord_dim == 3: return (self.x, self.y, self.z) + coords = tuple class LineString(OGRGeometry): @@ -485,7 +493,31 @@ class LineString(OGRGeometry): @property def tuple(self): "Returns the tuple representation of this LineString." - return tuple(self[i] for i in xrange(len(self))) + return tuple([self[i] for i in xrange(len(self))]) + coords = tuple + + def _listarr(self, func): + """ + Internal routine that returns a sequence (list) corresponding with + the given function. + """ + return [func(self._ptr, i) for i in xrange(len(self))] + + @property + def x(self): + "Returns the X coordinates in a list." + return self._listarr(getx) + + @property + def y(self): + "Returns the Y coordinates in a list." + return self._listarr(gety) + + @property + def z(self): + "Returns the Z coordinates in a list." + if self.coord_dim == 3: + return self._listarr(getz) # LinearRings are used in Polygons. class LinearRing(LineString): pass @@ -513,11 +545,13 @@ class Polygon(OGRGeometry): def shell(self): "Returns the shell of this Polygon." return self[0] # First ring is the shell + exterior_ring = shell @property def tuple(self): "Returns a tuple of LinearRing coordinate tuples." - return tuple(self[i].tuple for i in xrange(self.geom_count)) + return tuple([self[i].tuple for i in xrange(self.geom_count)]) + coords = tuple @property def point_count(self): @@ -575,7 +609,8 @@ class GeometryCollection(OGRGeometry): @property def tuple(self): "Returns a tuple representation of this Geometry Collection." - return tuple(self[i].tuple for i in xrange(self.geom_count)) + return tuple([self[i].tuple for i in xrange(self.geom_count)]) + coords = tuple # Multiple Geometry types. class MultiPoint(GeometryCollection): pass diff --git a/django/contrib/gis/gdal/prototypes/geom.py b/django/contrib/gis/gdal/prototypes/geom.py index 6ec55ec938..8a9b9ca82d 100644 --- a/django/contrib/gis/gdal/prototypes/geom.py +++ b/django/contrib/gis/gdal/prototypes/geom.py @@ -8,8 +8,8 @@ from django.contrib.gis.gdal.prototypes.generation import \ srs_output, string_output, void_output # Some prototypes need to be aware of what version GDAL we have. -major, minor1, minor2 = map(int, gdal_version().split('.')) -if major <= 1 and minor1 <= 4: +major, minor = map(int, gdal_version().split('.')[:2]) +if major <= 1 and minor <= 4: GEOJSON = False else: GEOJSON = True diff --git a/django/contrib/gis/tests/test_gdal_geom.py b/django/contrib/gis/tests/test_gdal_geom.py index 9e52a7ce57..093ed31093 100644 --- a/django/contrib/gis/tests/test_gdal_geom.py +++ b/django/contrib/gis/tests/test_gdal_geom.py @@ -117,6 +117,12 @@ class OGRGeomTest(unittest.TestCase): self.assertRaises(OGRIndexError, linestr.__getitem__, len(linestr)) prev = linestr + # Testing the x, y properties. + x = [tmpx for tmpx, tmpy in ls.tup] + y = [tmpy for tmpx, tmpy in ls.tup] + self.assertEqual(x, linestr.x) + self.assertEqual(y, linestr.y) + def test05_multilinestring(self): "Testing MultiLineString objects." prev = OGRGeometry('POINT(0 0)') @@ -354,6 +360,19 @@ class OGRGeomTest(unittest.TestCase): mp3.add(mpoly) # Adding a MultiPolygon's entire contents at once. for tmp in (mp1, mp2, mp3): self.assertEqual(mpoly, tmp) + def test15_extent(self): + "Testing `extent` property." + # The xmin, ymin, xmax, ymax of the MultiPoint should be returned. + mp = OGRGeometry('MULTIPOINT(5 23, 0 0, 10 50)') + self.assertEqual((0.0, 0.0, 10.0, 50.0), mp.extent) + # Testing on the 'real world' Polygon. + poly = OGRGeometry(polygons[3].wkt) + ring = poly.shell + x, y = ring.x, ring.y + xmin, ymin = min(x), min(y) + xmax, ymax = max(x), max(y) + self.assertEqual((xmin, ymin, xmax, ymax), poly.extent) + def suite(): s = unittest.TestSuite() s.addTest(unittest.makeSuite(OGRGeomTest))