Considerando que já temos uma coleção de endereços capturados e geocodificados, o natural é mostrá-los:
Parte III – Exibindo Mapas
Assim como existem vários serviços gratuitos de geocoding, outros tantos permitem exibir pontos arbitrários, embutindo o mapa no seu site e deixando o usuário navegar livremente dentro dele. Novamente temos que obter uma chave e usar uma API especializada – e continua valendo a sugestão de usar uma biblioteca que abstraia as diferentes APIs.
A que eu mais gostei foi o Mapstraction – que não é exclusivo de Ruby, podendo ser usada em qualquer plataforma (a “mágica” acontece no front-end, via Javascript). O site tem exemplos com vários provedores, e compensa dar uma olhada.
O caminho adotado no Bitchmaps foi outro: ao invés de embutir o mapa, o site exporta os endereços como KML, um formato de dados que permite representar localizações geográficas e seus metadados (descrições, telefones, endereços físicos, URLs, etc.). Vários softwares e sites são capazes de ler KML e exibir seus pontos num mapa (incluindo aí iPhone, que foi o principal atrativo).
O KML nada mais é que um XML com tags específicas. Veja um exemplo (extraído da Wikipedia):
<?xml version="1.0" encoding="UTF-8"?> <kml xmlns="http://earth.google.com/kml/2.0"> <Placemark> <description>New York City</description> <name>New York City</name> <Point> <coordinates>-74.006393,40.714172,0</coordinates> </Point> </Placemark> </kml>
No Rails você pode gerar esse tipo de XML usando um template .rxml (ou, de forma mais contemporânea, um template .builder):
xml.instruct! :xml, :version=>"1.0" xml.kml(:xmlns=>"http://earth.google.com/kml/2.1"){ xml.Document { xml.name(@name) for place in @places xml.Placemark { xml.name(place.description) xml.description(place.url) xml.Point { xml.coordinates(place.lng.to_s+','+place.lat.to_s) } for phone in place.phones xml.phoneNumber(phone.phone) end } end } }
Agora é só chamar este template colocando em @name o título do documento e em @places os locais capturados no banco. Neste exemplo, eles devem possuir as propriedades description, lat, lng e uma coleção phones contendo a propriedade phone (os nomes estão em inglês por mera conveniência de usar o ActiveRecord out-of-the-box sem mapear tabelas ou lançar mão de magia negra).
No caso do BitchMaps, eu chamo o arquivo acima de layer.rxml, e uso um código bem trivial no controller:
def layer filtro = "" case params[:id] when "sp" filtro = "Sao Paulo - SP" when "camp" filtro = "Campinas - SP" .. end @name = "BitchMaps" if filtro!="" @name = @name + " - " + filtro end @places = Place.find(:all, :conditions => ["city_state = ? and full_address is not null", filtro]) #render :xml => @places.to_xml respond_to { |format| format.kml {} } end
Com isso, ao chamar, por exemplo, http://localhost:3000/bm/layer?id=sp (bm é o ID do controller), eu obtenho o KML de São Paulo – SP.
Faltam apenas dois detalhes: o meu provedor é pobrinho e não suporta Ruby/Rails, e eu queria usar KMZ (a versão “zipada” do KML). Resolvo os dois problemas de uma só vez com um shell script que salva em arquivo e comprime cada uma das cidades:
#/bin/bash # Salva os XMLs de cada cidade em arquivos kml lista="sp camp cur lon poa rj bh" rm published/kmz/* for cidade in $lista; do wget http://localhost:3000/bm/layer/$cidade.kml -O published/kmz/$cidade.kml; done # Transforma os kml em kmz cd published/kmz for cidade in $lista; do zip -m $cidade.kmz $cidade.kml; done
Daí é só copiar os arquivos .kmz para o servidor, no qual um arquivo .htaccess customizado ajuda o Apache a servir os arquivos com o tipo correto (para orientar o browser) e a redirecionar os nomes no formato bitchmaps.com/XX para bitchmaps.com/kmz/XX.kmz:
AddType application/vnd.google-earth.kml+xml .kml AddType application/vnd.google-earth.kmz .kmz RewriteEngine on RewriteRule (sp|camp|cur|lon|poa|rj|bh)\/?$ http://bitchmaps.com/kmz/$1.kmz [R]
Enfim, é isso. Espero que esta série tenha matado a curiosidade de quem viu o BitchMaps e também que ajude a colocar mais informação geográfica na web. Até a próxima!




pq na proxima versão se possivel não coloca uma opção de cartas médias, pois meu cel é um 2630 (128X160) se eu setar as cartas grandes nao vejo as cartas do meu parceiro e se deixa pequenas mal enxergo…de resto o jogo eh perfeito…alias o unico q eu jogo em todos os lugares….
[Responder]