router.get(
"/:id",
async function (req, res) {
try {
if (!req.params?.id) {
return res.status(400).send({
success: false,
msg: "id field is required",
});
}
UserLocation.findAll({
attributes: [
["latitude", "lat"],
["longitude", "lng"],
["created_at", "time"],
],
})
.then(async (value) => {
let _cordinates = removeReference(value);
let fullroute = [];
if (_cordinates.length > 24) {
for (let i = 0; i < _cordinates.length; i += 24) {
const batch = _cordinates.slice(i, i + 24);
let _routesPoints = await getRouteFromGoogleMapsAPI(batch);
fullroute = fullroute.concat(_routesPoints);
}
} else {
fullroute = await getRouteFromGoogleMapsAPI(_cordinates);
}
return res.status(200).send({ success: true, data: fullroute });
})
.catch((error) => {
return res
.status(400)
.send({ success: false, msg: "no Locations found" });
});
} catch (e) {
console.log(e, ":::error");
return res
.status(400)
.send({ success: false, msg: "no Locations found" });
}
}
);
// ============ GET LAT LNG OF FULL PATH ==================
async function getRouteFromGoogleMapsAPI(points) {
if (points.length < 2) {
return [];
}
let waypoint = "";
points.forEach((e, i) => {
if (i != 0 && i < points.length - 1) {
waypoint = waypoint + `${e.lat},${e.lng}|`;
}
});
const url = `https://maps.googleapis.com/maps/api/directions/json?origin=${
points[0].lat
},${points[0].lng}&destination=${points[points.length - 1].lat},${
points[points.length - 1].lng
}&waypoints=${waypoint}&key=${
config.GoogleMapsApiKey
}&travelMode=WALKING&polylineQuality=HIGH_QUALITY`;
console.log("URL ::::::::- n", url);
const response = await axios.get(url);
if (response.data && response.data.routes.length > 0) {
const polyline = response.data.routes[0].overview_polyline.points;
return decodePolyline(polyline);
} else {
return [];
}
}
function decodePolyline(encoded) {
let points = [];
let index = 0,
len = encoded.length;
let lat = 0,
lng = 0;
while (index < len) {
let b,
shift = 0,
result = 0;
do {
b = encoded.charCodeAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
let dlat = result & 1 ? ~(result >> 1) : result >> 1;
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.charCodeAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
let dlng = result & 1 ? ~(result >> 1) : result >> 1;
lng += dlng;
points.push({ lat: lat / 1e5, lng: lng / 1e5 });
}
return points;
}
I have a route calculation system where I retrieve latitude and longitude data points from a database and then use the Google Maps Directions API to generate a route between these points. The purpose is to display the route on a map, showing the path passing through actual roads.
Current Implementation:
-
Database Query:
-
I retrieve user location data (latitude, longitude, and timestamp) from a database using
UserLocation.findAll()
. -
The data is processed into batches if there are more than 24 points, to avoid exceeding the Google Maps API’s waypoint limit.
-
-
Google Maps API Call:
- I use the
getRouteFromGoogleMapsAPI
function to send the points to the Google Maps Directions API. This function creates a route between the first and last point in each batch, with waypoints for the intermediate points.
- I use the
-
Route Representation:
-
If I use the
getRouteFromGoogleMapsAPI
function, the route is generated but sometimes appears with side paths and circular routes between distant points, along with actual roads. -
If I skip the API call and use the points directly, the route simply connects the points in a straight line, which doesn’t follow the actual roads.
-