Skip to content

Network construction

Jip Claassens edited this page Jul 30, 2026 · 1 revision

This is the heaviest step in the model, and the one everything else depends on. It runs per continent and produces a connected, routable and compressed link and node set on disk.

The generic logic lives in Templates/CreateNetwork_T. NetworkSetup selects the origins, destinations and roads per continent and calls that template.

Origins and destinations

Two point sets are attached to the network:

  • Origins are the population weighted settlement centroids of the continent.
  • Destinations are the 1 km land cells of the continent, each with its population, its separated unit, its country and its functional area.

Both are reduced to their coordinates, combined into one point set, and then made unique. That last step matters: a settlement centroid and a grid cell centroid can coincide, and the network only needs one connection point in that case. The unique point set (uq_OD_points) is what actually gets connected to the road network, and relations are kept back to the origin and destination domains.

Building the initial network

Segmentation. Every OSM line is cut into its individual segments with arc2segm. A segment inherits the speed, the direction flag, the connectable flag and the main road class of its parent line. First and last points are converted to Web Mercator and made unique, which gives the node set, and each segment gets a from node and a to node.

Connectivity check. A road network built from raw OSM data contains many fragments that are not attached to anything: a service road behind a fence, a mistagged track, a piece of a network that only continues in a neighbouring extract. Check_Connectiveness_T_seldomain runs connected_parts over the segment graph and then evaluates each connected part against the separated units it touches. A part is kept when it either has more than 1000 nodes inside a separated unit, or is the largest network touching that unit. This test is done per separated unit rather than globally, which is what allows a small island network to survive alongside a continental one. Segments in parts that fail the test are dropped.

Connecting origins and destinations. The surviving segments are handed to connect, together with the unique origin and destination points and a search radius. This does two things at once: it splits road segments where a connection point attaches, and it creates new links from each point to the network. Those new links are flagged with IsOD_connection_road, and they get the low default speed rather than a road speed, since they stand in for the last stretch of local access.

Impedance. Each link gets a length in kilometres from the straight line distance between its endpoints, and a travel time from that length and its speed. Travel time is the impedance used in all routing, expressed in seconds as s_f. The initial link set is written to %LocalDataProjDir%/Network_Setup/<continent>/Linkset_O-...fss, which is Store_Network1.

A container CorrectImpedanceForCrossroads is present, which would add a few seconds of delay per link depending on how many links meet at its endpoints (2 for a bend, 3 for a side road, 4 for a crossing, more for a complex junction). It is configured but currently not added to the impedance.

Compressing the network

A network built segment by segment from OSM has an enormous number of nodes that are not junctions at all. They exist only because a line was digitised in many small pieces. Routing over them is pure overhead, since a traveller has no choice to make there.

CreateMoreEfficientNetwork removes them, in ten iterations (ModelParameters/NumberOfItersForNetworkCleanUp). One iteration does the following:

  1. Mark deletable nodes. A node is deletable when exactly two links meet at it and it is not a connection point for an origin or destination. Connection points must survive, otherwise the origins and destinations lose their attachment.
  2. Find junction free sections. Links between deletable nodes form chains. connected_parts clusters those chains, giving the junction free sections. The links that border a section on either side are the connector links.
  3. Collapse. Each junction free section, together with its two connector links, is replaced by a single link running from the junction at one end to the junction at the other, carrying the summed impedance and the summed length. The result is one direction only when every part of it was one direction.
  4. Guard against cycles. A junction free section that closes on itself has no first and last connector link. Those are detected and excluded, since collapsing them would produce a link from a node to itself.
  5. Clean up. Links to dead ends that are not origins or destinations are removed, links that connect a node to itself are removed, and duplicate links between the same node pair are reduced to one, keeping the shortest impedance and length. All of this only applies to bidirectional links.

Each iteration feeds its result into the next, so successive rounds keep finding new junction free sections as dead ends and duplicates disappear. The iteration count of ten is a pragmatic setting: the link count per iteration is tracked in Iter/nrofarc_na_iter, and by then the reduction has largely converged.

Traceability. Compression would normally make it impossible to say anything about the original OSM links, which is a problem when link flows have to be reported per road class. The model therefore maintains a chain of relational attributes through every iteration, ending in ChangesTracker, which maps each link of the original link set to the link of the final link set that absorbed it. This is what allows the Travel distance proxy to push modelled flows back from the compressed network onto the original geometry.

The final node set, final link set and change tracker are written to disk, which is Store_Network2.

Running it

Network construction is driven by batch/gen_continental_networks.cmd, which calls, per continent:

GeoDmsRun.exe cfg\main.dms /NetworkSetup/Per_Continent/<continent>/Store_Network1

followed by Store_Network2. The two steps have to run in that order, since the compression reads the stored initial link set.

Clone this wiki locally