Snapping via-points to most "obvious" street

In my app I am trying to route a simple trip that looks like A (start) → B → C (finish). However when moving map markers (pins) on the screen it is impossible to set it precisely because of the screen resolution etc. So if I put a pin B somewhere, for this example let’s say it is on a highway, I acutally get a coordinates that are somewhere around, maybye even hundred meters off. This makes a mess in the routing: if it is off the highway, the routing algorithm wants to get off the highway, pass some local road (where the point B actually is) and then get back to the highway on the nearest entry point.

So the problem is NOT that the points are not matched to the road network. They are mached to roads, but to wrong ones, to minor, small roads - in an urban area there are some roads everywhere so mathing to a paved road per se is not a problem. See here, where a viapoint 8 is just a bit off the highway and it wants to exit the highway and get back a moment later:

Technically, i want to correct B to some alternative B’, that would provide me the shortest and most smooth (with least turns) path from A to C. Or maybe just snapping to a bigger road would be enough.

Is there some sort of API parameter to achieve this?

All I was able to come up with is to try various points around B and pick the shortest result. This is definitely not the optimal solution :frowning:

Have tou tried using geohashes instead of co-ordinates?

Have a look into the Map Matching API: Documentation - GraphHopper Directions API

Can you be please more specific how should I procede? I have updated the question. Being not snapped to the road network is not a problem. Problem is that the points are snapped to roads, but not to the intended ones.

The Map Matching API requires points as input like the Routing API but it handles them like candidates (“GPS measurements”) that can be rejected to return a “more likely” (cost-reduced) route. The problem for your use case might be that a too large distance between points might be interpreted as an interrupted sequence leading to an error.

1 Like

specify the road type when tying the road

 snap = locationIndex.findClosest(, point.lon, new OriginTypeEdgeFilter(edgeFilter,
                        roadClassEnc, point, radius, roadClass));


public class OriginTypeEdgeFilter implements EdgeFilter {

    private final EnumEncodedValue<RoadClass> rcEnc;
    private final Circle pointCircle;
    private final EdgeFilter edgeFilter;
    private final RoadClass roadClass;

    public OriginTypeEdgeFilter(EdgeFilter edgeFilter, EnumEncodedValue<RoadClass> rcEnc, GHPoint point, double radius, RoadClass roadClass) {
        this.edgeFilter = edgeFilter;
        this.rcEnc = rcEnc;
        this.pointCircle = new Circle(, point.lon, radius);
        this.roadClass = roadClass;

    public boolean accept(EdgeIteratorState edgeState) {
        if (!edgeFilter.accept(edgeState)) {
            return false;
        BBox bBox = createBbox(edgeState);
        if (!pointCircle.intersects(bBox)) {
            return false;
        return edgeState.get(rcEnc) == roadClass;

    private static BBox createBbox(EdgeIteratorState edgeState) {
        PointList geometry = edgeState.fetchWayGeometry(FetchMode.ALL);
        BBox bbox = new BBox(180, -180, 90, -90);
        for (int i = 0; i < geometry.size(); i++) {
            bbox.update(geometry.getLat(i), geometry.getLon(i));
        return bbox;
1 Like

Is it possible to at least avoid unpaved roads in the snapping feature?

This is currently not possible.

There is the snap_prevention option: Documentation - GraphHopper Directions API

However, this won’t let you prevent snapping to unpaved roads

Currently supported values are motorway, trunk, ferry, tunnel, bridge and ford.

But you could implement this using the same approach.

1 Like
Powered by Discourse