A simple way to find places along the route using Google maps API

Yashwant Gaikwad
7 min readOct 1, 2020

--

We can use Google Maps API for various purposes in our projects which can be on any platform (IOS, Android, web), in this article my main focus is the web. Before going any further I assume that you have a basic understanding of Javascript and Google Maps API. we can search for places using google places API by giving parameters like location(around which you want to search for places), category of places(lake, pool, restaurant, etc), radius, and more. this way you can only find places around one location.

There isn’t any specified way in google Maps API documentation to search places along the route but using some simple methods and logic we can achieve it very easily.

there are few simple steps

  1. get the route between two points using directions API
  2. draw a latitude-longitude bound around the route
  3. find all related places along the route
  4. find places which fall into the polygon of LAT-LNG bound

get the route between two points

first, we have to initialize the map in our page using the following code

HTML

<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta charset="utf-8" />
<title>Directions Service</title>
<style>
#map {
height: 100vh;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
</body>

js

let map;function initMap() {
map = new google.maps.Map(document.getElementById("map"), {
zoom: 8,
center: { lat: 19.07596, lng: 72.87764 },
});
}

loading script

// for static loadng<script defer
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>
//for dynamic loading// Create the script tag, set the appropriate attributes
var script = document.createElement('script');
script.src = 'https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap';
script.defer = true;
// Attach your callback function to the `window` object
window.initMap = function() {
// JS API is loaded and available
};
// Append the 'script' element to 'head'
document.head.appendChild(script);
initial map

use google directions API for the route

