Continuando a partir do artigo anterior “Mapas do Google no seu aplicativo Delphi”, vamos agora avançar um pouco mais, traçar rotas entre dois pontos, e mostrar isto ao usuário.
Esta é uma funcionalidade interessante para aplicativos como CRM ou de logística. Você pode obter informações completas sobre como utilizar as APIs do Google Maps em www.google.com/apis/maps, a maioria dos exemplos contempla Java, Javascript, PHP ou Python, porém não é dificil adaptá-los à linguagem que você utiliza, como estamos fazendo com o Delphi.
Para usar as APIs do Google, você precisa obter uma chave única e exclusiva sua, é de graça, e lhe dá acesso à todas as funcionalidades do Google Maps. Neste exemplo não vamos utilizar esta chave, é apenas um exemplo, muito embora você possa utilizar sem ter uma chave, como você pode constatar pelo código neste artigo, é aconselhável que você obtenha esta chave, por uma questão de copyright.
Bueno, vamos botar a mão na massa.
Primeiro de tudo você irá precisar, para mostrar o mapa, das coordenadas do ponto a ser mostrado na tela, normalmente você mostrará na tela o ponto inicial da rota, permitindo ao usuário que acompanhe a rota a partir do ponto de origem, porém você pode mostrar o ponto final da rota, a seu critério. Por este motivo criamos uma função para retornar as coordenadas.
As coordenadas (e mais uma série de informações sobre o endereço) são retornadas em um arquivo xml, você também pode solicitar que seja retornado em formato csv (separado por vírgulas). No caso de um arquivo xml a API do Google Maps retorna informações bem completas, incluindo até mesmo o CEP, no caso de arquivo CSV serão retornadas apenas as coordenadas.
Neste artigo iremos trabalhar com o arquivo XML, pois se você desejar obter mais informações sobre o endereço basta incrementar o código.
Como este artigo é direcionado para todos os desenvolvedores DELPHI, incluindo os iniciantes, vou tentar manter o código o mais simples possível, mesmo que em algumas partes pareça que há redundância ou que o código poderia ser reduzido, creio que desta forma fica fácil para todos acompanharem a metodologia, sinta-se a vontade para refatorar o código.
Para este código você deverá declarar a unit XMLDOC na parte de interface da sua unit.
Vamos também declarar um objeto do tipo XMLDocument para trabalhar com as informações retornadas pelo Google.
vXMLDoc : TXMLDocument;
Na inicialização da Unit, ou no evento onCreate do Form, você deverá criar o XMLDocument:
vXMLDoc := TXMLDocument.Create(Self);
Vamos criar a função que irá preencher as coordenadas, apenas para fins informativos mantivemos o array com 3 dimensões, na primeira iremos manter as coordenadas como recuperadas do arquivo xml, isto é apenas para fins informativos, você poderá consultar esta ocorrência do array para verificar como as coordenadas foram lidas. No seu aplicativo final de produção você pode eliminar esta ocorrência.
function getCoordenadas(Logradouro, Numero, Cidade, UF, Pais: String): String;
var
//Vamos declarar um array para trabalhar com as coordenadas:
strCoordenadas: array[0..2] of String;
strURL: String;
idx, inicio, tamanho : integer; // para manipular as strings de retorno
begin
Try
Result := ‘’;
strURL := ‘http://maps.google.com/maps/geo?q=’ +
Logradouro + ‘, ‘ + Numero + ‘ – ‘ + Cidade +
‘ – ‘ + UF + ‘, ‘ + Pais + ‘&output=xml’;
// O parâmetro final da string output determina o tipo de
// informação retornada (csv ou xml).
// Agora fazemos o xmldocument ler o retorno da URL
vXMLDoc.FileName := strURL;
vXMLDoc.Active := True;
// Se você quiser aprender mais sobre o retorno do Google.
// coloque um TMemo no formulário e passe o texto retornado
// para este TMemo, para ver o que é retornado, como abaixo:
Memo1.Lines.Clear;
Memo1.Lines.Add(vXMLDoc.XML.Text);
if not vXMLDoc.Active Then
exit;
For idx := 0 to vXMLDoc.XML.Count -1 do
begin
If Pos('<coordinates>', vXMLDoc.XML[idx]) > 0 Then
begin
inicio := Pos('<coordinates>', vXMLDoc.XML[idx]) + 13;
tamanho := (Length(vXMLDoc.XML[idx]) - inicio) - (Length(vXMLDoc.XML[idx]) - (Pos('</coordinates>', vXMLDoc.XML[idx])));
strCoordenadas[0] := Copy((vXMLDoc.XML[idx]), inicio, tamanho);
end;
end;
If length(strCoordenadas[0]) > 0 Then
begin
strCoordenadas[1] := Copy(strCoordenadas[0], 1, Pos(',', strCoordenadas[0]) -1);
strCoordenadas[2] := Copy(strCoordenadas[0], Pos(',', strCoordenadas[0])+ 1, Length(StrCoordenadas[0]));
if Pos(',', strCoordenadas[2]) > 0 Then
StrCoordenadas[2] := Copy(strCoordenadas[2], 1, Pos(',', strCoordenadas[2]) - 1);
end;
// Se você colocou um Memo para verificar o que é retornado,
// pode adicionar as coordenadas para verificar se está tudo OK.
// Lembre-se de retirar isto no software de produção.
Memo1.Lines.Add(strCoordenadas[0]);
Memo1.Lines.Add(strCoordenadas[1]);
Memo1.Lines.Add(strCoordenadas[2]);
Result := strCoordenadas[2] + ‘,’ + strCoordenadas[1];
Finally
End;
end;
Agora vamos declarar uma função para receber os endereços, as coordenadas e retornar a URL para traçar a rota. As URLs para buscar as coordenadas e para traçar as rotas, ficam mais fácil de gerenciar se você declarar na parte de interface da unit. Aqui declaramos as URLs no corpo das procedures e functions para facilitar o seu entendimento, apenas para fins didáticos.
Function Rotear( De_onde, Para_onde, coordenadas: String): String;
var
strURL : String;
begin
Try
Result := ‘’;
// URL para traçar a rota no google
// O parâmetro z (o último da URL) é o fator de zoom
// a ser aplicado ao mapa, experimente com outros
// valores (valores maiores, mais zoom, e vice-versa).
strURL := ‘http://maps.google.com/maps?f=d&source=s_d&saddr=’ +
De_onde + ‘&daddr=’ +
Para_onde + ‘&hl=pt-BR&geocode=&mra=pe&mrcr=0&ie=UTF8&ll=’ +
coordenadas + ‘&z=16’;Result := strURL;
Finally
end;
end;
Agora vamos usar a mesma função que usamos no outro artigo sobre mostrar mapas do google no delphi, para mostrar o mapa com a rota traçada:
Temos uma tabela de Clientes, 5 campos desta tabela nos interessam, que contém os dados que usaremos para pesquisar no mapa.
Logradouro = Contém o nome do logradouro do endereço, por exemplo “Rua Jesuíno Arruda”.
Numero = Contém o número do endereço, apenas o número e não o complemento (sala, loja, etc), por exemplo: 769
Cidade = O nome da cidade, por exemplo: São Paulo
UF = A sigla do estado, exemplo SP.
País = O nome do país;
E agora criar uma função que vai fazer o trabalho, é simples, prático e bem rápido.
procedure TForm1.CarregaMapa;
var
strURL, deOnde, paraOnde, coordenadas : String;
begin
// Localizamos o endereço inicial
Clientes.Locate(‘ClienteID’, VarArrayOf([clienteInicial]),[]);
Coordenadas := getCoordenadas(Clientes.FieldByName('Logradouro').AsString, Clientes.FieldByName('Numero').AsString, Clientes.FieldByName('Cidade').AsString, Clientes.FieldByName('UF').AsString, Clientes.FieldByName(‘Pais’).AsString);
deOnde := Clientes.FieldByName('Logradouro').AsString + ', ' +
Clientes.FieldByName('Numero').AsString + ', ' +
Clientes.FieldByName('Cidade').AsString + '-' +
Clientes.FieldByName('UF').AsString + ‘, ‘ +
Clientes.FieldByName(‘Pais’).AsString;
// Vamos localizar o endereço de destino
Clientes.Locate(‘ClienteID’, varArrayOf([clientefinal]), []);
Clientes.FieldByName('Numero').AsString + ', ' +
Clientes.FieldByName('Cidade').AsString + '-' +
Clientes.FieldByName('UF').AsString + ‘, ‘ +
Clientes.FieldByName(‘Pais’).AsString;
strURL := Rotear(deOnde, paraOnde, Coordenadas);
ShellExecute(0, Nil, PChar(strURL), Nil, Nil, 0);
// Fiz a chamada acima para que ficasse mais claro, mas você
// pode otimizar a clareza do código fazendo a chamada :
// ShellExecute(0, Nil, PChar(Rotear(deOnde, paraOnde, Coordenadas)), Nil, Nil, 0);
end;
Bom, com isso você já consegue colocar a funcionalidade de fazer rotas no seu aplicativo, você pode usar um TWebBrowser e embutir isto dentro do seu software. Há vantagens e desvantagens nisto, eu pessoalmente prefiro chamar um browser externo.
Como o TWebBrowser é baseado na engine do Internet Explorer, se o usuário tiver outro browser instalado (Opera, FireFox, Safari, etc), e não tiver o Internet Explorer instalado, seu aplicativo vai apresentar erro, e a bela funcionalidade que você implementou não irá funcionar. Da maneira como fizemos, o browser padrão do usuário é que será chamado, seja ele qual for.
14 comentários:
Como disse lá no News, ganhei o dia (e mais trabalho) mostrando isso pro chefe.
Já implementei na minha aplicação.
Valeu.
Felipe
Parabens pela dedicação em postar este material muito útil!!!
excelente material, parabens mesmo, mas e como que eu faço para enviar as coordenadas e pegar o endereco?
Você fala sobre as coordenadas geográficas? Latitude e Longitude?
voce tem os fontes para download?
O código é esse que está no post mesmo, na verdade foi extraído de um aplicativo de CRM que eu tenho.
thanks for this exacting tips 147896325
Gostaria de sabe se e possivel traçar mais de um destino e como seria isto.
Não entendi, você deseja a partir de um destino traçar mais de uma rota ao mesmo tempo? Ou oferecer ao usuário rotas alternativas?
O destino é um só para cada rota, porém automaticamente o google inclui as rotas alternativas, para isto você não precisa fazer nada, já é apresentado por default.
E se quisermos que a rota seja traçada saindo do Endereço_1 (origem), passando pelo Endereço_2, Endereço_3 e chegando ao destino Endereço_4 (final) ?
Marcelo
jaious@hotmal.com
Olá amigo, muito bom seu artigo mas o que eu preciso mesmo é um recurso de colocar no GMaps uma rota feita por um motorista baseado nas coordenadas obtidas por um GPS a bordo do veículo. Tipo uma rota de coleta de material que foi realizada. Voce teria como me dar alguma dica de como fazer isto?
Desde já, obrigado pela atenção dispensada.
Boa tarde.
Tenho as coordenadas dos fornecedores cadastradas, latitude e longitude, entao quero que o o cliente ache o fornecedor mais perto dele, e me relacione os mais perto até x fornecedores.
Teria como se encaixar no meu caso?
Paulo
comercial@g2soft.com.br
Abraço!
fiz mas da erro no retorno linha 0 no xmldocument
teria como pegar o fonte
bom dia, poderia me passar os fontes para meu email edson172012@gmail.com
Postar um comentário