Network clean-up¶
OSM data has small gaps: a footway that ends a metre short of the road it meets, a road cut in two by the area's border. Two steps deal with them, then an optional check.
| Step | Modes | Runs when |
|---|---|---|
| Connect dangling paths | walking, cycling | clip.connectivity_rescue (on), in a build from a PBF |
| Component filter | all | a boundary is set, and clip.keep_largest_component (on) or clip.min_component_edges > 1 |
| Validation | all | validation.enabled (off; on in the config template) |
Connect dangling paths¶
A dangling end is a node that touches only one edge, where that edge is a cycleway, footway,
path, steps, pedestrian or track. For each one, the build adds a straight connector edge
to the nearest node within clip.connect_snap_m metres (default 10), in both directions. Without it,
the path would be a separate piece and the component filter would drop it.
A connector edge has:
- a negative
osm_id,-min(a, b):aandbare theosm_ids of the path and of the road at the node it joins. Select connectors withosm_id < 0. - the
highwayof the path andoneway = FALSE; noname,lanesor other tags (NULL). In cycling, a connector that extends a dismount path is dismount too. - an
edge_idfrom the usual formula.
Monaco:
| Mode | Dangling ends joined | Connector edges added | Left after the component filter |
|---|---|---|---|
| walking | 254 | 508 | 490 |
| cycling | 512 | 1,024 | 986 |
Limits: it joins the nearest node, not the nearest point of an edge, so a connector can be longer than the real gap. The distance ignores levels, so it can join a path to a road on a bridge above it. An end with no node within the distance is not joined. Driving isn't repaired.
Component filter¶
The filter keeps the largest connected piece of each network and drops the rest: stubs cut off by
the border and small isolated pieces. It counts pieces by edges, and ignores direction (weakly
connected). Dropped edges also leave edge_graph, turn_restrictions, nodes and edge_id_map.
It works on the routable edges only: private_edges are not filtered.
| Key | Default | Does |
|---|---|---|
clip.keep_largest_component |
true |
keep only the largest piece |
clip.min_component_edges |
1 |
also keep every other piece with at least this many edges |
It runs only when a boundary is set (a whole country has real islands) and, for a PBF build, when the edge graph is built. It runs in clip builds too. Monaco:
| Mode | Edges dropped | Pieces dropped |
|---|---|---|
| driving | 79 | 15 |
| walking | 268 | 51 |
| cycling | 225 | 35 |
Because direction is ignored, the kept network can still hold a one-way dead end: an edge you can reach but not leave. Monaco, driving: 25 such edges.
Where the border cuts¶
Build from a PBF. The PBF is cut with osmium (strategy smart by default, complete_ways when
options.build_features: false; options.clip_strategy sets it): every way with a node inside
the boundary is kept whole, so roads that cross the border stick out past it. Then the component
filter removes what doesn't connect. boundary.buffer_m grows the boundary first.
Clip from a parent build. clip.predicate decides which edges are copied:
clip.predicate |
Keeps an edge when |
|---|---|
intersects (default) |
it touches the boundary: roads that cross the border are kept whole |
within |
it lies completely inside: no stubs, but roads that cross the border are lost |
centroid |
its middle point is inside |
duckosm extract always uses intersects.
Validation¶
With validation.enabled, each mode is checked once it is built. A failed check stops the
build unless validation.fail_on_error: false. How to switch it on and what the output looks like:
Check a build.
Check (validation. key) |
Passes when |
|---|---|
assert_single_component |
the largest piece holds at least 99.9% of the edges |
assert_no_stranded_named |
no edge with a name is outside the largest piece |
assert_unique_node_id |
no node_id appears twice in nodes |
assert_way_length_conserved |
no stretch of a kept OSM way is missing while an edge of the same way joins its two ends |
warn_layer_without_structure |
a warning only: edges with layer ≠ 0 but no bridge or tunnel tag |
The first two run only when the component filter ran. assert_way_length_conserved is skipped in a
clip build, which has no ways table.