por Cesar Cassiano Schimanco

Traçar rotas com Google Directions API

Use o formulário abaixo para gerar a rota entre dois endereços.

 
 

 


Baseado no artigo Calcular distância entre dois endereços, vou mostrar hoje como utilizar Google Directions API para calcular as direções entre localizações, ou seja, vai calcular a rota.


URL de exemplo:
http://maps.googleapis.com/maps/api/directions/xml?origin=Porto Alegre&destination=Sao Paulo&mode=driving&language=pt-BR&sensor=false

Descrição dos parâmetros:
Tipos de saídas: json e xml
origin: Porto Alegre
destination:São Paulo
mode: driving (driving - walking - bicycling )
language : pt-BR
sensor: (true – false) para aplicações que usam GPS...
units=metric (metric - imperial ) Retorna distância em quilômetros ou milhas.

Resultado:

<?xml version="1.0" encoding="UTF-8"?>
<DirectionsResponse>
 <status>OK</status>
 <route>
  <summary>Av. Osvaldo Aranha</summary>
  <leg>
   <step>
    <travel_mode>DRIVING</travel_mode>
    <start_location>
     <lat>-30.0320800</lat>
     <lng>-51.2209500</lng>
    </start_location>
    <end_location>
     <lat>-30.0323300</lat>
     <lng>-51.2229900</lng>
    </end_location>
    <polyline>
     <points>nshvD|aswHUpBYnCp@jAn@hA</points>
    </polyline>
    <duration>
     <value>31</value>
     <text>1 min</text>
    </duration>
    <html_instructions>Siga na direção &lt;b&gt;oeste&lt;/b&gt; na &lt;b&gt;Av. Osvaldo Aranha&lt;/b&gt; em direção à &lt;b&gt;Av. João Pessoa&lt;/b&gt;&lt;div style=&quot;font-size:0.9em&quot;&gt;O destino estará à direita&lt;/div&gt;</html_instructions>
    <distance>
     <value>217</value>
     <text>0,2 km</text>
    </distance>
   </step>
   <duration>
    <value>31</value>
    <text>1 min</text>
   </duration>
   <distance>
    <value>217</value>
    <text>0,2 km</text>
   </distance>
   <start_location>
    <lat>-30.0320800</lat>
    <lng>-51.2209500</lng>
   </start_location>
   <end_location>
    <lat>-30.0323300</lat>
    <lng>-51.2229900</lng>
   </end_location>
   <start_address>Avenida Osvaldo Aranha, 100 - Centro, Porto Alegre - RS, 90035-190, República Federativa do Brasil</start_address>
   <end_address>Avenida Osvaldo Aranha, 10 - Centro, Porto Alegre - RS, 90035-190, República Federativa do Brasil</end_address>
  </leg>
  <copyrights>Dados cartográficos ©2013 Google, MapLink</copyrights>
  <overview_polyline>
   <points>nshvD|aswHo@`G`BtC</points>
  </overview_polyline>
  <bounds>
   <southwest>
    <lat>-30.0323300</lat>
    <lng>-51.2229900</lng>
   </southwest>
   <northeast>
    <lat>-30.0318400</lat>
    <lng>-51.2209500</lng>
   </northeast>
  </bounds>
 </route>
</DirectionsResponse>


Tipos de Status
OK Retorno válido.
NOT_FOUND Algum local ou ponto informado, não foi localizado.
ZERO_RESULTS Nenhum resultado encontrado.
MAX_WAYPOINTS_EXCEEDED Excesso de waypointss na consulta.
INVALID_REQUEST Requisição inválida.
OVER_QUERY_LIMIT Aplicação excedeu o número máximo de requisições em um determinado período.
REQUEST_DENIED Sua aplicação bloqueou o uso do Distance Matrix.
UNKNOWN_ERROR Erro no servidor. Tente novamente que pode funcionar.

Alguns limites de uso:
- 2,500 requisições diárias
- As URLs de requisição não podem ultrapassar 2048 characteres

Mais sobre a documentação do Google Directions API
https://developers.google.com/maps/documentation/directions


