or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdchangesets.mderrors.mdindex.mdnodes.mdnotes.mdrelations.mdways.md

ways.mddocs/

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

```