From 5d7fd63423e631773880265fab82749189932c0a Mon Sep 17 00:00:00 2001 From: Justin Bronn Date: Sun, 7 Oct 2007 22:42:26 +0000 Subject: [PATCH] gis: geos: Fixed #5630 with patch from rcoup; added the `ogr` and `srs` properties. git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@6465 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/gis/geos/base.py | 28 ++++++++++++++ django/contrib/gis/geos/geometries.py | 3 +- django/contrib/gis/geos/pointer.py | 2 +- django/contrib/gis/tests/test_geos.py | 53 +++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 2 deletions(-) diff --git a/django/contrib/gis/geos/base.py b/django/contrib/gis/geos/base.py index 8efd53dc83..e44a6e7549 100644 --- a/django/contrib/gis/geos/base.py +++ b/django/contrib/gis/geos/base.py @@ -15,6 +15,14 @@ from django.contrib.gis.geos.error import GEOSException, GEOSGeometryIndexError from django.contrib.gis.geos.libgeos import lgeos, HAS_NUMPY, ISQLQuote from django.contrib.gis.geos.pointer import GEOSPointer, NULL_GEOM +# Trying to import GDAL libraries, if available. Have to place in +# try/except since this package may be used outside GeoDjango. +try: + from django.contrib.gis.gdal import OGRGeometry, SpatialReference + HAS_GDAL=True +except: + HAS_GDAL=False + # Regular expression for recognizing HEXEWKB and WKT. A prophylactic measure # to prevent potentially malicious input from reaching the underlying C # library. Not a substitute for good web security programming practices. @@ -435,6 +443,26 @@ class GEOSGeometry(object): gtype = self.geom_type return '<%s>%s' % (gtype, self.coord_seq.kml, gtype) + #### GDAL-specific output routines #### + @property + def ogr(self): + "Returns the OGR Geometry for this Geometry." + if HAS_GDAL: + if self.srid: + return OGRGeometry(self.wkb, self.srid) + else: + return OGRGeometry(self.wkb) + else: + return None + + @property + def srs(self): + "Returns the OSR SpatialReference for SRID of this Geometry." + if HAS_GDAL and self.srid: + return SpatialReference(self.srid) + else: + return None + #### Topology Routines #### def _unary_topology(self, func, *args): """ diff --git a/django/contrib/gis/geos/geometries.py b/django/contrib/gis/geos/geometries.py index cc4bdc58ea..8246513c00 100644 --- a/django/contrib/gis/geos/geometries.py +++ b/django/contrib/gis/geos/geometries.py @@ -53,7 +53,8 @@ class Point(GEOSGeometry): super(Point, self).__init__(lgeos.GEOSGeom_createPoint(cs), srid=srid) def __len__(self): - "Returns the number of dimensions for this Point (either 2 or 3)." + "Returns the number of dimensions for this Point (either 0, 2 or 3)." + if self.empty: return 0 if self.hasz: return 3 else: return 2 diff --git a/django/contrib/gis/geos/pointer.py b/django/contrib/gis/geos/pointer.py index 50c0970d95..58b76207f1 100644 --- a/django/contrib/gis/geos/pointer.py +++ b/django/contrib/gis/geos/pointer.py @@ -186,7 +186,7 @@ class GEOSPointer(object): n_child = len(ptr_list) # Determining whether coordinate sequences pointers were passed in. - if isinstance(ptr_list[0], (tuple, list)): + if n_child and isinstance(ptr_list[0], (tuple, list)): self._child_cs = True else: self._child_cs = False diff --git a/django/contrib/gis/tests/test_geos.py b/django/contrib/gis/tests/test_geos.py index 062da04098..be7de1f981 100644 --- a/django/contrib/gis/tests/test_geos.py +++ b/django/contrib/gis/tests/test_geos.py @@ -4,9 +4,11 @@ from django.contrib.gis.geos import \ GEOSGeometry, Point, LineString, LinearRing, Polygon, \ MultiPoint, MultiLineString, MultiPolygon, GeometryCollection, \ fromstr, HAS_NUMPY +from django.contrib.gis.geos.base import HAS_GDAL from geometries import * if HAS_NUMPY: from numpy import array +if HAS_GDAL: from django.contrib.gis.gdal import OGRGeometry, SpatialReference class GEOSTest(unittest.TestCase): @@ -722,6 +724,57 @@ class GEOSTest(unittest.TestCase): mpoly = MultiPolygon(poly.clone(), poly) self.assertEqual(8.0, mpoly.length) + def test20_emptyCollections(self): + "Testing empty geometries and collections." + gc1 = GeometryCollection([]) + gc2 = fromstr('GEOMETRYCOLLECTION EMPTY') + pnt = fromstr('POINT EMPTY') + ls = fromstr('LINESTRING EMPTY') + poly = fromstr('POLYGON EMPTY') + mls = fromstr('MULTILINESTRING EMPTY') + mpoly1 = fromstr('MULTIPOLYGON EMPTY') + mpoly2 = MultiPolygon(()) + + for g in [gc1, gc2, pnt, ls, poly, mls, mpoly1, mpoly2]: + self.assertEqual(True, g.empty) + + # Testing len() and num_geom. + if isinstance(g, Polygon): + self.assertEqual(1, len(g)) # Has one empty linear ring + self.assertEqual(1, g.num_geom) + self.assertEqual(0, len(g[0])) + elif isinstance(g, (Point, LineString)): + self.assertEqual(1, g.num_geom) + self.assertEqual(0, len(g)) + else: + self.assertEqual(0, g.num_geom) + self.assertEqual(0, len(g)) + + # Testing __getitem__ (doesn't work on Point or Polygon) + if isinstance(g, Point): + self.assertRaises(GEOSGeometryIndexError, g.get_x) + elif isinstance(g, Polygon): + lr = g.shell + self.assertEqual('LINEARRING EMPTY', lr.wkt) + self.assertEqual(0, len(lr)) + self.assertEqual(True, lr.empty) + self.assertRaises(GEOSGeometryIndexError, lr.__getitem__, 0) + else: + self.assertRaises(GEOSGeometryIndexError, g.__getitem__, 0) + + def test21_test_gdal(self): + "Testing `ogr` and `srs` properties." + if not HAS_GDAL: return + g1 = fromstr('POINT(5 23)') + self.assertEqual(True, isinstance(g1.ogr, OGRGeometry)) + self.assertEqual(g1.srs, None) + + g2 = fromstr('LINESTRING(0 0, 5 5, 23 23)', srid=4326) + self.assertEqual(True, isinstance(g2.ogr, OGRGeometry)) + self.assertEqual(True, isinstance(g2.srs, SpatialReference)) + self.assertEqual(g2.hex, g2.ogr.hex) + self.assertEqual('WGS 84', g2.srs.name) + def suite(): s = unittest.TestSuite() s.addTest(unittest.makeSuite(GEOSTest))