# The GDAL C library, OGR exception, and the Field object from django.contrib.gis.gdal.error import OGRException, OGRIndexError from django.contrib.gis.gdal.field import Field from django.contrib.gis.gdal.geometries import OGRGeometry, OGRGeomType from django.contrib.gis.gdal.srs import SpatialReference # ctypes function prototypes from django.contrib.gis.gdal.prototypes.ds import \ destroy_feature, feature_equal, get_fd_geom_type, get_feat_geom_ref, \ get_feat_name, get_feat_field_count, get_fid, get_field_defn, \ get_field_index, get_field_name from django.contrib.gis.gdal.prototypes.geom import clone_geom, get_geom_srs from django.contrib.gis.gdal.prototypes.srs import clone_srs # For more information, see the OGR C API source code: # http://www.gdal.org/ogr/ogr__api_8h.html # # The OGR_F_* routines are relevant here. class Feature(object): "A class that wraps an OGR Feature, needs to be instantiated from a Layer object." #### Python 'magic' routines #### def __init__(self, feat, fdefn): "Initializes on the pointers for the feature and the layer definition." self._ptr = None # Initially NULL if not feat or not fdefn: raise OGRException('Cannot create OGR Feature, invalid pointer given.') self._ptr = feat self._fdefn = fdefn def __del__(self): "Releases a reference to this object." if self._ptr: destroy_feature(self._ptr) def __getitem__(self, index): """ Gets the Field object at the specified index, which may be either an integer or the Field's string label. Note that the Field object is not the field's _value_ -- use the `get` method instead to retrieve the value (e.g. an integer) instead of a Field instance. """ if isinstance(index, basestring): i = self.index(index) else: if index < 0 or index > self.num_fields: raise OGRIndexError('index out of range') i = index return Field(self._ptr, i) def __iter__(self): "Iterates over each field in the Feature." for i in xrange(self.num_fields): yield self[i] def __len__(self): "Returns the count of fields in this feature." return self.num_fields def __str__(self): "The string name of the feature." return 'Feature FID %d in Layer<%s>' % (self.fid, self.layer_name) def __eq__(self, other): "Does equivalence testing on the features." return bool(feature_equal(self._ptr, other._ptr)) #### Feature Properties #### @property def fid(self): "Returns the feature identifier." return get_fid(self._ptr) @property def layer_name(self): "Returns the name of the layer for the feature." return get_feat_name(self._fdefn) @property def num_fields(self): "Returns the number of fields in the Feature." return get_feat_field_count(self._ptr) @property def fields(self): "Returns a list of fields in the Feature." return [get_field_name(get_field_defn(self._fdefn, i)) for i in xrange(self.num_fields)] @property def geom(self): "Returns the OGR Geometry for this Feature." # Retrieving the geometry pointer for the feature. geom_ptr = get_feat_geom_ref(self._ptr) return OGRGeometry(clone_geom(geom_ptr)) @property def geom_type(self): "Returns the OGR Geometry Type for this Feture." return OGRGeomType(get_fd_geom_type(self._fdefn)) #### Feature Methods #### def get(self, field): """ Returns the value of the field, instead of an instance of the Field object. May take a string of the field name or a Field object as parameters. """ field_name = getattr(field, 'name', field) return self[field_name].value def index(self, field_name): "Returns the index of the given field name." i = get_field_index(self._ptr, field_name) if i < 0: raise OGRIndexError('invalid OFT field name given: "%s"' % field_name) return i