Thursday, October 31

Batch Geocoding with Google Geocode API and C#

Introduction: Geocoding is the process of converting addresses into geographic coordinates (like latitude and longitude), which can be used to place on the map. The Google Geocoding API provides a direct way to access a these services via an HTTP request. Please see the full documentation at https://developers.google.com/maps/documentation/geocoding/.

Geocoding API Request :
http://maps.googleapis.com/maps/api/geocode/output?parameters.
Some of the parameters are required and some are optional. The parameters are separated by ampersand (&) character.

Required Parameters:
Address – The address that needs to be geocoded.
Latlng – The latitude/longitude value for which the closest address can be obtained.
Components – Component filter for which geocode needs to be obtained.
Sensor: Whether a geocoding request comes from a device with location sensor.

Geocoding Response:
Geocoding response is returned in the format indicated by the output flag. It is either JSON or XML.

JSON output Formats: API requests a JSON output for Address 600 W. Chicago,IL 70345

http://maps.googleapis.com/maps/api/geocode/json?address=600+w.+Chicago,+IL+70345 &sensor=true_or_false

XML output Format: API requests a JSON output for Address 600 W. Chicago,IL 70345

http://maps.googleapis.com/maps/api/geocode/XML?address=600+w.+Chicago,+IL+70345 &sensor=true_or_false

Both output returns Status and Result elements.

Status Element: returns the status of the request.

Result Element:  it consists of the following:

Types[] Array : types of returned result.
Formatted_address: Address of the location.
Address_component []- contains separated address_components.
Geometry – contains:
(1)    Location: geocoded latitude and Logitude
(2)    Location_type: location Types- the following values are supported:
(A)Rooftop: indicates that the returned result is a precise geocode for which we have location information accurate down to street address precision.
(B)Range_interpolated : indicates that the returned result reflects an approximation (usually on a road) interpolated between two precise points (such as intersections).
©Geometric Center- indicates that the returned result is the geometric center of a result such as a polyline (for example, a street) or polygon (region).
(D)Approximate- indicates that the returned result is approximate
Partial Match- indicates that the geocoder did not return an exact match for the original request, though it was able to match part of the requested address.
Here I’ll provide C# code that calls Google Geocode API. It geocodes addresses in a batch. It takes addresses from a .csv file and returns a .csv file with geocodes (Latitude/Longitude) for each address if it finds a geo location. Also, it returns a status code and location type.
Open a Windows Form Application from Visual studio. Drag a button and call it ‘Geocode’ and paste the following code under private void Geocode_Click(object sender, EventArgs e) events. Prepare a file with Addresses (street address, City, State, and zip) and save it as .csv file. In my code I placed it under c: drive and name it as ‘Address.txt’. Change your file name and path location. Run this program and click the ‘Geocode’ button. It’ll create a ‘AddressWithGeocode.csv’ file under c: drive. You can change the file path and file name.

 Code

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.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Diagnostics;
using System.Net;


namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        HttpWebRequest request;
        Stream responseReader;
        Uri address;
        public string lng = "";
        string lat = "";
        String location_type = "";
        String partial_match = "";
        String callingServer;
        XmlDocument xmlDoc;


        System.Xml.XmlDocument rootNode = new System.Xml.XmlDocument();
        System.Xml.XmlDocument rootNodeGeo = new System.Xml.XmlDocument();
        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void Geocode_Click(object sender, EventArgs e)
        {
             StreamReader sr = new StreamReader("C:\\address.txt"); //reading from Address file
            String strline = "";
            String[] _values = null;
            //int x = 0;


            StreamWriter wr = new StreamWriter(@"C:\AddressWithGeoCode.csv"); //writting to AddressWithGeoCode file
           
            wr.WriteLine("Address" + ","+ "City" +","+ "State"+","+"Zip"+ "," + "latitude" + "," + "Longitude" + "," + "Partial Match" + "," + "Location type");
                     
            while (!sr.EndOfStream)
            {
               
                strline = sr.ReadLine();
               
               
                _values = strline.Split(',');
                String Street = _values[0];
                String City = _values[1];
                String State = _values[2];
                String Zip = _values[3];


            

                callingServer = "http://maps.googleapis.com/maps/api/geocode/xml?address=" +
                     Street+City+State+Zip +"&sensor=false";

                address = new Uri(callingServer);
                try
                {
                    //request
                    request = (HttpWebRequest)WebRequest.Create(callingServer);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
                request.ContentType = "application/xml; charset=utf-8";
             
                // Get response 
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

               // Get the response stream into a reader 
                responseReader = response.GetResponseStream();


                XmlTextWriter outXML;
                outXML = new XmlTextWriter("response.xml", null);
                xmlDoc = new XmlDocument();
                xmlDoc.Load(responseReader);
                xmlDoc.Save(outXML);
                outXML.Close();
                responseReader.Close();

                //PopulateNodes(rootNode);
               
                rootNode.Load(@"response.xml");
                XmlNodeList itemList = rootNode.GetElementsByTagName("location");
                XmlNodeList itemList1 = rootNode.GetElementsByTagName("partial_match");
                XmlNodeList itemList2 = rootNode.GetElementsByTagName("location_type");
        
                foreach (XmlNode currNode in itemList)
                {                 
                       lat = currNode.ChildNodes[0].ChildNodes[0].Value.ToString();
                       lng = currNode.ChildNodes[1].ChildNodes[0].Value.ToString();
                       break;
                     
                }       
                foreach (XmlNode currNode in itemList1)
                {           
                     partial_match = currNode.ChildNodes[0].Value.ToString();
                     break;
                }
                foreach (XmlNode currNode in itemList2)
                {
                     location_type = currNode.ChildNodes[0].Value.ToString();
                     break;
                }
             
              
                wr.WriteLine(Street+","+City+","+State+","+Zip + "," + lat + "," + lng + "," + partial_match + "," + location_type);
               }
            MessageBox.Show("Geocoding is done. Pl. check your file");
            wr.Close();
            wr.Close();
          
        }     
    }
}




 output:

Address,City,State,Zip,latitude,Longitude,Partial Match,Location type
1007 Mandalay ct,Naperviile,IL,60563,41.7866794,-88.2149432,,RANGE_INTERPOLATED
5566 West Chester Road,West Chester,OH,45069,39.3302867,-84.439955,,RANGE_INTERPOLATED
3075 Highland Parkway,Downers Grove,IL,60515,41.832551,-88.005306,,ROOFTOP
1275 First Street,West Lafayette,IN,47906,40.4253133,-86.9249989,,ROOFTOP
6 Mortomar Dr,Andover,MA,1810,40.4253133,-86.9249989,,ROOFTOP
601 Old Court Circle,Mekinney,TX,75070,40.4253133,-86.9249989,,ROOFTOP
131 Quill Ridge Dr,Westmont,IL,60559,41.8236432,-87.9571126,,RANGE_INTERPOLATED