XML - Exemplo de implementação do Google Maps API para gerar rota automaticamente entre endereços com retorno XML
URL de exemplo para retornar XML:
http://maps.googleapis.com/maps/api/directions/xml?origin=Porto%20Alegre,%20Osvaldo%20Aranha,%20100&destination=Porto%20Alegre,%20Osvaldo%20Aranha,%2010&sensor=false

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">

    <div>
        <div>
            <table border="0" cellpadding="0" cellspacing="0">
                <tr>
                    <td>
                        <label for="txtOrigem">Origem</label>
                        <asp:TextBox runat="server" ID="txtOrigem" ClientIDMode="Static" />
                    </td>
                    </tr>
                <tr>
                    <td>
                        <label for="txtDestino">Destino</label>
                        <asp:TextBox runat="server" ID="txtDestino" ClientIDMode="Static" />                    
                    </td>
                </tr>
            </table>
            <asp:Button Text="Calcular" ID="btnCalcular" runat="server" 
                onclick="btnCalcular_Click" />
        </div>
    </div>
        <div style="padding:10px">
            <iframe id="map" runat="server" width="750" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="https://maps.google.com/maps?saddr=porto+alegre&daddr=São paulo&amp;output=embed"></iframe>
        </div>
        <asp:Literal ID="litResultado" runat="server" />
    </form>
</body>
</html>

Defautl.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Net;
using System.Xml.Linq;

public partial class Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        
    }
    protected void btnCalcular_Click(object sender, EventArgs e)
    {
        //URL do distancematrix - adicionando endereço de origem e destino
        string url = string.Format("http://maps.googleapis.com/maps/api/directions/xml?origin={0}&destination={1}&mode=driving&language=pt-BR&sensor=false",
            txtOrigem.Text, txtDestino.Text);

        //Carregar o XML via URL
        XElement xml = XElement.Load(url);

        //Verificar se o status é OK
        if (xml.Element("status").Value == "OK")
        {
            string rota = string.Empty;
            //Pegar os detalhes de cada passo da rota
            foreach (var item in xml.Element("route").Element("leg").Elements("step"))
            {
                //Pegar as instruções da rota em HTML
                rota += item.Element("html_instructions").Value + "<br />";
                //Pegar a distância deste trecho
                rota += item.Element("distance").Element("text").Value + "<br />";
            }

            //Formatar a resposta
            litResultado.Text = string.Format("<strong>Origem</strong>: {0} <br /><strong>Destino:</strong> {1} <br /><strong>Distância</strong>: {2} <br /><strong>Duração</strong>: {3} <br /><strong>Como chegar ao destino</strong>:<br /> {4}",
                //Pegar endereço de origem
                xml.Element("route").Element("leg").Element("start_address").Value,
                //Pegar endereço de destino
                xml.Element("route").Element("leg").Element("end_address").Value,
                //Pegar duração
                xml.Element("route").Element("leg").Element("duration").Element("text").Value,
                //Pegar a distância
                xml.Element("route").Element("leg").Element("distance").Element("text").Value,
                //Adicionar a rota gerada logo acima
                rota
                );
            //Atualizar o mapa
            map.Src = "https://maps.google.com/maps?saddr=" + xml.Element("route").Element("leg").Element("start_address").Value + "&daddr=" + xml.Element("route").Element("leg").Element("end_address").Value + "&output=embed";
        }
        else
        {
            //Se ocorrer algum erro
            litResultado.Text = String.Concat("Ocorreu o seguinte erro: ", xml.Element("status").Value);
        }
    }
}


Retorno do XML:

<?xml version="1.0" encoding="UTF-8"?>
<DirectionsResponse>
 <status>OK</status>
 <route>
  <summary>Av. Osvaldo Aranha</summary>
  <leg>
   <step>
    <travel_mode>DRIVING</travel_mode>
    <start_location>
     <lat>-30.0320800</lat>
     <lng>-51.2209500</lng>
    </start_location>
    <end_location>
     <lat>-30.0323300</lat>
     <lng>-51.2229900</lng>
    </end_location>
    <polyline>
     <points>nshvD|aswHUpBYnCp@jAn@hA</points>
    </polyline>
    <duration>
     <value>31</value>
     <text>1 min</text>
    </duration>
    <html_instructions>Siga na direção &lt;b&gt;oeste&lt;/b&gt; na &lt;b&gt;Av. Osvaldo Aranha&lt;/b&gt; em direção à &lt;b&gt;Av. João Pessoa&lt;/b&gt;&lt;div style=&quot;font-size:0.9em&quot;&gt;O destino estará à direita&lt;/div&gt;</html_instructions>
    <distance>
     <value>217</value>
     <text>0,2 km</text>
    </distance>
   </step>
   <duration>
    <value>31</value>
    <text>1 min</text>
   </duration>
   <distance>
    <value>217</value>
    <text>0,2 km</text>
   </distance>
   <start_location>
    <lat>-30.0320800</lat>
    <lng>-51.2209500</lng>
   </start_location>
   <end_location>
    <lat>-30.0323300</lat>
    <lng>-51.2229900</lng>
   </end_location>
   <start_address>Avenida Osvaldo Aranha, 100 - Centro, Porto Alegre - RS, 90035-190, República Federativa do Brasil</start_address>
   <end_address>Avenida Osvaldo Aranha, 10 - Centro, Porto Alegre - RS, 90035-190, República Federativa do Brasil</end_address>
  </leg>
  <copyrights>Dados cartográficos ©2013 Google, MapLink</copyrights>
  <overview_polyline>
   <points>nshvD|aswHo@`G`BtC</points>
  </overview_polyline>
  <bounds>
   <southwest>
    <lat>-30.0323300</lat>
    <lng>-51.2229900</lng>
   </southwest>
   <northeast>
    <lat>-30.0318400</lat>
    <lng>-51.2209500</lng>
   </northeast>
  </bounds>
 </route>
