Geocode z wykorzystaniem GoogleMap API Drukuj
Ocena użytkowników: / 1
SłabyŚwietny 
Wpisany przez Patryk yarpo Jar   
sobota, 23 października 2010 22:54

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:

Interfejs programu

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:

 

Zobacz podobne artykuły