app/django/contrib/gis/gdal/feature.py
author Mario Ferraro <fadinlight@gmail.com>
Sun, 15 Nov 2009 22:12:20 +0100
changeset 3093 d1be59b6b627
parent 323 ff1a9aa48cfd
permissions -rw-r--r--
GMaps related JS changed to use new google namespace. Google is going to change permanently in the future the way to load its services, so better stay safe. Also this commit shows uses of the new melange.js module. Fixes Issue 634.

# 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