</DirectionsResponse>

 

Atenção: A versão do Google Maps JavaScript V2 utilizada neste artigo foi descontinuada pelo Google. Então oi necessário fazer uma adaptação para o exemplo (JSON) voltar a funcionar. O artigo já está atualizado e funcionando e no final explico o que mudou.

 

A adaptação tem o objetivo de minimizar o impacto para os que utilizaram este exemplo. A solução mostrada aqui consiste em criada uma interface que vai se comunicar com a API, processar os dados e retornar a versão JSON correspondente. Abaixo está o novo webservice deve receber como parâmetro a URL original do Google Maps.

webservice.ashx:

<%@ WebHandler Language="C#" Class="webservice" %>
using System;
using System.Web;

public class webservice : IHttpHandler {
    
    public void ProcessRequest (HttpContext context) {
        //Pegar a URL enviada como Parâmetro
        string url = context.Request.QueryString["url"];
        //Instanciar o WebClient
        System.Net.WebClient wc = new System.Net.WebClient();
        //Definir a codificação como UTF8
        wc.Encoding = System.Text.Encoding.UTF8;
        //Obter o conteúdo (JSON) da URL
        string json = wc.DownloadString(HttpUtility.UrlDecode(url));
        //Retornar o JSON
        context.Response.Write(json);
        //Definie o ContentType = JSON
        context.Response.ContentType = "application/json";
    }
 
    public bool IsReusable {
        get {
            return false;
        }
    }
}

 

JSON - Exemplo de implementação do Google Maps API para traçar rota entre endereços com retorno JSON.
URL de exemplo para retornar JSON:
http://maps.googleapis.com/maps/api/directions/json?origin=Porto%20Alegre,%20Osvaldo%20Aranha,%20100&destination=Porto%20Alegre,%20Osvaldo%20Aranha,%2010&sensor=false

