How to best match GraphHopper's roads against external source's roads?

Currently using TomTom’s real-time traffic data in the form of Vector Flow Tile to update the values of GraphHopper’s graph’s edges. TomTom’s lists of coordinates, or the geometries, representing roads are put through the map-matching algorithm to increase the accuracy of the coordinates, then each of the geometries’ corresponding GraphHopper’s roads are located using LocationIndex. All in all, the process of locating edges is not an issue.

The difficulty we’re having is the inaccuracy of the speed value (the updated speed value from the real-time traffic data) resulting from the difference between what TomTom defines as a unit of road and what GraphHopper defines as a unit of road. For example,

  • Let’s say TomTom regards road A to span 20km, but GraphHopper divides this road into two different roads A and B, spanning 10km and 10km, respectively. Then, the real-time traffic data is too generalized and doesn’t reflect the granularity of the localized traffic.

  • Inversely, TomTom regards road A to span 10km, but GraphHopper regards this as a part of a larger road B spanning 20km. Then, there the real-time traffic data won’t cover the rest of the road, since once updated edge will be excluded from any further updates to prevent duplicate updates.

I hope my explanation is clear. Is there an efficient way to overcome this issue?

Are you trying to use the TomTom traffic data with GraphHopper roads generated from OSM? I’m unsure what you mean saying GraphHopper is dividing roads into two separate roads. Whether or not the roads are divided depends on the way you are generating the graph?

IANAL, but make sure that TomTom’s license terms actually allow this. Mixing OSM and commercial data is usually a no-go for these vendors.

Could you clarify what you mean by “it depends on the way you are generating the graph”? Do you mean I should generate the graph in the way that caters to the way TomTom segments roads?

To provide more context, I’m using a similar approach as “graphhopper-traffic-data-integration” by karussell (sorry I can’t put a hyperlink since the post is only letting me post up to 2 links) where you find a coordinate of TomTom’s road segment that coincides with that of GraphHopper’s and updating the speed value of that edge.

            QueryResult qr = locationIndex.findClosest(, point.lon, EdgeFilter.ALL_EDGES);
            if (!qr.isValid()) {
                //"no matching road found for entry " + entry.getId() + " at " + point);

            int edgeId = qr.getClosestEdge().getEdge();
            if (edgeIds.contains(edgeId)) {
                // TODO this wouldn't happen with our map matching component

            EdgeIteratorState edge = graph.getEdgeIteratorState(edgeId, Integer.MIN_VALUE);

The issue with above approach is the difference segmentation of roads by TomTom and GraphHopper. Here is a good example of the differences in TomTom’s road segment and GraphHopper’s road segment (Edge ID #2349332). There is an overlap on a road called “Alexmuir Boulevard” where the speed would be accurately updated, but the rest of the road would not.

I’m thinking maybe some sort of a spatial interpolation technique where you either split or merge TomTom’s geometries to match GraphHopper’s road segments depending on whether TomTom’s road encompasses GraphHopper’s or vice versa, but I’m not quite sure if this is the right approach or fundamentally flawed.

In order to open up an account with TomTom, you have to go through the process of explaining the use cases in which we explicitly explained the integration of TomTom’s data into OSM. The fact that they approved it tells me they are OK with it.