app/django/contrib/gis/gdal/datasource.py
changeset 323 ff1a9aa48cfd
equal deleted inserted replaced
322:6641e941ef1e 323:ff1a9aa48cfd
       
     1 """
       
     2  DataSource is a wrapper for the OGR Data Source object, which provides
       
     3  an interface for reading vector geometry data from many different file
       
     4  formats (including ESRI shapefiles).
       
     5 
       
     6  When instantiating a DataSource object, use the filename of a
       
     7  GDAL-supported data source.  For example, a SHP file or a
       
     8  TIGER/Line file from the government.
       
     9 
       
    10  The ds_driver keyword is used internally when a ctypes pointer
       
    11  is passed in directly.
       
    12 
       
    13  Example:
       
    14   ds = DataSource('/home/foo/bar.shp')
       
    15   for layer in ds:
       
    16       for feature in layer:
       
    17           # Getting the geometry for the feature.
       
    18           g = feature.geom
       
    19 
       
    20           # Getting the 'description' field for the feature.
       
    21           desc = feature['description']
       
    22 
       
    23           # We can also increment through all of the fields
       
    24           #  attached to this feature.
       
    25           for field in feature:
       
    26               # Get the name of the field (e.g. 'description')
       
    27               nm = field.name
       
    28 
       
    29               # Get the type (integer) of the field, e.g. 0 => OFTInteger
       
    30               t = field.type
       
    31 
       
    32               # Returns the value the field; OFTIntegers return ints,
       
    33               #  OFTReal returns floats, all else returns string.
       
    34               val = field.value
       
    35 """
       
    36 # ctypes prerequisites.
       
    37 from ctypes import byref, c_void_p
       
    38 
       
    39 # The GDAL C library, OGR exceptions, and the Layer object.
       
    40 from django.contrib.gis.gdal.driver import Driver
       
    41 from django.contrib.gis.gdal.error import OGRException, OGRIndexError
       
    42 from django.contrib.gis.gdal.layer import Layer
       
    43 
       
    44 # Getting the ctypes prototypes for the DataSource.
       
    45 from django.contrib.gis.gdal.prototypes.ds import \
       
    46     destroy_ds, get_driver_count, register_all, open_ds, release_ds, \
       
    47     get_ds_name, get_layer, get_layer_count, get_layer_by_name
       
    48 
       
    49 # For more information, see the OGR C API source code:
       
    50 #  http://www.gdal.org/ogr/ogr__api_8h.html
       
    51 #
       
    52 # The OGR_DS_* routines are relevant here.
       
    53 class DataSource(object):
       
    54     "Wraps an OGR Data Source object."
       
    55 
       
    56     #### Python 'magic' routines ####
       
    57     def __init__(self, ds_input, ds_driver=False, write=False):
       
    58 
       
    59         # DataSource pointer is initially NULL.
       
    60         self._ptr = None
       
    61 
       
    62         # The write flag.
       
    63         if write:
       
    64             self._write = 1
       
    65         else:
       
    66             self._write = 0
       
    67 
       
    68         # Registering all the drivers, this needs to be done
       
    69         #  _before_ we try to open up a data source.
       
    70         if not get_driver_count(): register_all()
       
    71 
       
    72         if isinstance(ds_input, basestring):
       
    73             # The data source driver is a void pointer.
       
    74             ds_driver = c_void_p()
       
    75             try:
       
    76                 # OGROpen will auto-detect the data source type.
       
    77                 ds = open_ds(ds_input, self._write, byref(ds_driver))
       
    78             except OGRException:
       
    79                 # Making the error message more clear rather than something
       
    80                 # like "Invalid pointer returned from OGROpen".
       
    81                 raise OGRException('Could not open the datasource at "%s"' % ds_input)
       
    82         elif isinstance(ds_input, c_void_p) and isinstance(ds_driver, c_void_p):
       
    83             ds = ds_input
       
    84         else:
       
    85             raise OGRException('Invalid data source input type: %s' % type(ds_input))
       
    86 
       
    87         if bool(ds):
       
    88             self._ptr = ds
       
    89             self._driver = Driver(ds_driver)
       
    90         else:
       
    91             # Raise an exception if the returned pointer is NULL 
       
    92             raise OGRException('Invalid data source file "%s"' % ds_input)
       
    93 
       
    94     def __del__(self):
       
    95         "Destroys this DataStructure object."
       
    96         if self._ptr: destroy_ds(self._ptr)
       
    97 
       
    98     def __iter__(self):
       
    99         "Allows for iteration over the layers in a data source."
       
   100         for i in xrange(self.layer_count):
       
   101             yield self[i]
       
   102 
       
   103     def __getitem__(self, index):
       
   104         "Allows use of the index [] operator to get a layer at the index."
       
   105         if isinstance(index, basestring):
       
   106             l = get_layer_by_name(self._ptr, index)
       
   107             if not l: raise OGRIndexError('invalid OGR Layer name given: "%s"' % index)
       
   108         elif isinstance(index, int):
       
   109             if index < 0 or index >= self.layer_count:
       
   110                 raise OGRIndexError('index out of range')
       
   111             l = get_layer(self._ptr, index)
       
   112         else:
       
   113             raise TypeError('Invalid index type: %s' % type(index))
       
   114         return Layer(l)
       
   115         
       
   116     def __len__(self):
       
   117         "Returns the number of layers within the data source."
       
   118         return self.layer_count
       
   119 
       
   120     def __str__(self):
       
   121         "Returns OGR GetName and Driver for the Data Source."
       
   122         return '%s (%s)' % (self.name, str(self.driver))
       
   123 
       
   124     #### DataSource Properties ####
       
   125     @property
       
   126     def driver(self):
       
   127         "Returns the Driver object for this Data Source."
       
   128         return self._driver
       
   129         
       
   130     @property
       
   131     def layer_count(self):
       
   132         "Returns the number of layers in the data source."
       
   133         return get_layer_count(self._ptr)
       
   134 
       
   135     @property
       
   136     def name(self):
       
   137         "Returns the name of the data source."
       
   138         return get_ds_name(self._ptr)