function initMap() {
var directionsService = new window.google.maps.DirectionsService();
var directionsRenderer = new window.google.maps.DirectionsRenderer();map = new google.maps.Map(document.getElementById("map"), {
zoom: 8,
center: { lat: 19.07596, lng: 72.87764 },
});
var request = {
origin: "mumbai",
destination: "pune",
travelMode: "DRIVING"
};
directionsService.route(request, function (result, status) {
if (status == "OK") {
directionsRenderer.setDirections(result);
}
}
directionsRenderer.setMap(map);
}
the route between A and B

draw a latitude-longitude bound around the route

This is the important step, we can draw a polygon on the map using google.map.polygon but we don’t want a simple polygon like a rectangle or triangle, we want a polygon which is exactly like a blue route shown in the above image and covers the whole route.

to implement that I build a small and simple algorithm that takes all waypoints between route and returns an array having all the points need to generate the latitude-longitude bound.

When sending a directions request to the API, you receive a response consisting of a status code, and a result, which is an object.

we need overview_polyline from this response object which contains all the waypoints on the route in an encoded format and can be accessed using result.routes[0].overview_polyline

wwlsBg|x{LvLsUh@uH~BgFf]aZnJ{K|Fo\bAqLuEcKuTca@uIaObAgAfC_GvE}CtI_AlHgBbI{JzC_QtEwP`Quc@rNy_@x@wLvD_KbMkM~HcF@qC_FcSw@cEmEoQkPin@{HqZuLix@qMw}@kFiWeFuLeHuHkKeKyByDy@yDfAa[`Dkw@lF_aBpA_TnHStBnAvJr@ns@c@nJ_Ajc@u^fTqQxJ{Cto@{E~OgAxDuARoHMkEzYs^lJeNlCiU|Cs]mA{MaWef@gPkXqn@qdAaG{Ke@iIpAoFtIwMdOaUvn@sfAf`@om@lP_ZbGeS`LeU`Tqa@ll@cm@rXwWvP_Ip`@ye@vo@ok@|}A}sArE_BtL]`|@bUlPrEtOz@puAuVlQwEnQgK`b@k^~c@{g@l[{]~SmZvKkUzp@azArGsHpLwEbTuFv|@ib@tqBe`ArbAqe@f`@}QjMsI~p@a`A|l@{|@`J}TbI_WpG{PvGiHl_@kVbi@}|@l[kRpZsPff@qWdTeNrGqMbTc|@xMei@zHuMrNcJ|RkJ`Zid@rRkJ~EiLc@uKkBwNdF{XtEiTtDwJrHmHFsBaNwOg@iD|@oCxFaBrOqBjQ}HnDkCKgBmFuJ}HoEXaBvDkDcCwFyOkM_DqG}PuJ{@aB\sB|Bs@dQnHlH`GjHpMxFzHrCt@|BsA_@kE}KuDqCsE{DaL[wDaI{H_FyBsH_Gg@eMfAeDzNcIzViLpc@eItAsCoBiIzD_NAkE{MgOiAeI_DgLiD_HeVkN}JgH}CoJmAcJeBsf@f@u[bEyUvKwVzNs]vEgOzGmU`CsTjBqLjCcCpGg@hRAj]aJd[fBrb@hF|E\vLyCdF_IJc_@nBmPxEwRt@qLoC{Rei@uzBu[ozCyHou@aIkm@}Kwn@eDgV@yKdBaNxHeStKsLhTmJdMaBtYiAvMsDrRoNdAgBn]gh@hQg_@rh@ev@fd@sr@|Kgt@xUqmBT{M_AmJ_UekA}Dm]qDeNoMwi@eHqf@yJot@VwMdCsKlf@_xAh^igAn@aKs@kQ`@iKbCiJzLaOn{@s^hIcFlNePja@wg@b`@e]xlAqdA|DuIdAeHRyt@~Bsr@rAaAhIm@hRuFv|@}WdTuGp}@kW~qAc`@b_B}c@ju@iS~YeIl@yCgAoNbA{YtJmW`Ak`@bDiQjAqE^mCnAgd@xE_`@~No]rM}PjUiVx\}]tTgOdD}DnAeGlCsApIs@zZqJzo@ib@paAio@zJiLdy@cpAdEcM~@eFvEoYvDsOtKhEhBmDtJgGzT_ItBy@^sDj@sA

decode this polyline using the NPM package google-polyline

in order to use the NPM package in browser, I’m using browserify

var polyline = require( ‘google-polyline’ )
polyline.decode( result.routes[0].overview_polyline )

this is a decoded polyline

// these are all waypoints between two locations
[
[19.07596, 72.87764],
[19.07376, 72.88126],
[19.07355, 72.88281],
[19.07291, 72.88397],
.
.
.
[18.52082, 73.85554],
[18.52044, 73.85686],
]

assign it to a variable

let waypoints = []function initMap() {
.
.
.
directionsService.route(request, function (result, status) {
if (status == "OK") {
directionsRenderer.setDirections(result);
waypoints = polyline.decode(result.routes[0].overview_polyline);
}
}
directionsRenderer.setMap(map);
}

Algorithm to generate latitude-longitude bound

If we have to add distance in latitude or longitude there is a mathematical formula

for latitude : new latitude = latitude + (distance / R) * (180 / pi)

for longitude : new longitude = longitude + (distaance/ R) * (180 / pi) / cos(latitude * pi/180);

where

distance = distance you want to add (meters)

R = radius of the earth (meters)

pi = 3.14

for this method, we only need to add distance in latitude. because latitude is horizontal additional distance change is going to be vertical

positive distance(eg. 1000) for an upward change

negative distance(eg. -1000) for downward change

marker position after 1000 meters of distance change

the code below takes latitude and returns upper and lower latitude with a difference of specified meters

function PolygonArray(latitude) {
const R = 6378137;
const pi = 3.14;
//distance in metersconst upper_offset = 1000;
const lower_offset = -1000;
Lat_up = upper_offset / R;
Lat_down = lower_offset / R;
//OffsetPosition, decimal degreeslat_upper = latitude + (Lat_up * 180) / pi;
lat_lower = latitude + (Lat_down * 180) / pi;
return [lat_upper, lat_lower];}

by passing the latitude of waypoints which we stored earlier we get the upper and lower bound of the route. Then store upper co-ordinates in an array named UpperBound and lower co-ordinates in an array named LowerBound (coordinates should be like { lat: latitude, lng: longitude })we have to reverse the LowerBound in order to set the coordinates in the correct position and draw the exact polygon

function PolygonPoints() {let polypoints = waypoints
let PolyLength = polypoints.length;
let UpperBound = [];
let LowerBound = [];
for (let j = 0; j <= PolyLength - 1; j++) {
let NewPoints = PolygonArray(polypoints[j][0]);
UpperBound.push({ lat: NewPoints[0], lng: polypoints[j][1] });
LowerBound.push({ lat: NewPoints[1], lng: polypoints[j][1] });
}
let reversebound = LowerBound.reverse();let FullPoly = UpperBound.concat(reversebound);return FullPoly;
}

assign waypoints to variable polypoints, then assign empty arrays to UpperBound and LowerBound respectively. then loop through polypoints and call PolygonArray function and push values returned by it to UpperBound and LowerBound.then reverse lowerbound and assign it to reversebound after that concat UpperBound and reversebound and return It as FullPoly

FullPoly contains all the co-ordinates required to draw the polygon around the route

Drawing polygon on the map

using google maps API’S google.maps.Polygon method we can draw a polygon on a map

let waypoints = []function initMap() {
.
.
.
directionsService.route(request, function (result, status) {
if (status == "OK") {
directionsRenderer.setDirections(result);
waypoints = polyline.decode(result.routes[0].overview_polyline);
}
}
const PolygonCoords = PolygonPoints();
const PolygonBound = new google.maps.Polygon({
paths: PolygonCoords,
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35,
});
//to hide polygon set strokeOpacity and fillColor = 0PolygonBound.setMap(map);
directionsRenderer.setMap(map);
}
LAT-LNG bound around the route (with directions off)
with directions on

find all related places along the route

to find all places along the route we have to loop through waypoints and search for places around the respective coordinate, but if we consider all coordinates in waypoints then you can imagine how much requests you are going to make to places API. you will end up bankrupt for making that many requests for a single route each time JK :-) we can avoid that by incrementing the loop by more than 20 points or more and setting the radius as much as possible so that we can get results in very few requests, to find places the code is as follows

function initMap() {
.
.
.
service = new google.maps.places.PlacesService(map);
for(let j = 0;j< waypoints.length;j+=40){service.nearbySearch({
location: { lat:waypoints[j][0], lng:waypoints[j][1] },
radius: '20000',
type: ['restaurant']
}, callback);
function callback(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
new google.maps.Marker({
position: results[i].geometry.location,
map,
title: "Hello World!"
});
}
}
}
}
}

in the code,j is incrementing by 40 points and the radius is 20000

all places around the route

find places which fall into the polygon of LAT-LNG bound

there’s a method in google maps API called containsLocation using which we can find out if a given coordinate is Inside the polygon or not containsLocation needs two parameters coordinate and polygon

function initMap() {
.
.
.
service = new google.maps.places.PlacesService(map);
for(let j = 0;j< waypoints.length;j+=40){service.nearbySearch({
location: { lat:waypoints[j][0], lng:waypoints[j][1] },
radius: '20000',
type: ['restaurant']
}, callback);
function callback(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
if(google.maps.geomet
ry.poly.containsLocation(results[i].geometry.location,PolygonBound) == true) {
new google.maps.Marker({
position: results[i].geometry.location,
map,
title: "Hello World!"
});
}
}
}
}
}
}

in the above code, we are looping through results returned by places API if that result is in the polygon then placing the marker for that position

places along the route

phew, now you can find places between any route.

GitHub repo

note: you can also use other APIs for places search like Foursquare API

--

--