Skip to main content

Routing

Massif Maps embeds Valhalla: turn-by-turn routing for car, bicycle, pedestrian and more, run either against an HTTP endpoint or entirely offline from tiles on the device. The same service also does map matching — snapping a recorded GPS trace back onto the road network. Indoor routing uses a separate engine, SGRE, over a graph you supply.

Routing is a service you create, a request you create, and a call. Nothing about it touches the map, so a route can be computed with no map view at all.

No hosted service

The CARTO routing endpoints are gone with the rest of the CARTO services. Point customServiceURL at a Valhalla server you run or a public one, or ship offline tiles.

Online

MassifObject router = Massif.object("routing", "router", Spec.of("valhalla-online"));
router.set("customServiceURL", "https://valhalla1.openstreetmap.de/{service}");
router.set("profile", "bicycle");

MassifObject request = Massif.object("routing", "query", Spec.of("request")
.set("projection", "EPSG:4326")
.set("points", new double[][] {{5.7249, 45.1877}, {5.7148, 45.1916}}));

// Free-form Valhalla options are JSON, so they are a call rather than a property.
request.call("setCustomParameter", "language", "fr-FR");

router.callAsync("calculateRoute", route -> {
double metres = route.getDouble("totalDistance", 0);
long steps = route.getLong("instructionCount", 0);
for (int i = 0; i < steps; i++) {
MassifObject step = route.call("getInstruction", i);
Log.i(TAG, step.getString("streetName", "") + ": " + step.getString("instruction", ""));
}
}, request);

Points are [longitude, latitude] in the projection the request names. {service} in the URL is substituted per Valhalla endpoint (route, trace_route, …).

Measured against the public OSM endpoint on a phone: a 1 km walking route came back in 681 ms, 72 positions and 21 instructions.

Offline

Ship a Valhalla tile package (.vtiles) with the app or download it, then point the service at it. No network, no key, and the same request and result shape:

MassifObject router = Massif.object("routing", "router", Spec.of("valhalla-offline")
.set("path", "/sdcard/routing/france.vtiles"));
router.set("profile", "auto");

multi-valhalla-offline takes several packages and picks the one that covers the request, which is what a per-country download UI wants:

MassifObject router = Massif.object("routing", "router", Spec.of("multi-valhalla-offline"));
router.call("add", "/sdcard/routing/france.vtiles");
router.call("add", "/sdcard/routing/switzerland.vtiles");

Building the tiles is Valhalla's own job — valhalla_build_tiles over an OSM extract. The result is a directory or a tar; the SDK reads it as it is.

Offline routing runs on the device's CPU, so a very long route over a large package takes seconds rather than the hundreds of milliseconds a server takes. Keep the packages regional.

Reading the result

totalDistance / totalTimemetres and seconds
pointCount / instructionCountcounts, as properties
getInstruction(i)one maneuver: action, pointIndex, distance, streetName, instruction
getPoints()the whole path as a flat x0,y0,x1,y1,… buffer

The path is deliberately not readable as a property: a 9 km cycling route is 562 positions, which as JSON is a 15 KB string to build, cross and parse. The flat buffer is one crossing and no copy — and it applies no projection, so read projection.name to know what the numbers are.

To draw the route, feed those positions to a line element, or — for many routes at once — through the GeoJSON tiling pyramid. Turn arrows are a feature of their own: maneuver arrows.

Map matching

Same service, a different request. match-request adds the accuracy of the measured points, in metres:

MassifObject request = Massif.object("routing", "trace", Spec.of("match-request")
.set("projection", "EPSG:4326")
.set("accuracy", 10)
.set("points", recordedTrace));

router.callAsync("matchRoute", result ->, request);

Indoor routing

SGRERoutingService routes over a graph the app provides as GeoJSON — corridors, stairs, lifts, with your own edge costs. It is a separate engine from Valhalla and is not tied to OSM data at all. See the SGRE sources and all/modules/routing/ for the request shape.

Routing without the map

The repository also ships routing-lib: Valhalla and its bindings, with no renderer and no map view. If your app only needs routes, that is a much smaller dependency — see the installation guide.

Full spec keys, properties and methods: routing reference.