Hands On
100DaysOfCode

Solutions: Day 61-65 #100DaysOfCode

By Shruti Kuber | 08 June 2020

Try HERE Maps

Create a free API key to build location-aware apps and services.

Get Started

Let's get started with week 13 of #100DaysOfCode with HERE and dive further into the Routing v7 API.
If you have no idea what I'm talking about, take a look at this blog post which will tell you everything about #100DaysOfCode. If you have missed the solutions for days 0-60, you can read them in the previous blogs posts or on our YouTube channel.
Let's begin!

Day 61/100

Let's say you want to limit your delivery area or want to limit your travel to 10 km around you. Can you simply draw a circle of radius 10 Km and any place Within the circle can be reached by driving for 10 Km or less? This is what we will be checking with day 61. We have already covered drawing a circle on day 14 of 100DaysOfCode. Click on any point on the circumference of this circle and get the route to that point. Also note the total distance covered by this route.


var circle10Km = new H.map.Circle({lat:52.4571601,lng:13.3806395}, 10000);
// Add the circle to the map:
map.addObject(circle10Km);

// Get an instance of the routing service version 7:
var router = platform.getRoutingService();

// Create the parameters for the routing request:
var routingParameters = {
  waypoint0:"52.4569927,13.380545",
  waypoint1:"52.47911050,13.5236065",// point on the circumference of the circle
  mode:"fastest;car;traffic:enabled",
  representation: "display",
  routeAttributes:'summary'
};
  
// Define a callback function to process the routing response:
var onResult = function(result) {
  console.log(result);
  var colors =["green","orange","yellow","red"]
  result.response.route.forEach(route =>{
  var lineString = new H.geo.LineString(),
    routeShape = route.shape,
    polyline,
    startMarker,
    endMarker;
  
  // Retrieve the mapped positions of the requested waypoints:
  startPoint = route.waypoint[0].mappedPosition;
  endPoint = route.waypoint[1].mappedPosition;

  routeShape.forEach(function(point) {
    var parts = point.split(',');
    lineString.pushLatLngAlt(parts[0], parts[1]);
  });


  polyline = new H.map.Polyline(lineString, {
    style: {
      lineWidth: 4,
      strokeColor: colors[result.response.route.indexOf(route)]
    }
  });

  startMarker = new H.map.Marker({
    lat:route.waypoint[0].mappedPosition.latitude,
    lng:route.waypoint[0].mappedPosition.longitude 
  });

  endMarker = new H.map.Marker({
    lat:route.waypoint[1].mappedPosition.latitude,
    lng:route.waypoint[1].mappedPosition.longitude 
  });

  // Add the polyline to the map
  map.addObjects([polyline,startMarker,endMarker]);
  // And zoom to its bounding rectangle
  document.getElementById("panel").innerHTML += 'Route '+(result.response.route.indexOf(route)+1)+ ' Distance: '+ route.summary.distance/1000 +' Km'+ `
`; map.getViewPort().setPadding(100, 0, 0, 0); map.getViewModel().setLookAtData({ bounds: polyline.getBoundingBox() }); map.getViewPort().setPadding(0, 0, 0, 0); }); }; var onError = function(error) { alert(error.message); }; router.calculateRoute(routingParameters, onResult, onError);

You will notice that these routes are definitely longer than 10 Km. This is even more evident if the center of your cirle is near a water-body. You definitely cannot drive across water and it takes much longer to cross it from a bridge which may or may not be near you. This leads us to the search of places reachable by driving 10 Km or less

reachable circle

Day 62/100

Isoline routing is the answer to the problem from day 61. It returns all the places which can be reached by driving or walking a certain distance. It basically gives us the answer to - Is the road network to this place within a distance of 10 Km? The The Calculate Isoline endpoint of the Routing API needs a starting point, a range which will be 10000 meters in this case and a range type- distance. The routing engine will return a polyline that connects all the end points of all routes starting from the start and at a distance of 10 Km from it. Laying the Isoline polyline on the circle from the previous example, you will see the difference between the actually reachable radius.


  // Get an instance of the routing service:
  var router = platform.getRoutingService();


  var routingParams = {
    'mode': 'fastest;car;',
    'start': '52.4571601,13.3806395',
    'range': '10000',
    'rangetype': 'distance'
  };
  
  // Define a callback function to process the isoline response.
  var onResult = function(result) {
    var center = new H.geo.Point(
        result.response.center.latitude,
        result.response.center.longitude),
      isolineCoords = result.response.isoline[0].component[0].shape,
      linestring = new H.geo.LineString(),
      isolinePolygon,
      isolineCenter;
  
    // Add the returned isoline coordinates to a linestring:
    isolineCoords.forEach(function(coords) {
    linestring.pushLatLngAlt.apply(linestring, coords.split(','));
    });
  
    // Create a polygon and a marker representing the isoline:
    isolinePolygon = new H.map.Polygon(linestring);
    isolineCenter = new H.map.Marker(center);
  
    // Add the polygon and marker to the map:
    map.addObjects([isolineCenter, isolinePolygon]);
  
    // Center and zoom the map so that the whole isoline polygon is
    // in the viewport:
    map.getViewModel().setLookAtData({bounds: isolinePolygon.getBoundingBox()});
  };
  
  
  // Call the Routing API to calculate an isoline:
  router.calculateIsoline(
    routingParams,
    onResult,
    function(error) {
    alert(error.message);
    }
  );

Isoline vs Circle

Day 63/100

