You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
138 lines
4.9 KiB
138 lines
4.9 KiB
""" |
|
DataSource is a wrapper for the OGR Data Source object, which provides |
|
an interface for reading vector geometry data from many different file |
|
formats (including ESRI shapefiles). |
|
|
|
When instantiating a DataSource object, use the filename of a |
|
GDAL-supported data source. For example, a SHP file or a |
|
TIGER/Line file from the government. |
|
|
|
The ds_driver keyword is used internally when a ctypes pointer |
|
is passed in directly. |
|
|
|
Example: |
|
ds = DataSource('/home/foo/bar.shp') |
|
for layer in ds: |
|
for feature in layer: |
|
# Getting the geometry for the feature. |
|
g = feature.geom |
|
|
|
# Getting the 'description' field for the feature. |
|
desc = feature['description'] |
|
|
|
# We can also increment through all of the fields |
|
# attached to this feature. |
|
for field in feature: |
|
# Get the name of the field (e.g. 'description') |
|
nm = field.name |
|
|
|
# Get the type (integer) of the field, e.g. 0 => OFTInteger |
|
t = field.type |
|
|
|
# Returns the value the field; OFTIntegers return ints, |
|
# OFTReal returns floats, all else returns string. |
|
val = field.value |
|
""" |
|
# ctypes prerequisites. |
|
from ctypes import byref, c_void_p |
|
|
|
# The GDAL C library, OGR exceptions, and the Layer object. |
|
from django.contrib.gis.gdal.driver import Driver |
|
from django.contrib.gis.gdal.error import OGRException, OGRIndexError |
|
from django.contrib.gis.gdal.layer import Layer |
|
|
|
# Getting the ctypes prototypes for the DataSource. |
|
from django.contrib.gis.gdal.prototypes.ds import \ |
|
destroy_ds, get_driver_count, register_all, open_ds, release_ds, \ |
|
get_ds_name, get_layer, get_layer_count, get_layer_by_name |
|
|
|
# For more information, see the OGR C API source code: |
|
# http://www.gdal.org/ogr/ogr__api_8h.html |
|
# |
|
# The OGR_DS_* routines are relevant here. |
|
class DataSource(object): |
|
"Wraps an OGR Data Source object." |
|
|
|
#### Python 'magic' routines #### |
|
def __init__(self, ds_input, ds_driver=False, write=False): |
|
|
|
# DataSource pointer is initially NULL. |
|
self._ptr = None |
|
|
|
# The write flag. |
|
if write: |
|
self._write = 1 |
|
else: |
|
self._write = 0 |
|
|
|
# Registering all the drivers, this needs to be done |
|
# _before_ we try to open up a data source. |
|
if not get_driver_count(): register_all() |
|
|
|
if isinstance(ds_input, basestring): |
|
# The data source driver is a void pointer. |
|
ds_driver = c_void_p() |
|
try: |
|
# OGROpen will auto-detect the data source type. |
|
ds = open_ds(ds_input, self._write, byref(ds_driver)) |
|
except OGRException: |
|
# Making the error message more clear rather than something |
|
# like "Invalid pointer returned from OGROpen". |
|
raise OGRException('Could not open the datasource at "%s"' % ds_input) |
|
elif isinstance(ds_input, c_void_p) and isinstance(ds_driver, c_void_p): |
|
ds = ds_input |
|
else: |
|
raise OGRException('Invalid data source input type: %s' % type(ds_input)) |
|
|
|
if bool(ds): |
|
self._ptr = ds |
|
self._driver = Driver(ds_driver) |
|
else: |
|
# Raise an exception if the returned pointer is NULL |
|
raise OGRException('Invalid data source file "%s"' % ds_input) |
|
|
|
def __del__(self): |
|
"Destroys this DataStructure object." |
|
if self._ptr: destroy_ds(self._ptr) |
|
|
|
def __iter__(self): |
|
"Allows for iteration over the layers in a data source." |
|
for i in xrange(self.layer_count): |
|
yield self[i] |
|
|
|
def __getitem__(self, index): |
|
"Allows use of the index [] operator to get a layer at the index." |
|
if isinstance(index, basestring): |
|
l = get_layer_by_name(self._ptr, index) |
|
if not l: raise OGRIndexError('invalid OGR Layer name given: "%s"' % index) |
|
elif isinstance(index, int): |
|
if index < 0 or index >= self.layer_count: |
|
raise OGRIndexError('index out of range') |
|
l = get_layer(self._ptr, index) |
|
else: |
|
raise TypeError('Invalid index type: %s' % type(index)) |
|
return Layer(l) |
|
|
|
def __len__(self): |
|
"Returns the number of layers within the data source." |
|
return self.layer_count |
|
|
|
def __str__(self): |
|
"Returns OGR GetName and Driver for the Data Source." |
|
return '%s (%s)' % (self.name, str(self.driver)) |
|
|
|
#### DataSource Properties #### |
|
@property |
|
def driver(self): |
|
"Returns the Driver object for this Data Source." |
|
return self._driver |
|
|
|
@property |
|
def layer_count(self): |
|
"Returns the number of layers in the data source." |
|
return get_layer_count(self._ptr) |
|
|
|
@property |
|
def name(self): |
|
"Returns the name of the data source." |
|
return get_ds_name(self._ptr)
|
|
|