Reachable ranges

Request Access

Important note Calculate Reachable Range is in Private Preview and unavailable on a Freemium or Pay As You Grow (PAYG) basis. Your API key needs access to it, and its API documentation requires a TomTom enterprise login. Click the Request Access button above to contact our Sales team. A call with a key that lacks the access rejects with INSUFFICIENT_PERMISSIONS, and the error names the API. See A key refused access.

calculateReachableRanges computes the area reachable from an origin within a travel time or distance budget, and returns one GeoJSON polygon per budget. Several budgets from one origin give concentric bands. calculateReachableRange computes a single range.

The demo below shows 10, 20 and 30 minutes of driving from two stations, drawn by the reachable ranges module in the map’s own colours.

Budget types

Each range takes a budget of { type, value }:

  • timeMinutes – Travel time, in minutes
  • distanceKM – Distance, in kilometres

budgetTypes and the BudgetType type list them. budgetUnits holds the unit of each. All three come from @tomtom-org/maps-sdk/core, so your own labels can read like the module’s titles:

import { budgetUnits } from '@tomtom-org/maps-sdk/core';
const title = `${budget.value} ${budgetUnits[budget.type]}`; // '30 min', '50 km'

Example

import { ReachableRangesModule, TomTomMap } from '@tomtom-org/maps-sdk/map';
import { calculateReachableRanges } from '@tomtom-org/maps-sdk/services';
const origin: [number, number] = [4.9041, 52.3676];
const result = await calculateReachableRanges([
{ origin, budget: { type: 'timeMinutes', value: 10 } },
{ origin, budget: { type: 'timeMinutes', value: 20 } },
{ origin, budget: { type: 'timeMinutes', value: 30 } },
]);
const map = new TomTomMap({ mapLibre: { container: 'map', center: origin, zoom: 9 } });
const rangesModule = await ReachableRangesModule.create(map);
await rangesModule.show(result); // titled '30 min', '20 min', '10 min'
  • result.features – One polygon per range the service could calculate, in request order.
  • result.bbox – The bounding box of them all.
  • feature.properties – The request it was calculated with (origin, budget, vehicle, …), without the API key or any other common service parameter.
  • Ranges are calculated one after another, not in parallel, to stay within the service’s rate limit.

The same call runs in Node.js, with no map. The code below mixes a time and a distance budget and prints each polygon’s vertex count and bounding box. Change the address or a budget’s value to compare ranges:

import { type BBox, budgetUnits, TomTomConfig } from '@tomtom-org/maps-sdk/core';
import { calculateReachableRanges, geocodeOne } from '@tomtom-org/maps-sdk/services';
import { API_KEY } from './config';

TomTomConfig.instance.put({ apiKey: API_KEY });

const formatBBox = (bbox: BBox) => bbox.map((value) => value.toFixed(3)).join(', ');

(async () => {
    const origin = await geocodeOne('Domplein 9, Utrecht');
    console.log(`Origin: ${origin.properties.address.freeformAddress}\n`);

    const ranges = await calculateReachableRanges([
        { origin, budget: { type: 'timeMinutes', value: 30 } },
        { origin, budget: { type: 'distanceKM', value: 25 } },
    ]);

    for (const range of ranges.features) {
        const { budget } = range.properties;
        const vertices = range.geometry.coordinates.flat(1).length;
        console.log(
            `${budget.value} ${budgetUnits[budget.type]}: ${vertices} vertices, bbox [${formatBBox(range.bbox)}]`,
        );
    }

    if (ranges.bbox) console.log(`\nBoth ranges fit in [${formatBBox(ranges.bbox)}]`);
})();

Range options

Besides vehicle, costModel and when, which work as in calculateRoute within the limits below, a range takes:

  • maxFerryLengthMeters – Leaves out ferries longer than this, so a long crossing doesn’t stretch the range.
  • smoothing – How much to smooth the polygon’s boundary. One of 'none', 'weak' or 'strong' (default).

Display on the map

ReachableRangesModule draws the result unchanged. Its guide covers fill styles, band colours, titles, events and every setting.

const ranges = await ReachableRangesModule.create(map, { fill: { style: 'inverted' } });
await ranges.show(result);

Ranges that can’t be calculated

If the service answers a range with a 4xx error, calculateReachableRanges skips it instead of rejecting the batch. The service answers a 400 with the API error code MAP_MATCHING_FAILURE for an origin it can’t match to a road, such as a point at sea.

  • result.features can be shorter than the request array, or empty. Match each feature to its request through properties.budget and properties.origin, and treat an empty result as “no range from this origin”.
  • calculateReachableRange rejects with that error instead.
  • A 401, 403, 404 or 429 response, any 5xx, a network failure, an aborted signal and a request the SDK’s validation rejects reject the batch. They would fail every other range too, such as an outage or a commonBaseURL that points to the wrong host.

Cancelling a batch

calculateReachableRanges takes one signal for the whole batch as its second argument. Aborting it cancels the range in flight and skips the rest. When a new origin replaces the previous one, run the batch through createLatestRequest, as the reachable ranges example does on every map click:

import type { HasLngLat } from '@tomtom-org/maps-sdk/core';
import { calculateReachableRanges, createLatestRequest } from '@tomtom-org/maps-sdk/services';
const latestRanges = createLatestRequest();
const showRanges = async (origin: HasLngLat) => {
const ranges = await latestRanges.run((signal) =>
calculateReachableRanges(
[10, 20, 30].map((value) => ({ origin, budget: { type: 'timeMinutes', value } })),
{ signal },
),
);
if (!ranges.current) return; // a newer origin retired this batch
await rangesModule.show(ranges.value);
};

Unsupported options

The types leave out these routing parameters. For untyped callers, validation rejects them instead of returning a range computed without them.

ParameterUse instead
vehicle.state.headingOmit it, or use calculateRoute, which accepts it
costModel.avoid: 'alreadyUsedRoads'Drop that entry. The other avoidables are accepted
costModel.avoidAreasOmit it. This endpoint can’t avoid areas
when: { option: 'arriveBy', date }Use when: { option: 'departAt', date }, or omit when entirely

API reference

  • Reachable ranges module – Drawing the ranges: fill styles, colours, labels, events and every setting
  • Vehicle configuration – Weight and restrictions of the vehicle a range is calculated for
  • Geometries – Polygons of your own, styled per feature rather than as bands