feature.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. # The GDAL C library, OGR exception, and the Field object
  2. from django.contrib.gis.gdal.base import GDALBase
  3. from django.contrib.gis.gdal.error import OGRException, OGRIndexError
  4. from django.contrib.gis.gdal.field import Field
  5. from django.contrib.gis.gdal.geometries import OGRGeometry, OGRGeomType
  6. # ctypes function prototypes
  7. from django.contrib.gis.gdal.prototypes import ds as capi, geom as geom_api
  8. from django.utils.encoding import force_bytes, force_text
  9. from django.utils import six
  10. from django.utils.six.moves import xrange
  11. # For more information, see the OGR C API source code:
  12. # http://www.gdal.org/ogr/ogr__api_8h.html
  13. #
  14. # The OGR_F_* routines are relevant here.
  15. class Feature(GDALBase):
  16. """
  17. This class that wraps an OGR Feature, needs to be instantiated
  18. from a Layer object.
  19. """
  20. #### Python 'magic' routines ####
  21. def __init__(self, feat, layer):
  22. """
  23. Initializes Feature from a pointer and its Layer object.
  24. """
  25. if not feat:
  26. raise OGRException('Cannot create OGR Feature, invalid pointer given.')
  27. self.ptr = feat
  28. self._layer = layer
  29. def __del__(self):
  30. "Releases a reference to this object."
  31. if self._ptr:
  32. capi.destroy_feature(self._ptr)
  33. def __getitem__(self, index):
  34. """
  35. Gets the Field object at the specified index, which may be either
  36. an integer or the Field's string label. Note that the Field object
  37. is not the field's _value_ -- use the `get` method instead to
  38. retrieve the value (e.g. an integer) instead of a Field instance.
  39. """
  40. if isinstance(index, six.string_types):
  41. i = self.index(index)
  42. else:
  43. if index < 0 or index > self.num_fields:
  44. raise OGRIndexError('index out of range')
  45. i = index
  46. return Field(self, i)
  47. def __iter__(self):
  48. "Iterates over each field in the Feature."
  49. for i in xrange(self.num_fields):
  50. yield self[i]
  51. def __len__(self):
  52. "Returns the count of fields in this feature."
  53. return self.num_fields
  54. def __str__(self):
  55. "The string name of the feature."
  56. return 'Feature FID %d in Layer<%s>' % (self.fid, self.layer_name)
  57. def __eq__(self, other):
  58. "Does equivalence testing on the features."
  59. return bool(capi.feature_equal(self.ptr, other._ptr))
  60. #### Feature Properties ####
  61. @property
  62. def encoding(self):
  63. return self._layer._ds.encoding
  64. @property
  65. def fid(self):
  66. "Returns the feature identifier."
  67. return capi.get_fid(self.ptr)
  68. @property
  69. def layer_name(self):
  70. "Returns the name of the layer for the feature."
  71. name = capi.get_feat_name(self._layer._ldefn)
  72. return force_text(name, self.encoding, strings_only=True)
  73. @property
  74. def num_fields(self):
  75. "Returns the number of fields in the Feature."
  76. return capi.get_feat_field_count(self.ptr)
  77. @property
  78. def fields(self):
  79. "Returns a list of fields in the Feature."
  80. return [capi.get_field_name(capi.get_field_defn(self._layer._ldefn, i))
  81. for i in xrange(self.num_fields)]
  82. @property
  83. def geom(self):
  84. "Returns the OGR Geometry for this Feature."
  85. # Retrieving the geometry pointer for the feature.
  86. geom_ptr = capi.get_feat_geom_ref(self.ptr)
  87. return OGRGeometry(geom_api.clone_geom(geom_ptr))
  88. @property
  89. def geom_type(self):
  90. "Returns the OGR Geometry Type for this Feture."
  91. return OGRGeomType(capi.get_fd_geom_type(self._layer._ldefn))
  92. #### Feature Methods ####
  93. def get(self, field):
  94. """
  95. Returns the value of the field, instead of an instance of the Field
  96. object. May take a string of the field name or a Field object as
  97. parameters.
  98. """
  99. field_name = getattr(field, 'name', field)
  100. return self[field_name].value
  101. def index(self, field_name):
  102. "Returns the index of the given field name."
  103. i = capi.get_field_index(self.ptr, force_bytes(field_name))
  104. if i < 0:
  105. raise OGRIndexError('invalid OFT field name given: "%s"' % field_name)
  106. return i