0
# Way Operations
1
2
Complete lifecycle management for OpenStreetMap ways including creation with node references, modification, deletion, and relationship tracking. Ways represent linear features like roads, paths, and area boundaries by connecting a series of nodes.
3
4
## Capabilities
5
6
### Way Retrieval
7
8
Get individual ways by ID with optional version specification.
9
10
```python { .api }
11
def WayGet(WayId, WayVersion=-1):
12
"""
13
Returns way with WayId as a dict.
14
15
Parameters:
16
- WayId (int): Unique identifier of the way
17
- WayVersion (int, optional): Specific version to retrieve (-1 for latest)
18
19
Returns:
20
dict: Way data including id, nd (node list), tag, changeset, version,
21
user, uid, timestamp, visible
22
23
Raises:
24
- ElementDeletedApiError: If way has been deleted
25
- ElementNotFoundApiError: If way cannot be found
26
"""
27
```
28
29
**Usage Example:**
30
31
```python
32
import osmapi
33
34
api = osmapi.OsmApi()
35
36
# Get latest version of way
37
way = api.WayGet(456)
38
print(f"Way {way['id']} with {len(way['nd'])} nodes")
39
print(f"Type: {way['tag'].get('highway', way['tag'].get('building', 'other'))}")
40
print(f"Name: {way['tag'].get('name', 'Unnamed')}")
41
42
# Get specific version
43
way_v3 = api.WayGet(456, WayVersion=3)
44
print(f"Version 3 had {len(way_v3['nd'])} nodes")
45
```
46
47
### Way Creation
48
49
Create new ways by connecting existing nodes with optional tags.
50
51
```python { .api }
52
def WayCreate(WayData):
53
"""
54
Creates a way based on the supplied WayData dict.
55
56
Parameters:
57
- WayData (dict): Way data with nd (node list) and optional tag
58
Required: nd (list[int]) - list of node IDs
59
Optional: tag (dict)
60
61
Returns:
62
dict: Updated WayData with assigned id, version, changeset,
63
user, uid, visible
64
65
Raises:
66
- UsernamePasswordMissingError: If no authentication provided
67
- NoChangesetOpenError: If no changeset is open
68
- OsmTypeAlreadyExistsError: If way data contains existing ID
69
- ChangesetClosedApiError: If changeset is closed
70
- PreconditionFailedApiError: If referenced nodes don't exist
71
"""
72
```
73
74
**Usage Example:**
75
76
```python
77
import osmapi
78
79
api = osmapi.OsmApi(username="your_username", password="your_password")
80
81
with api.Changeset({"comment": "Adding new street"}) as changeset_id:
82
# Create nodes for the way first
83
node1 = api.NodeCreate({"lat": 47.6060, "lon": -122.3320, "tag": {}})
84
node2 = api.NodeCreate({"lat": 47.6065, "lon": -122.3325, "tag": {}})
85
node3 = api.NodeCreate({"lat": 47.6070, "lon": -122.3330, "tag": {}})
86
87
# Create way connecting the nodes
88
new_way = api.WayCreate({
89
"nd": [node1["id"], node2["id"], node3["id"]],
90
"tag": {
91
"highway": "residential",
92
"name": "Example Street",
93
"surface": "asphalt",
94
"maxspeed": "25 mph"
95
}
96
})
97
print(f"Created way {new_way['id']} with {len(new_way['nd'])} nodes")
98
```
99
100
### Way Updates
101
102
Modify existing ways by updating node list, tags, or other attributes.
103
104
```python { .api }
105
def WayUpdate(WayData):
106
"""
107
Updates way with the supplied WayData dict.
108
109
Parameters:
110
- WayData (dict): Way data with id, version, and updated fields
111
Required: id (int), nd (list[int]), version (int)
112
Optional: tag (dict)
113
114
Returns:
115
dict: Updated WayData with new version, changeset, user, uid, visible
116
117
Raises:
118
- UsernamePasswordMissingError: If no authentication provided
119
- NoChangesetOpenError: If no changeset is open
120
- VersionMismatchApiError: If version doesn't match current
121
- ChangesetClosedApiError: If changeset is closed
122
- PreconditionFailedApiError: If referenced nodes don't exist
123
"""
124
```
125
126
**Usage Example:**
127
128
```python
129
import osmapi
130
131
api = osmapi.OsmApi(username="your_username", password="your_password")
132
133
# Get current way data
134
way = api.WayGet(12345)
135
136
with api.Changeset({"comment": "Updating street information"}) as changeset_id:
137
# Add new tag information
138
way["tag"]["surface"] = "concrete"
139
way["tag"]["lanes"] = "2"
140
way["tag"]["lit"] = "yes"
141
142
# Add a new node to extend the way
143
new_node = api.NodeCreate({"lat": 47.6075, "lon": -122.3335, "tag": {}})
144
way["nd"].append(new_node["id"])
145
146
updated_way = api.WayUpdate(way)
147
print(f"Updated way {updated_way['id']} to version {updated_way['version']}")
148
print(f"Now has {len(updated_way['nd'])} nodes")
149
```
150
151
### Way Deletion
152
153
Delete ways from OpenStreetMap (marks as invisible).
154
155
```python { .api }
156
def WayDelete(WayData):
157
"""
158
Delete way with WayData.
159
160
Parameters:
161
- WayData (dict): Way data with id, version, and current attributes
162
Required: id (int), nd (list[int]), version (int)
163
Optional: tag (dict)
164
165
Returns:
166
dict: Updated WayData with visible=False and new version
167
168
Raises:
169
- UsernamePasswordMissingError: If no authentication provided
170
- NoChangesetOpenError: If no changeset is open
171
- VersionMismatchApiError: If version doesn't match current
172
- ChangesetClosedApiError: If changeset is closed
173
- ElementDeletedApiError: If way already deleted
174
- ElementNotFoundApiError: If way cannot be found
175
- PreconditionFailedApiError: If way is still used by relations
176
"""
177
```
178
179
**Usage Example:**
180
181
```python
182
import osmapi
183
184
api = osmapi.OsmApi(username="your_username", password="your_password")
185
186
# Get way to delete
187
way = api.WayGet(12345)
188
189
# Check if way is used in relations first
190
relations = api.WayRelations(way["id"])
191
if relations:
192
print(f"Warning: Way is used in {len(relations)} relations")
193
194
with api.Changeset({"comment": "Removing obsolete way"}) as changeset_id:
195
deleted_way = api.WayDelete(way)
196
print(f"Deleted way {deleted_way['id']}, now version {deleted_way['version']}")
197
print(f"Visible: {deleted_way['visible']}") # False
198
```
199
200
### Way History
201
202
Retrieve complete version history for a way.
203
204
```python { .api }
205
def WayHistory(WayId):
206
"""
207
Returns dict with version as key containing all way versions.
208
209
Parameters:
210
- WayId (int): Unique identifier of the way
211
212
Returns:
213
dict: Version history with version numbers as keys and
214
WayData dicts as values
215
"""
216
```
217
218
**Usage Example:**
219
220
```python
221
import osmapi
222
223
api = osmapi.OsmApi()
224
225
# Get complete history
226
history = api.WayHistory(456)
227
228
for version, way_data in history.items():
229
print(f"Version {version}: {way_data['user']} at {way_data['timestamp']}")
230
print(f" Nodes: {len(way_data['nd'])} ({way_data['nd'][:3]}...)")
231
print(f" Highway type: {way_data['tag'].get('highway', 'none')}")
232
```
233
234
### Way Relationships
235
236
Find relations that reference a specific way.
237
238
```python { .api }
239
def WayRelations(WayId):
240
"""
241
Returns a list of relations containing the specified way.
242
243
Parameters:
244
- WayId (int): Unique identifier of the way
245
246
Returns:
247
list[dict]: List of RelationData dicts containing the way
248
"""
249
```
250
251
**Usage Example:**
252
253
```python
254
import osmapi
255
256
api = osmapi.OsmApi()
257
258
way_id = 456
259
260
# Find relations using this way
261
relations = api.WayRelations(way_id)
262
print(f"Way {way_id} is used in {len(relations)} relations:")
263
for relation in relations:
264
print(f" Relation {relation['id']}: {relation['tag'].get('name', 'Unnamed')}")
265
print(f" Type: {relation['tag'].get('type', 'unknown')}")
266
267
# Find this way's role in the relation
268
for member in relation['member']:
269
if member['type'] == 'way' and member['ref'] == way_id:
270
print(f" Role: {member['role']}")
271
```
272
273
### Way with Full Data
274
275
Retrieve way with all referenced nodes included.
276
277
```python { .api }
278
def WayFull(WayId):
279
"""
280
Returns the full data for way WayId as list of dicts.
281
282
Parameters:
283
- WayId (int): Unique identifier of the way
284
285
Returns:
286
list[dict]: List of elements with type and data keys, including
287
the way itself and all referenced nodes
288
289
Raises:
290
- ElementDeletedApiError: If way has been deleted
291
- ElementNotFoundApiError: If way cannot be found
292
"""
293
```
294
295
**Usage Example:**
296
297
```python
298
import osmapi
299
300
api = osmapi.OsmApi()
301
302
# Get way with all referenced nodes
303
full_data = api.WayFull(456)
304
305
way_data = None
306
nodes_data = []
307
308
for element in full_data:
309
if element['type'] == 'way':
310
way_data = element['data']
311
elif element['type'] == 'node':
312
nodes_data.append(element['data'])
313
314
print(f"Way {way_data['id']}: {way_data['tag'].get('name', 'Unnamed')}")
315
print(f"Coordinates:")
316
for node in nodes_data:
317
print(f" Node {node['id']}: ({node['lat']}, {node['lon']})")
318
```
319
320
### Bulk Way Operations
321
322
Retrieve multiple ways in a single API call for efficiency.
323
324
```python { .api }
325
def WaysGet(WayIdList):
326
"""
327
Returns dict with way IDs as keys for multiple ways.
328
329
Parameters:
330
- WayIdList (list[int]): List of way IDs to retrieve
331
332
Returns:
333
dict: Way IDs as keys with WayData dicts as values
334
"""
335
```
336
337
**Usage Example:**
338
339
```python
340
import osmapi
341
342
api = osmapi.OsmApi()
343
344
# Get multiple ways efficiently
345
way_ids = [456, 789, 101112, 131415]
346
ways = api.WaysGet(way_ids)
347
348
for way_id, way_data in ways.items():
349
highway_type = way_data['tag'].get('highway', 'other')
350
name = way_data['tag'].get('name', 'Unnamed')
351
print(f"Way {way_id}: {highway_type} - {name}")
352
print(f" Nodes: {len(way_data['nd'])}")
353
354
# Check for missing ways
355
found_ids = set(ways.keys())
356
missing_ids = set(way_ids) - found_ids
357
if missing_ids:
358
print(f"Missing ways: {missing_ids}")
359
```
360
361
## Way Data Structure
362
363
### WayData Dictionary
364
365
```python { .api }
366
WayData = {
367
'id': int, # Way ID (assigned by OSM after creation)
368
'nd': list[int], # List of node IDs that make up this way (required)
369
'tag': dict, # Key-value pairs for attributes
370
'version': int, # Version number (starts at 1)
371
'changeset': int, # ID of changeset that last modified this way
372
'user': str, # Username of last editor
373
'uid': int, # User ID of last editor
374
'timestamp': str, # ISO timestamp of last modification
375
'visible': bool # True if visible, False if deleted
376
}
377
```
378
379
### Common Way Tags
380
381
```python
382
# Road/Highway
383
{
384
"highway": "residential",
385
"name": "Main Street",
386
"surface": "asphalt",
387
"lanes": "2",
388
"maxspeed": "30 mph",
389
"lit": "yes"
390
}
391
392
# Building outline
393
{
394
"building": "residential",
395
"addr:housenumber": "123",
396
"addr:street": "Main Street",
397
"addr:city": "Example City",
398
"building:levels": "2"
399
}
400
401
# Natural feature
402
{
403
"natural": "river",
404
"name": "Example River",
405
"waterway": "river",
406
"width": "15"
407
}
408
409
# Area (closed way)
410
{
411
"landuse": "park",
412
"name": "Central Park",
413
"access": "public",
414
"leisure": "park"
415
}
416
```
417
418
## Way Types and Patterns
419
420
### Linear Ways
421
Ways representing linear features like roads, rivers, or boundaries.
422
423
```python
424
# Road way - nodes should be ordered along the path
425
road_way = {
426
"nd": [node1_id, node2_id, node3_id, node4_id],
427
"tag": {"highway": "primary", "name": "Highway 101"}
428
}
429
```
430
431
### Closed Ways (Areas)
432
Ways where the first and last nodes are the same, representing areas.
433
434
```python
435
# Building way - first and last node IDs are identical
436
building_way = {
437
"nd": [node1_id, node2_id, node3_id, node4_id, node1_id],
438
"tag": {"building": "house", "addr:housenumber": "42"}
439
}
440
```
441
442
### Way Validation
443
- Must have at least 2 nodes
444
- Maximum of 2000 nodes per way
445
- All referenced nodes must exist
446
- For areas, first and last node should be the same
447
- Nodes should be ordered correctly for the intended geometry
448
449
## Error Handling
450
451
Way operations can raise various exceptions:
452
453
```python
454
import osmapi
455
456
api = osmapi.OsmApi(username="user", password="pass")
457
458
try:
459
way = api.WayGet(999999)
460
except osmapi.ElementNotFoundApiError:
461
print("Way does not exist")
462
except osmapi.ElementDeletedApiError:
463
print("Way has been deleted")
464
465
try:
466
with api.Changeset({"comment": "Test"}) as changeset_id:
467
# This will fail if nodes don't exist
468
api.WayCreate({
469
"nd": [999999, 999998], # Non-existent nodes
470
"tag": {"highway": "path"}
471
})
472
except osmapi.PreconditionFailedApiError:
473
print("Referenced nodes don't exist or are not visible")
474
except osmapi.VersionMismatchApiError:
475
print("Version conflict - way was modified by another user")
476
```