Default.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
    <script src="http://code.jquery.com/jquery-1.8.1.js" type="text/javascript"></script>
    <script type="text/javascript">
        function CalculaRota() {
            var urlDirections = "http://maps.googleapis.com/maps/api/directions/json?origin={0}&destination={1}&mode=driving&language=pt-BR&sensor=false";
            //Adicionar endereço de origem
            urlDirections = urlDirections.replace("{0}", $("#txtOrigem").val());
            //Adicionar endereço de destino
            urlDirections = urlDirections.replace("{1}", $("#txtDestino").val());

            $('#litResultado').html('Aguarde...');
            $.getJSON("webservice.ashx?url=" + escape(urlDirections ),
              function (data) {
                  //Verificar se o Status está OK
                  if (data.status == "OK") {
                      var rota = "";
                      for (var i = 0; i < data.routes[0].legs[0].steps.length; i++) {
                          //Pegar as instruções da rota em HTML
                          rota += data.routes[0].legs[0].steps[i].html_instructions + "<br />";
                          //Pegar a distância deste trecho
                          rota += data.routes[0].legs[0].steps[i].distance.text + "<br />";
                      }
                      //Retornar o resultado na página
                      $('#litResultado').html(
                          //Pegar endereço de origem
                          "<strong>Origem</strong>: " + data.routes[0].legs[0].start_address +
                          //Pegar endereço de destino
                          "<br /><strong>Destino:</strong> " + data.routes[0].legs[0].end_address +
                          //Pegar a distância
                          "<br /><strong>Distância</strong>: " + data.routes[0].legs[0].distance.text +
                          //Pegar duração
                          " <br /><strong>Duração</strong>: " + data.routes[0].legs[0].duration.text +
                          //Adicionar a rota gerada logo acima
                          " <br /><strong>Como chegar ao destino</strong>:<br /> " + rota
                          );
                      //Atualizar o mapa
                      $("#map").attr("src", "https://maps.google.com/maps?saddr=" + data.routes[0].legs[0].start_address +"&daddr=" + data.routes[0].legs[0].end_address + "&output=embed");
                  }
                //Se o Status não for OK
                  else
                      $('#litResultado').html('Ocorreu um erro');

              }
            ).error(function () { $('#litResultado').html('Ocorreu um erro!'); });
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">

        <div>
            <div>
                <table border="0" cellpadding="0" cellspacing="0">
                    <tr>
                        <td>
                            <label for="txtOrigem">Origem</label>
                            <input type="text" id="txtOrigem" />
                        </td>
                    </tr>
                    <tr>
                        <td>
                            <label for="txtDestino">Destino</label>
                            <input type="text" id="txtDestino" />
                        </td>
                    </tr>
                </table>
                <input type="button" value="Calcular distância" onclick="CalculaRota()" />
            </div>
        </div>
        <div style="padding:10px">
            <iframe id="map" width="750" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="https://maps.google.com/maps?saddr=porto+alegre&daddr=São paulo&amp;output=embed"></iframe>
        </div>
        <span id="litResultado"></span>
    </form>
</body>
</html>


Retorno do JSON:

{
   "routes" : [
      {
         "bounds" : {
            "northeast" : {
               "lat" : -30.031840,
               "lng" : -51.220950
            },
            "southwest" : {
               "lat" : -30.03233000000001,
               "lng" : -51.222990
            }
         },
         "copyrights" : "Dados cartográficos ©2013 Google, MapLink",
         "legs" : [
            {
               "distance" : {
                  "text" : "0,2 km",
                  "value" : 217
               },
               "duration" : {
                  "text" : "1 min",
                  "value" : 31
               },
               "end_address" : "Avenida Osvaldo Aranha, 10 - Centro, Porto Alegre - RS, 90035-190, República Federativa do Brasil",
               "end_location" : {
                  "lat" : -30.03233000000001,
                  "lng" : -51.222990
               },
               "start_address" : "Avenida Osvaldo Aranha, 100 - Centro, Porto Alegre - RS, 90035-190, República Federativa do Brasil",
               "start_location" : {
                  "lat" : -30.032080,
                  "lng" : -51.220950
               },
               "steps" : [
                  {
                     "distance" : {
                        "text" : "0,2 km",
                        "value" : 217
                     },
                     "duration" : {
                        "text" : "1 min",
                        "value" : 31
                     },
                     "end_location" : {
                        "lat" : -30.03233000000001,
                        "lng" : -51.222990
                     },
                     "html_instructions" : "Siga na direção \u003cb\u003eoeste\u003c/b\u003e na \u003cb\u003eAv. Osvaldo Aranha\u003c/b\u003e em direção à \u003cb\u003eAv. João Pessoa\u003c/b\u003e\u003cdiv style=\"font-size:0.9em\"\u003eO destino estará à direita\u003c/div\u003e",
                     "polyline" : {
                        "points" : "nshvD|aswHUpBYnCp@jAn@hA"
                     },
                     "start_location" : {
                        "lat" : -30.032080,
                        "lng" : -51.220950
                     },
                     "travel_mode" : "DRIVING"
                  }
               ],
               "via_waypoint" : []
            }
         ],
         "overview_polyline" : {
            "points" : "nshvD|aswHo@`G`BtC"
         },
         "summary" : "Av. Osvaldo Aranha",
         "warnings" : [],
         "waypoint_order" : []
      }
   ],
   "status" : "OK"
}


 O que mudou?

Antes:

$('#litResultado').html('Aguarde...');
$.getJSON(urlDirections,
  function (data) {

 Depois:

$('#litResultado').html('Aguarde...');
$.getJSON("webservice.ashx?url=" + escape(urlDistance),
  function (data) {

Também foi adicionada uma nova página webservice.ashx

 

Comentários

Carregando comentários

Postar um novo comentário



Processando...