Where's the park?
A mere 15 minutes drive from here. 😅
In many parts of the world, it is common to tell distances in time. Sometimes for our applications, we may have a time constraint to where we walk or drive to. Some restaurants offer delivery within a certain time. For such use cases, you want to know the places you can walk or drive to within a certain time. The Calculate Isoline endpoint has the ability to do this when you set the rangeType to time and specify the time in seconds.


// Get an instance of the routing service version 7:
var router = platform.getRoutingService();

var routingParams = {
  'mode': 'fastest;car;',
  'start': '52.4571601,13.3806395',
  'range': '900',// 15 x 60 sec
  'rangetype': 'time'
};

Day 64/100

When you're making a group plan to go out, you need to select a place that is convenient to all your friends. This involves finding out the route to your favourite brewery from everyone's houses. And then someone suggests another place and you calculate all the routes all over again. What if you could do this all at once? The Calculate Matrix end point of the Routing API lets you do exactly this. You can calculate the route summaries from multiple starting points to multiple destinations.


function getMatrixRoute(){
  let url = `https://matrix.route.ls.hereapi.com/routing/7.2/calculatematrix.json?`+
            `apikey=${window.hereCreds.JS_KEY}`+
            `&mode=fastest;car`+
            `&start0=52.4571601,13.3806395`+
            `&start1=52.530858,13.384744`+
            `&start2=52.50665,13.39162`+
            `&destination0=52.48505,13.47921`+
            `&destination1=52.54345,13.35946`+
            `&matrixAttributes=indices`

  fetch(url)
    .then(response => response.json())
    .then(response => {
      console.log(response);
    }, error =>{
      console.error(error);
    });
}

getMatrixRoute();

Day 65/100

Along with route indices, the calculate matrix endpoint also returns different properties within route summary. One of them is a route ID. Every route after calculation gets assigned a unique route ID. You can access this route later using the route ID. With day 65, we are going to use the route ID of the routes calculated by Calculate Matrix and render them using Get Route. While calculating the route summaries with Matrix Routing, include the summaryattributes=routeId. Use this route ID with the Get Route end point to get the route shape and render it on the map.


  
function getMatrixRoute(){
  let url = `https://matrix.route.ls.hereapi.com/routing/7.2/calculatematrix.json?`+
            `apikey=${window.hereCreds.JS_KEY}`+
            `&mode=fastest;car`+
            `&start0=52.4571601,13.3806395`+
            `&start1=52.530858,13.384744`+
            `&start2=52.50665,13.39162`+
            `&destination0=52.48505,13.47921`+
            `&destination1=52.54345,13.35946`+
            `&matrixAttributes=indices,summary`+
            `&summaryattributes=routeId`

  fetch(url)
    .then(response => response.json())
    .then(response => {
      console.log(response.response.matrixEntry);
      response.response.matrixEntry.forEach(entry=>{
        // let routeId = entry.summary.routeId; 
        // console.log(entry.summary.routeId,entry.startIndex);
        drawRoute(entry.summary.routeId,entry.startIndex);
      });
    }, error =>{
      console.error(error);
    });
}


function drawRoute(routeID, routeIndex){
  let url = `https://route.ls.hereapi.com/routing/7.2/getroute.json?`+
            `apikey=${window.hereCreds.JS_KEY}`+
            `&routeId=${routeID}`+
            `&representation=display`

  fetch(url)
  .then(response => response.json())
  .then(response => {
    drawPolyline(response,routeIndex);
    // console.log(response);
  }, error =>{
    console.error(error);
  });

}


function drawPolyline(response,routeIndex){

  let route = response.response.route
        var lineString = new H.geo.LineString(),
        routeShape = route.shape,
        polyline,
        startMarker,
        endMarker,
        colors = ["#38d9a9","#cc5de8","#ffa94d"];
      
      // Retrieve the mapped positions of the requested waypoints:
      startPoint = route.waypoint[0].mappedPosition;
      endPoint = route.waypoint[1].mappedPosition;

      routeShape.forEach(function(point) {
        var parts = point.split(',');
        lineString.pushLatLngAlt(parts[0], parts[1]);
      });


      polyline = new H.map.Polyline(lineString, {
        style: {
          lineWidth: 4,
          strokeColor: colors[routeIndex]
        }
      });

      startMarker = new H.map.Marker({
        lat:route.waypoint[0].mappedPosition.latitude,
        lng:route.waypoint[0].mappedPosition.longitude 
      },{icon:new H.map.Icon('img/start.png')});

      endMarker = new H.map.Marker({
        lat:route.waypoint[1].mappedPosition.latitude,
        lng:route.waypoint[1].mappedPosition.longitude 
      },{icon:new H.map.Icon('img/end.png')});

      // Add the polyline to the map
      map.addObjects([polyline,startMarker,endMarker]);
      // And zoom to its bounding rectangle

      map.getViewPort().setPadding(100, 0, 0, 0);
      map.getViewModel().setLookAtData({
        bounds: polyline.getBoundingBox()
      });
      map.getViewPort().setPadding(0, 0, 0, 0);

}

getMatrixRoute();

Matrix routing

That was week 13 of #100DaysOfCode With HERE. Keep following us on Twitter for more tasks and complete all 100 days. If you want to watch the video version of these solutions, take a look at our playlist for #100DaysOfCode on YouTube. If you want the code snippets of the APIs covered with #100DaysOfCode, head over to the 100daysofcode GitHub repository.
While you're at it, why don't you take a look at the tutorial - Add a HERE Web Map into your React application.
Happy coding!