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