Construire une carte de zones de livraison
Une zone de livraison n'est pas un cercle. Un cercle tracé à cinq kilomètres traverse la rivière, la gare de triage et l'escarpement comme s'ils n'existaient pas, et il promet une livraison à une adresse que votre chauffeur met quarante minutes à atteindre. Ce que vous voulez, c'est l'ensemble des lieux accessibles en un temps donné par de vraies routes : une isochrone.
Ce guide construit trois zones autour d'un dépôt, les dessine, et y teste l'adresse d'un client. Le code est du TypeScript ordinaire. Pour le câblage React, Next.js, Vue ou Nuxt, partez des recettes par framework et collez-y ces appels.
Trouver le dépôt et dessiner les zones
Partez d'une adresse plutôt que de coordonnées relevées à la main : le même code fonctionne encore
quand le dépôt déménage. Un seul appel d'isochrone renvoie ensuite les trois bandes sous forme de
FeatureCollection GeoJSON, de la plus large à la plus étroite.
const [depot] = await unmap.geocoder.search("1010 8 St SW, Calgary", { limit: 1 });
if (!depot) throw new Error("depot address not found");
const zones = await unmap.router.isochrone([depot.lng, depot.lat], {
minutes: [10, 20, 30],
mode: "auto",
});La longitude d'abord, partout. Si vos zones apparaissent dans l'océan Indien, c'est pour cela.
Quatre contours est le plafond et 120 minutes la durée la plus longue. Les deux reprennent les
limites de service de Valhalla appliquées par la passerelle : en demander plus donne un 400 qui
nomme la règle plutôt qu'une troncature silencieuse. Chaque contour est une passe de calcul
distincte dans le conteneur d'itinéraires, et c'est la raison même du plafond.
Pour un coursier à vélo, passez mode: "bicycle", et pour une camionnette soumise à des limites de
hauteur ou de poids, mode: "truck" avec un profil de véhicule. La documentation des
itinéraires liste les cinq modes.
Les afficher sur la carte
La réponse a déjà la forme attendue par MapLibre : elle devient donc une source telle quelle. Le remplissage d'abord et le contour ensuite gardent les frontières lisibles là où les bandes se chevauchent.
import type { FeatureCollection } from "@unmap/routing";
function drawZones(zones: FeatureCollection) {
unmap.map!.on("load", () => {
unmap.map!.addSource("zones", { type: "geojson", data: zones });
unmap.map!.addLayer({
id: "zones-fill",
type: "fill",
source: "zones",
paint: { "fill-color": "#FF3E9A", "fill-opacity": 0.15 },
});
unmap.map!.addLayer({
id: "zones-line",
type: "line",
source: "zones",
paint: { "line-color": "#FF3E9A", "line-width": 1 },
});
});
}Tester une adresse dans une zone
Aucun point de terminaison ne répond à « cette adresse est-elle dans ma zone de livraison », et il ne devrait pas y en avoir : la réponse dépend de vos règles d'affaires, pas du réseau routier. Géocodez l'adresse, puis demandez à la carte dans quelle bande le point tombe.
async function bandFor(address: string): Promise<number | undefined> {
const [customer] = await unmap.geocoder.search(address, { limit: 1 });
if (!customer) return undefined;
const pixel = unmap.map!.project([customer.lng, customer.lat]);
const [hit] = unmap.map!.queryRenderedFeatures(pixel, { layers: ["zones-fill"] });
return hit?.properties?.contour as number | undefined;
}contour est la valeur en minutes de la bande : la fonction renvoie donc la tranche de temps de
trajet plutôt qu'un simple oui ou non. Elle lit la carte rendue, ce qui veut dire qu'elle ne répond
que pour les zones actuellement dessinées, et seulement dans le navigateur. Pour le même test sur
un serveur, conservez la FeatureCollection et faites-y une vérification point-dans-polygone avec
une bibliothèque de géométrie.
Ce que ces zones sont et ne sont pas
Une isochrone est un modèle du réseau routier, pas une promesse sur un mardi après-midi. Elle ne sait rien de votre quai de chargement, de la pause du chauffeur, de la zone scolaire à 15 h ni de la circulation en temps réel, car le graphe d'itinéraires ne contient aucune donnée de trafic en direct. Traitez les bandes comme la forme de votre zone de service et gardez la promesse faite au client comme une décision d'affaires par-dessus.
La couverture s'arrête à la frontière. Un dépôt près de Windsor obtient une zone qui s'arrête net à la rivière au lieu d'atteindre Détroit, parce que le graphe d'itinéraires est l'extrait du Canada.
Pour aller plus loin
- Zones de temps de trajet pour la version la plus simple
- API d'itinéraires pour les modes, les profils de camion et les paramètres
- Frameworks pour câbler cela dans React, Next.js, Vue ou Nuxt