Road/Extraction

Blog/ 2026-10-07

How to merge a vector road diff into a routing graph without breaking topology

A clean road diff is only half the job. The other half is getting it into a graph that already has turn restrictions, one-way flags, and years of edits baked into it, without leaving behind a dangling node or a duplicate edge that sends routes down an alignment that no longer exists.

Most production teams learn this the hard way: a batch of new segments goes in, the import runs clean, and three weeks later support tickets start showing up for a detour that routes drivers into a field. The diff was right. The merge wasn't.

Why a straight import breaks the graph

A vector diff describes geometry and attributes. It does not know about your graph's internal node IDs, your existing edge splits, or which intersections are already snapped to a traffic signal record. When you drop new LineStrings into a routing graph without reconciling those things first, three failure modes show up over and over:

  • Orphaned nodes. A new segment ends near an existing intersection but not exactly on it, so the router sees two nodes a few centimeters apart instead of one. The segment connects to nothing.
  • Duplicate edges. A changed segment that replaces an old alignment gets added alongside the old one instead of in place of it, and now the graph has two parallel edges with different weights competing for the same route.
  • Lost attributes. The old edge carried a turn restriction, a bridge height limit, or a one-way flag. The new edge replacing it doesn't, unless someone carries that forward on purpose.

This is the real meaning of node-edge conflation: matching the new diff's nodes and edges against the graph's existing nodes and edges before you commit anything, not just dropping geometry on top and hoping the snapping tolerance saves you.

A merge sequence that holds topology together

A sequence that works in practice, roughly in this order:

  1. Buffer-match endpoints first. Before touching edges, run every new segment's endpoints against existing nodes within a small tolerance, something like 1 to 3 meters depending on your source GSD. Anything that matches gets snapped to the existing node ID, not a new one.
  2. Flag unmatched endpoints for review. An endpoint with no match nearby is either a genuinely new intersection or a geometry offset from imagery alignment. Don't auto-create a node here. Queue it.
  3. Resolve edge replacement before edge addition. If the diff marks a segment as changed rather than new, pull the old edge's attribute set (turn restrictions, access class, surface type) and carry forward whatever the new geometry doesn't override. Then retire the old edge in the same transaction that adds the new one, so there's never a window where both exist.
  4. Re-run connectivity checks on the affected subgraph only. You don't need to validate the whole national graph every quarter. Isolate the bounding area touched by the diff, run a connected-components check on it, and confirm nothing got split off from the rest of the network.
  5. Hold a rollback point. Keep the pre-merge graph state addressable so a bad batch can be reverted without re-pulling the entire region.

None of this requires exotic tooling. A spatial join, a transaction boundary, and a connectivity check cover most of it. What it does require is treating the merge as its own step with its own QA pass, separate from the extraction that produced the diff.

What the diff format should give you upfront

The merge above gets a lot easier if the diff itself ships as a proper vector layer with clear change flags, added, changed, or removed, rather than a flattened image you have to re-vectorize yourself. That's the whole point of pulling a structured quarterly diff instead of re-running extraction on a full scene: you're merging known changes into a known graph, not reconciling two independent full networks against each other.

If you're evaluating how a vector road diff actually gets delivered, before you build a merge pipeline around it, the Road Extraction overview lays out what ships each quarter and in what format.

Pull a sample diff over your next problem corridor and see how it sits against your current graph before the next cadence hits.

Start a project