Author: jbronn
Date: 2009-11-09 19:54:35 -0600 (Mon, 09 Nov 2009)
New Revision: 11727

Modified:
   django/trunk/django/contrib/gis/gdal/layer.py
   django/trunk/django/contrib/gis/gdal/prototypes/ds.py
   django/trunk/django/contrib/gis/gdal/tests/test_ds.py
Log:
Added support for spatially filtering what OGR features are returned in 
iteration via the `Layer.spatial_filter` property.


Modified: django/trunk/django/contrib/gis/gdal/layer.py
===================================================================
--- django/trunk/django/contrib/gis/gdal/layer.py       2009-11-08 00:51:42 UTC 
(rev 11726)
+++ django/trunk/django/contrib/gis/gdal/layer.py       2009-11-10 01:54:35 UTC 
(rev 11727)
@@ -1,5 +1,5 @@
 # Needed ctypes routines
-from ctypes import byref
+from ctypes import c_double, byref
 
 # Other GDAL imports.
 from django.contrib.gis.gdal.base import GDALBase
@@ -7,11 +7,12 @@
 from django.contrib.gis.gdal.error import OGRException, OGRIndexError, 
SRSException
 from django.contrib.gis.gdal.feature import Feature
 from django.contrib.gis.gdal.field import OGRFieldTypes
-from django.contrib.gis.gdal.geometries import OGRGeomType
+from django.contrib.gis.gdal.geomtype import OGRGeomType
+from django.contrib.gis.gdal.geometries import OGRGeometry
 from django.contrib.gis.gdal.srs import SpatialReference
 
 # GDAL ctypes function prototypes.
-from django.contrib.gis.gdal.prototypes import ds as capi, srs as srs_api
+from django.contrib.gis.gdal.prototypes import ds as capi, geom as geom_api, 
srs as srs_api
 
 # For more information, see the OGR C API source code:
 #  http://www.gdal.org/ogr/ogr__api_8h.html
@@ -156,6 +157,29 @@
         return [capi.get_field_precision(capi.get_field_defn(self._ldefn, i))
                 for i in xrange(self.num_fields)]
 
