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.

feature.py 3.8KB

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