Geokodowanie – procedura przyporządkowania punktom lub obszarom na kuli ziemskiej kodów, umożliwiających jednoznaczną identyfikację każdego miejsca. (wikipedia)
W przypadku, jaki tu opisuję kodem będzie np. "Gdańsk, Grunwaldzka 123". Mimo, że Google Map API wspiera tylko Java Script (jeśli jest inaczej, to proszę o informację w komentarzu), to można wykorzystać pewne funkcjonalności w dowolnym języku potrafiącym parsować JSON/XML. W tym artykule pokażę jak uzyskać współrzędne geograficzne wskazanego miejsca.
Zasada działania
Zwyczajnie wywiołamy stronę www, przekazując przez URL odpowiednie parametry. W wyniku otrzymamy kod JSON, który po przeparsowaniu pozwoli nam odczytać wszystkie potrzebne dane.
Adres:
http://maps.google.com/maps/api/geocode/json?address=tu-miejsce-ktorego-wspolrzednych-szukamy&sensor=false
Prosty interfejs:
W pierwsze pole wpisywać będziemy adres miejsca, np. "Gdynia" (można podać też ulicę i numer domu). Drugie pole będzie nam pokazywać wynik (współrzędne podanego punktu), trzecie pole pokaże nam adres URL, z którego pobrano dane.
Kod
Przypiszmy do przycisku rekację na zdarzenie onclick (u mnie przycisk ma nazwę `geocodeActivator'):
private void geocodeActivator_Click(object sender, EventArgs e)
{
string url = string.Format(
"http://maps.google.com/maps/api/geocode/json?address={0}&sensor=false",
urlEncode(address.Text)
);
googleUrl.Text = url;
var request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(GeoResponse));
GeoResponse res = (GeoResponse)serializer.ReadObject(request.GetResponse().GetResponseStream());
if ("OK" == res.Status)
{
lngLat.Text = "Lng: " + res.Results[0].Geometry.Location.Lng + "\tLat: " + res.Results[0].Geometry.Location.Lat;
}
else
{
lngLat.Text = "Błąd";
}
}
W kodzie jest wywołana metoda `urlEncode', oto jej ciało:
private static object urlEncode(string url)
{
string stFormD = url.Normalize(NormalizationForm.FormD);
StringBuilder sb = new StringBuilder();
for (int ich = 0; ich < stFormD.Length; ich++)
{
UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]);
if (uc != UnicodeCategory.NonSpacingMark)
{
if (stFormD[ich] == 'ł')
{
sb.Append('l');
}
else
{
sb.Append(stFormD[ich]);
}
}
}
return (sb.ToString().Normalize(NormalizationForm.FormC));
}
}
Spyta ktoś, dlaczego sprawdzam osobno literkę "ł". Otóż, nie jest ona wychwytywana w normalnych warunkach, a o dziwo "Łomża" powoduje błąd, podczas gdy "Lomza" działa poprawnie.
Jeszcze tylko dodatkowa klasa `GeoResponse':
[DataContract]
class GeoResponse
{
[DataMember(Name = "status")]
public string Status { get; set; }
[DataMember(Name = "results")]
public CResult[] Results { get; set; }
[DataContract]
public class CResult
{
[DataMember(Name = "geometry")]
public CGeometry Geometry { get; set; }
[DataContract]
public class CGeometry
{
[DataMember(Name = "location")]
public CLocation Location { get; set; }
[DataContract]
public class CLocation
{
[DataMember(Name = "lat")]
public double Lat { get; set; }
[DataMember(Name = "lng")]
public double Lng { get; set; }
}
}
}
}
A także niezbęne usingi (to na górze pliku):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Globalization;
using System.Runtime.Serialization.Json;
using System.Runtime.Serialization;
Przynajmniej u mnie trzeba było dodać referencję do `System.Runtime.Serialization'.
Wynik
Jeśli już wszystko jest na swoim miejscu starczy tylko sprawdzić, czy całość działa poprawnie. Po uruchomieniu program powinien działać mniej - więcej tak:
|