0
# Data Model
1
2
Fiona's data model is built around GeoJSON-like Python objects that provide an intuitive interface for working with geospatial features. The core classes Feature, Geometry, and Properties represent the fundamental building blocks of vector geospatial data, following GeoJSON conventions while providing additional functionality for validation and manipulation.
3
4
## Capabilities
5
6
### Feature Class
7
8
Represents a complete geospatial feature with geometry, properties, and optional ID. Features are the primary unit of geospatial data in Fiona, corresponding to rows in a shapefile or individual objects in a GeoJSON file.
9
10
```python { .api }
11
class Feature:
12
def __init__(self, geometry=None, id=None, properties=None, **data):
13
"""
14
Create a GeoJSON-like feature.
15
16
Parameters:
17
- geometry: dict or Geometry, the feature's geometry
18
- id: str or int, unique identifier for the feature
19
- properties: dict or Properties, feature attributes
20
- data: dict, additional key-value pairs
21
"""
22
23
@classmethod
24
def from_dict(cls, ob=None, **kwargs):
25
"""
26
Create Feature from dictionary or GeoJSON-like object.
27
28
Parameters:
29
- ob: dict, GeoJSON-like feature dictionary
30
- kwargs: dict, additional parameters
31
32
Returns:
33
Feature instance
34
"""
35
36
@property
37
def geometry(self):
38
"""Get the feature's geometry object."""
39
40
@property
41
def id(self):
42
"""Get the feature's unique identifier."""
43
44
@property
45
def properties(self):
46
"""Get the feature's properties/attributes."""
47
48
@property
49
def type(self):
50
"""Always returns 'Feature'."""
51
```
52
53
#### Usage Examples
54
55
```python
56
from fiona.model import Feature, Geometry, Properties
57
58
# Create a point feature
59
geometry = {'type': 'Point', 'coordinates': [-122.5, 37.5]}
60
properties = {'name': 'San Francisco', 'population': 875000}
61
feature = Feature(geometry=geometry, properties=properties, id='sf_001')
62
63
print(f"Feature type: {feature.type}")
64
print(f"Feature ID: {feature.id}")
65
print(f"Geometry type: {feature.geometry['type']}")
66
print(f"Properties: {feature.properties}")
67
68
# Create from dictionary (GeoJSON-like)
69
feature_dict = {
70
'type': 'Feature',
71
'geometry': {
72
'type': 'Polygon',
73
'coordinates': [[[-1, -1], [1, -1], [1, 1], [-1, 1], [-1, -1]]]
74
},
75
'properties': {'area': 4.0, 'name': 'Square'},
76
'id': 'poly_001'
77
}
78
79
feature = Feature.from_dict(feature_dict)
80
print(f"Created feature: {feature.id}")
81
82
# Access feature components
83
coords = feature.geometry['coordinates']
84
area = feature.properties['area']
85
```
86
87
### Geometry Class
88
89
Represents the spatial component of a feature, supporting all OGR geometry types including points, lines, polygons, and multi-geometries with optional Z and M coordinates.
90
91
```python { .api }
92
class Geometry:
93
def __init__(self, coordinates=None, type=None, geometries=None, **data):
94
"""
95
Create a GeoJSON-like geometry.
96
97
Parameters:
98
- coordinates: list, coordinate sequences for the geometry
99
- type: str, geometry type (Point, LineString, Polygon, etc.)
100
- geometries: list, constituent geometries for GeometryCollection
101
- data: dict, additional key-value pairs
102
"""
103
104
@classmethod
105
def from_dict(cls, ob=None, **kwargs):
106
"""
107
Create Geometry from dictionary or GeoJSON-like object.
108
109
Parameters:
110
- ob: dict, GeoJSON-like geometry dictionary
111
- kwargs: dict, additional parameters
112
113
Returns:
114
Geometry instance
115
"""
116
117
@property
118
def coordinates(self):
119
"""Get the geometry's coordinate sequence."""
120
121
@property
122
def type(self):
123
"""Get the geometry type."""
124
125
@property
126
def geometries(self):
127
"""Get constituent geometries (for GeometryCollection)."""
128
```
129
130
#### Usage Examples
131
132
```python
133
from fiona.model import Geometry
134
135
# Create a point geometry
136
point = Geometry(coordinates=[-122.5, 37.5], type='Point')
137
print(f"Point coordinates: {point.coordinates}")
138
139
# Create a linestring geometry
140
linestring = Geometry(
141
coordinates=[[-122.5, 37.5], [-122.4, 37.6], [-122.3, 37.7]],
142
type='LineString'
143
)
144
print(f"LineString length: {len(linestring.coordinates)} points")
145
146
# Create a polygon geometry (with exterior ring and hole)
147
polygon = Geometry(
148
coordinates=[
149
# Exterior ring
150
[[-1, -1], [1, -1], [1, 1], [-1, 1], [-1, -1]],
151
# Interior ring (hole)
152
[[-0.5, -0.5], [0.5, -0.5], [0.5, 0.5], [-0.5, 0.5], [-0.5, -0.5]]
153
],
154
type='Polygon'
155
)
156
157
# Create from dictionary
158
geometry_dict = {
159
'type': 'MultiPoint',
160
'coordinates': [[-122.5, 37.5], [-122.4, 37.6]]
161
}
162
multipoint = Geometry.from_dict(geometry_dict)
163
print(f"MultiPoint has {len(multipoint.coordinates)} points")
164
165
# Create a geometry collection
166
collection = Geometry(
167
type='GeometryCollection',
168
geometries=[
169
{'type': 'Point', 'coordinates': [0, 0]},
170
{'type': 'LineString', 'coordinates': [[0, 0], [1, 1]]}
171
]
172
)
173
print(f"Collection has {len(collection.geometries)} geometries")
174
```
175
176
### Properties Class
177
178
Represents the attribute data associated with a feature, providing a dictionary-like interface for feature properties and metadata.
179
180
```python { .api }
181
class Properties:
182
def __init__(self, **kwds):
183
"""
184
Create feature properties mapping.
185
186
Parameters:
187
- kwds: dict, property key-value pairs
188
"""
189
190
@classmethod
191
def from_dict(cls, mapping=None, **kwargs):
192
"""
193
Create Properties from dictionary.
194
195
Parameters:
196
- mapping: dict, property dictionary
197
- kwargs: dict, additional properties
198
199
Returns:
200
Properties instance
201
"""
202
```
203
204
#### Usage Examples
205
206
```python
207
from fiona.model import Properties
208
209
# Create properties from keyword arguments
210
props = Properties(name='Golden Gate Bridge', length=2737, year_built=1937)
211
print(f"Bridge name: {props['name']}")
212
print(f"Length: {props['length']} meters")
213
214
# Create from dictionary
215
prop_dict = {
216
'population': 875000,
217
'area_km2': 121.4,
218
'country': 'USA',
219
'founded': 1776
220
}
221
city_props = Properties.from_dict(prop_dict)
222
223
# Properties behave like dictionaries
224
city_props['timezone'] = 'PST'
225
print(f"City area: {city_props['area_km2']} km²")
226
227
# Iterate over properties
228
for key, value in city_props.items():
229
print(f"{key}: {value}")
230
```
231
232
### Geometry Type Enumeration
233
234
OGR geometry type constants for working with different geometry types programmatically.
235
236
```python { .api }
237
class OGRGeometryType(Enum):
238
"""Enumeration of OGR geometry type constants."""
239
Unknown = 0
240
Point = 1
241
LineString = 2
242
Polygon = 3
243
MultiPoint = 4
244
MultiLineString = 5
245
MultiPolygon = 6
246
GeometryCollection = 7
247
CircularString = 8
248
CompoundCurve = 9
249
CurvePolygon = 10
250
MultiCurve = 11
251
MultiSurface = 12
252
Curve = 13
253
Surface = 14
254
PolyhedralSurface = 15
255
TIN = 16
256
Triangle = 17
257
NONE = 100
258
LinearRing = 101
259
# Z variants (3D)
260
CircularStringZ = 1008
261
CompoundCurveZ = 1009
262
# M variants (measured)
263
PointM = 2001
264
LineStringM = 2002
265
# ZM variants (3D + measured)
266
PointZM = 3001
267
LineStringZM = 3002
268
# 25D variants (legacy 3D)
269
Point25D = 0x80000001
270
LineString25D = 0x80000002
271
```
272
273
#### Usage Examples
274
275
```python
276
from fiona.model import OGRGeometryType
277
278
# Check geometry type
279
geom_type = OGRGeometryType.Point
280
print(f"Point type value: {geom_type.value}")
281
282
# Use in schema definition
283
schema = {
284
'geometry': OGRGeometryType.Polygon.name, # 'Polygon'
285
'properties': {'name': 'str', 'area': 'float'}
286
}
287
288
# Compare geometry types
289
if geom_type == OGRGeometryType.Point:
290
print("This is a point geometry")
291
292
# Work with 3D geometries
293
if geom_type.value > 1000 and geom_type.value < 2000:
294
print("This is a 3D (Z) geometry type")
295
296
# Work with measured geometries (M coordinates)
297
point_m = OGRGeometryType.PointM
298
if 2000 <= point_m.value < 3000:
299
print("This geometry has measure (M) coordinates")
300
301
# Work with 3D + measured geometries (ZM coordinates)
302
point_zm = OGRGeometryType.PointZM
303
if point_zm.value >= 3000:
304
print("This geometry has both Z and M coordinates")
305
306
# Practical geometry type checking
307
def get_coordinate_dimensions(geom_type):
308
"""Determine coordinate dimensions from geometry type."""
309
if geom_type.value >= 3000:
310
return "ZM (3D + Measured)"
311
elif geom_type.value >= 2000:
312
return "M (Measured)"
313
elif geom_type.value >= 1000:
314
return "Z (3D)"
315
elif geom_type.value >= 0x80000000: # 25D variants
316
return "25D (Legacy 3D)"
317
else:
318
return "2D"
319
320
# Example usage
321
for geom_type in [OGRGeometryType.Point, OGRGeometryType.PointM,
322
OGRGeometryType.Point25D, OGRGeometryType.PointZM]:
323
dims = get_coordinate_dimensions(geom_type)
324
print(f"{geom_type.name}: {dims}")
325
```
326
327
## Validation and Type Conversion
328
329
### Data Validation
330
331
Features, geometries, and properties include validation methods to ensure data integrity:
332
333
```python
334
# Validate feature structure
335
feature = Feature(
336
geometry={'type': 'Point', 'coordinates': [0, 0]},
337
properties={'name': 'Origin'}
338
)
339
340
# Validate geometry coordinates
341
try:
342
invalid_geom = Geometry(coordinates='invalid', type='Point')
343
except ValueError as e:
344
print(f"Validation error: {e}")
345
346
# Properties validate against expected types
347
schema = {'name': 'str', 'count': 'int'}
348
# This would be validated when writing to a collection
349
```
350
351
### Type Conversions
352
353
Automatic conversion between dictionaries and Fiona objects:
354
355
```python
356
# Dict to Fiona objects
357
feature_dict = {
358
'type': 'Feature',
359
'geometry': {'type': 'Point', 'coordinates': [0, 0]},
360
'properties': {'name': 'Test'}
361
}
362
363
# Automatic conversion when reading from collections
364
with fiona.open('data.geojson', 'r') as collection:
365
for feature in collection: # Already Feature-like objects
366
geom = feature['geometry'] # Dictionary access
367
props = feature['properties'] # Dictionary access
368
369
# Explicit conversion
370
feature_obj = Feature.from_dict(feature_dict)
371
```
372
373
## Integration with Collections
374
375
The data model classes integrate seamlessly with Fiona's Collection interface:
376
377
```python
378
# Writing Feature objects to collections
379
with fiona.open('output.geojson', 'w', **collection_kwargs) as output:
380
feature = Feature(
381
geometry=Geometry(coordinates=[0, 0], type='Point'),
382
properties=Properties(name='Test Point')
383
)
384
output.write(feature) # Automatic serialization
385
386
# Reading returns feature-like dictionaries
387
with fiona.open('input.geojson', 'r') as input_data:
388
for feature in input_data:
389
# feature behaves like Feature but is actually a dict
390
print(f"Geometry: {feature['geometry']['type']}")
391
print(f"Properties: {feature['properties']}")
392
```