Vẽ vùng phục vụ cửa hàng bằng isochrone: khách nào tới được trong 10 phút
Trả lời nhanh: vùng phục vụ của một cửa hàng là vùng mà khách đi tới được trong một số phút, theo
đường thật. Bản đồ gọi đó là isochrone (đường đẳng thời). Một lệnh gọi
GET /api/v1/isochrone?at=kinh_độ,vĩ_độ&minutes=5,10,15&mode=motorbike trả về các vùng 5, 10 và 15 phút đi
xe máy dưới dạng GeoJSON, vẽ được ngay trên MapLibre, Leaflet hoặc QGIS.
Thử ngay: bấm lên bản đồ để đặt cửa hàng
Diện tích từng vùng, tính trên trình duyệt từ đa giác API trả về. Lệnh gọi cho cửa hàng vừa đặt:
Mỗi lần đặt cửa hàng, trang gửi một lệnh gọi isochrone tới map.vapp.vn. Lệnh gọi được ghi vào nhật ký truy vấn như mọi lệnh gọi API, xem Chính sách bảo mật.
Vì sao không dùng bán kính
Một vòng tròn bán kính 2 km coi mọi hướng như nhau. Thực tế khách phải đi theo đường: sông, kênh, đường một chiều, cầu và đường cao tốc làm vùng đi được méo đi. Hai cửa hàng cách nhau 2 km qua sông có thể phục vụ hai nhóm khách khác hẳn. Isochrone tính theo mạng lưới đường nên phản ánh điều đó. Bấm vài điểm hai bên sông Sài Gòn trên bản đồ trên để thấy.
Bước 1 — Gọi API isochrone
curl -G "https://map.vapp.vn/api/v1/isochrone" \
--data-urlencode "at=106.6980,10.7725" \
--data-urlencode "minutes=5,10,15" \
--data-urlencode "mode=motorbike"
Kết quả là GeoJSON FeatureCollection, mỗi mốc thời gian một Polygon, mốc lớn nhất đứng đầu. properties.contour là số phút; properties.fill là màu gợi ý.
| Tham số | Ý nghĩa |
|---|---|
at | Vị trí cửa hàng, theo thứ tự kinh độ, vĩ độ (lng,lat). Điểm cách đường tới 500 m vẫn được gắn vào đường gần nhất. |
minutes | Các mốc thời gian, cách nhau bằng dấu phẩy: tối đa 4 mốc, mỗi mốc không quá 120 phút. Quá giới hạn, API trả mã 400 kèm error. |
mode | motorbike (xe máy), car (ô tô), bike (xe đạp), foot (đi bộ). Mặc định là ô tô. |
Bước 2 — Vẽ lên bản đồ của bạn
Đưa thẳng kết quả vào một nguồn GeoJSON, rồi tô màu theo properties.fill:
<link href="https://unpkg.com/maplibre-gl@5.24.0/dist/maplibre-gl.css" rel="stylesheet" />
<script src="https://unpkg.com/maplibre-gl@5.24.0/dist/maplibre-gl.js"></script>
<div id="map" style="height: 480px"></div>
<script>
const store = [106.698, 10.7725]; // [kinh độ, vĩ độ]
const map = new maplibregl.Map({ container: "map", style: "https://map.vapp.vn/style.json", center: store, zoom: 12 });
map.on("load", async () => {
const url = "https://map.vapp.vn/api/v1/isochrone?at=" + store.join(",") + "&minutes=5,10,15&mode=motorbike";
const zones = await (await fetch(url)).json();
map.addSource("zones", { type: "geojson", data: zones });
map.addLayer({ id: "zones", type: "fill", source: "zones",
paint: { "fill-color": ["get", "fill"], "fill-opacity": 0.25 } });
new maplibregl.Marker().setLngLat(store).addTo(map);
});
</script>
Vì mốc lớn nhất đứng đầu, vùng 5 phút được vẽ sau cùng và nằm trên. Gửi khóa trong header x-api-key như mọi API
khác (xem hướng dẫn chuyển từ Google Maps).
Bước 3 — Chuỗi cửa hàng: cửa hàng nào phục vụ khách này
Khi có nhiều cửa hàng, câu hỏi thường gặp là: đơn hàng của khách ở địa chỉ X nên giao từ cửa hàng nào? Dùng API ma trận:
sources là các cửa hàng, targets là khách. Ví dụ với ba cửa hàng ở TP.HCM và một khách ở Landmark 81:
| Hàng | Cửa hàng | lng,lat |
|---|---|---|
| 0 | Bến Thành | 106.6980,10.7725 |
| 1 | Thảo Điền | 106.7320,10.8030 |
| 2 | Phú Nhuận | 106.6800,10.7990 |
curl -G "https://map.vapp.vn/api/v1/matrix" \
--data-urlencode "sources=106.6980,10.7725;106.7320,10.8030;106.6800,10.7990" \
--data-urlencode "targets=106.7220,10.7950" \
--data-urlencode "mode=motorbike"
Mỗi hàng của durations là một cửa hàng theo thứ tự gửi, mỗi cột là một khách; đơn vị là giây. Cửa hàng có số nhỏ nhất ở cột của khách là cửa hàng tới nhanh nhất. Một lệnh gọi trả lời cho nhiều khách cùng lúc: thêm khách vào targets, cách nhau bằng dấu
chấm phẩy.
Bước 4 — Dùng vùng phục vụ để quyết định
- Vùng giao hàng: nhận đơn khi khách nằm trong vùng 15 phút của ít nhất một cửa hàng; kiểm tra bằng API ma trận (thời gian ≤ 900 giây) thay vì vẽ đa giác.
- Mở cửa hàng mới: vẽ vùng 10 phút của mọi cửa hàng hiện có; khoảng trống giữa các vùng là nơi chưa được phục vụ. Vùng chồng lên nhau nhiều là nơi các cửa hàng tranh khách của nhau.
- Phí giao hàng theo vùng: dùng các mốc 5, 10, 15 phút làm ba mức phí thay cho khoảng cách đường chim bay.
Giới hạn cần biết
- Thời gian của isochrone tính theo tốc độ khi đường thông thoáng, chưa tính kẹt xe. Giờ cao điểm, vùng đi được thực tế nhỏ hơn: chọn mốc ngắn hơn, hoặc kiểm tra từng địa chỉ bằng API chỉ đường.
- Vùng được tính trên dữ liệu đường OpenStreetMap. Hẻm chưa có trên bản đồ thì chưa được tính.
- Kết quả giống nhau cho cùng một lệnh gọi được lưu đệm, nên lần gọi lại nhanh hơn.
Ví dụ API trên được kiểm tra tự động với API thật trước mỗi lần cập nhật trang. Diện tích trong công cụ thử là ước tính từ đa giác, dùng để so sánh, không phải số liệu đo đạc.