+    def _get_spatial_filter(self):
+        try:
+            return 
OGRGeometry(geom_api.clone_geom(capi.get_spatial_filter(self.ptr)))
+        except OGRException:
+            return None
+
+    def _set_spatial_filter(self, filter):
+        if isinstance(filter, OGRGeometry):
+            capi.set_spatial_filter(self.ptr, filter.ptr)
+        elif isinstance(filter, (tuple, list)):
+            if not len(filter) == 4:
+                raise ValueError('Spatial filter list/tuple must have 4 
elements.')
+            # Map c_double onto params -- if a bad type is passed in it
+            # will be caught here.
+            xmin, ymin, xmax, ymax = map(c_double, filter)
+            capi.set_spatial_filter_rect(self.ptr, xmin, ymin, xmax, ymax)
+        elif filter is None:
+            capi.set_spatial_filter(self.ptr, None)
+        else:
+            raise TypeError('Spatial filter must be either an OGRGeometry 
instance, a 4-tuple, or None.')
+
+    spatial_filter = property(_get_spatial_filter, _set_spatial_filter)
+
     #### Layer Methods ####
     def get_fields(self, field_name):
         """

Modified: django/trunk/django/contrib/gis/gdal/prototypes/ds.py
===================================================================
--- django/trunk/django/contrib/gis/gdal/prototypes/ds.py       2009-11-08 
00:51:42 UTC (rev 11726)
+++ django/trunk/django/contrib/gis/gdal/prototypes/ds.py       2009-11-10 
01:54:35 UTC (rev 11727)
@@ -3,7 +3,7 @@
  related data structures. OGR_Dr_*, OGR_DS_*, OGR_L_*, OGR_F_*, 
  OGR_Fld_* routines are relevant here.
 """
-from ctypes import c_char_p, c_int, c_long, c_void_p, POINTER
+from ctypes import c_char_p, c_double, c_int, c_long, c_void_p, POINTER
 from django.contrib.gis.gdal.envelope import OGREnvelope
 from django.contrib.gis.gdal.libgdal import lgdal
 from django.contrib.gis.gdal.prototypes.generation import \
@@ -38,6 +38,9 @@
 get_next_feature = voidptr_output(lgdal.OGR_L_GetNextFeature, [c_void_p])
 reset_reading = void_output(lgdal.OGR_L_ResetReading, [c_void_p], 
errcheck=False)
 test_capability = int_output(lgdal.OGR_L_TestCapability, [c_void_p, c_char_p])
+get_spatial_filter = geom_output(lgdal.OGR_L_GetSpatialFilter, [c_void_p])
+set_spatial_filter = void_output(lgdal.OGR_L_SetSpatialFilter, [c_void_p, 
c_void_p], errcheck=False)
+set_spatial_filter_rect = void_output(lgdal.OGR_L_SetSpatialFilterRect, 
[c_void_p, c_double, c_double, c_double, c_double], errcheck=False)
 
 ### Feature Definition Routines ###
 get_fd_geom_type = int_output(lgdal.OGR_FD_GetGeomType, [c_void_p])

Modified: django/trunk/django/contrib/gis/gdal/tests/test_ds.py
===================================================================
--- django/trunk/django/contrib/gis/gdal/tests/test_ds.py       2009-11-08 
00:51:42 UTC (rev 11726)
+++ django/trunk/django/contrib/gis/gdal/tests/test_ds.py       2009-11-10 
01:54:35 UTC (rev 11727)
@@ -1,13 +1,11 @@
 import os, os.path, unittest
-from django.contrib.gis.gdal import DataSource, Envelope, OGRException, 
OGRIndexError
+from django.contrib.gis.gdal import DataSource, Envelope, OGRGeometry, 
OGRException, OGRIndexError
 from django.contrib.gis.gdal.field import OFTReal, OFTInteger, OFTString
 from django.contrib import gis
 
 # Path for SHP files
 data_path = os.path.join(os.path.dirname(gis.__file__), 'tests' + os.sep + 
'data')
 def get_ds_file(name, ext):
-    
-
     return os.sep.join([data_path, name, name + '.%s' % ext])
 
 # Test SHP data source object
@@ -191,7 +189,41 @@
                     if hasattr(source, 'srs_wkt'):
                         self.assertEqual(source.srs_wkt, g.srs.wkt)
 
+    def test06_spatial_filter(self):
+        "Testing the Layer.spatial_filter property."
+        ds = DataSource(get_ds_file('cities', 'shp'))
+        lyr = ds[0]
 
+        # When not set, it should be None.
+        self.assertEqual(None, lyr.spatial_filter)
+
+        # Must be set a/an OGRGeometry or 4-tuple.
+        self.assertRaises(TypeError, lyr._set_spatial_filter, 'foo')
+
+        # Setting the spatial filter with a tuple/list with the extent of
+        # a buffer centering around Pueblo.
+        self.assertRaises(ValueError, lyr._set_spatial_filter, range(5))
+        filter_extent = (-105.609252, 37.255001, -103.609252, 39.255001)
+        lyr.spatial_filter = (-105.609252, 37.255001, -103.609252, 39.255001)
+        self.assertEqual(OGRGeometry.from_bbox(filter_extent), 
lyr.spatial_filter)
+        feats = [feat for feat in lyr]
+        self.assertEqual(1, len(feats))
+        self.assertEqual('Pueblo', feats[0].get('Name'))
+
+        # Setting the spatial filter with an OGRGeometry for buffer centering
+        # around Houston.
+        filter_geom = OGRGeometry('POLYGON((-96.363151 28.763374,-94.363151 
28.763374,-94.363151 30.763374,-96.363151 30.763374,-96.363151 28.763374))')
+        lyr.spatial_filter = filter_geom
+        self.assertEqual(filter_geom, lyr.spatial_filter)
+        feats = [feat for feat in lyr]
+        self.assertEqual(1, len(feats))
+        self.assertEqual('Houston', feats[0].get('Name'))
+
+        # Clearing the spatial filter by setting it to None.  Now
+        # should indicate that there are 3 features in the Layer.
+        lyr.spatial_filter = None
+        self.assertEqual(3, len(lyr))
+        
 def suite():
     s = unittest.TestSuite()
     s.addTest(unittest.makeSuite(DataSourceTest))


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

Reply via email to