Python: Code Snippets - Geocode

Sunday 23rd July 2017 3:25am

UPDATE:- Google are no longer offering API keys without billing information

Geocoding is the process of converting locations (a street address, postcode etc.) into coordinates; latitude and longitude.

The first script takes these coordinates and returns an image of the location.

To run this script copy the code below and save to a file called geocode_image.py

geocode_image.py:

#!/usr/bin/env python

# Geocode map image
# Return an image for a given location
# (latitude and longitude)

# Date: 07 March 2016
# Written By: Phantom Raspberry Blower

import Image
import urllib
import StringIO
import os
from math import log, exp, tan, atan, pi, ceil

# Define constants
EARTH_RADIUS = 6378137  # in metres
EQUATOR_CIRCUMFERENCE = 2 * pi * EARTH_RADIUS
INITIAL_RESOLUTION = EQUATOR_CIRCUMFERENCE / 256.0
ORIGIN_SHIFT = EQUATOR_CIRCUMFERENCE / 2.0


class GeocodeImage():

    # Initialize
    def __init__(self):
        pass  # Do nothing

    def latlontopixels(self, lat, lon, zoom):
        mx = (lon * ORIGIN_SHIFT) / 180.0
        my = log(tan((90 + lat) * pi / 360.0))/(pi / 180.0)
        my = (my * ORIGIN_SHIFT) / 180.0
        res = INITIAL_RESOLUTION / (2 ** zoom)
        px = (mx + ORIGIN_SHIFT) / res
        py = (my + ORIGIN_SHIFT) / res
        return px, py

    def pixelstolatlon(self, px, py, zoom):
        res = INITIAL_RESOLUTION / (2**zoom)
        mx = px * res - ORIGIN_SHIFT
        my = py * res - ORIGIN_SHIFT
        lat = (my / ORIGIN_SHIFT) * 180.0
        lat = 180 / pi * (2*atan(exp(lat*pi/180.0)) - pi/2.0)
        lon = (mx / ORIGIN_SHIFT) * 180.0
        return lat, lon

    def geocode_image(self, lat, lon, file_path):
        plat, plon = self.latlontopixels(lat, lon, 17)
        nlat, nlon = self.pixelstolatlon(plat-320, plon+180, 17)
        upperleft = '%f,%f' % (nlat, nlon)
        plat, plon = self.latlontopixels(nlat, nlon, 17)
        nlat, nlon = self.pixelstolatlon(plat+640, plon-360, 17)
        lowerright = '%f,%f' % (nlat, nlon)
        zoom = 18 # be careful not to get too many images!
        map_type = 'hybrid'
        ullat, ullon = map(float, upperleft.split(','))
        lrlat, lrlon = map(float, lowerright.split(','))
        # Set some important parameters
        scale = 1
        maxsize = 640
        # convert all these coordinates to pixels
        ulx, uly = self.latlontopixels(ullat, ullon, zoom)
        lrx, lry = self.latlontopixels(lrlat, lrlon, zoom)
        # calculate total pixel dimensions of final image
        dx, dy = abs(lrx - ulx), abs(uly - lry)
        # calculate rows and columns
        cols, rows = int(ceil(dx/maxsize)), int(ceil(dy/maxsize))
        # calculate pixel dimensions of each small image
        bottom = 120
        length = int(ceil(dx/cols))
        height = int(ceil(dy/rows))
        heightplus = height + bottom
        final = Image.new("RGB", (int(dx), int(dy)))
        for x in range(cols):
            for y in range(rows):
                dxn = length * (0.5 + x)
                dyn = height * (0.5 + y)
                latn, lonn = self.pixelstolatlon(ulx + dxn,
                                                 uly - dyn - bottom/2,
                                                 zoom)
                position = ','.join((str(latn), str(lonn)))
                print x, y, position
                urlparams = urllib.urlencode({'center': position,
                                              'zoom': str(zoom),
                                              'size': '%dx%d' % (length,
                                                                 heightplus),
                                              'maptype': map_type,
                                              'sensor': 'false',
                                              'scale': scale})
                url = 'http://maps.google.com/maps/api/staticmap?' + urlparams
                f = urllib.urlopen(url)
                im = Image.open(StringIO.StringIO(f.read()))
                final.paste(im, (int(x*length), int(y*height)))
                final.save(file_path)
        final.show()
        return final

# Check if running stand-alone or imported
if __name__ == '__main__':
    import os
    # Request both latitude and longitude
    latitude = input('Enter Latitude: ')
    longitude = input('Enter Longitude: ')
    gi = GeocodeImage()
    print "Fetching image ..."
    gi.geocode_image(latitude,
    longitude,
    os.getcwd() + '/geocode_image.jpg')
    print "Image saved!"

The next script accepts an address, location or postcode and returns the latitude and longitude.

Copy the code below and save to a file called geocode.py

geocode.py:

#!/usr/bin/env python

# Geocode
# Return the address and location for a given postcode

# Date: 07 March 2016
# Written By: Phantom Raspberry Blower

import requests # Used to request web pages
import Image
import urllib
import StringIO
from geocode_image import GeocodeImage


class Geocode():

    # Initialize
    def __init__(self):
        self.addr = ''

    def geocode_postcode(self, postcode):
        self.geocode(postcode)

    def _clear(self):
        self.post_code = ''
        self.addr = ''
        self.addr_label = ''
        self.formatted_addr = ''
        self.lat = 0.0
        self.lon = 0.0

    def geocode(self, postcode):
        self._clear()
        self.post_code = postcode.upper()
        url = 'https://maps.googleapis.com/maps/api/geocode/json'
        params = {'sensor': 'false', 'address': postcode}
        r = requests.get(url, params=params)
        results = r.json()['results']
        location = results[0]['geometry']['location']
        self.lat = location['lat']
        self.lon = location['lng']
        address_components = results[0]['address_components']
        for item in range(1, len(address_components)):
            if item > 1:
                self.addr = "%s\n" % self.addr
            self.addr = "%s%s" % (self.addr, address_components[item]['long_name'])
        self.formatted_addr = results[0]['formatted_address']

    def image(self): 
        gi = GeocodeImage()
        gi.geocode_image(self.lat, self.lon, os.getcwd() + '/geocode_image.jpg')
        return "Image Saved"

    def postcode(self):
        return self.post_code

    def location(self):
        return [self.latitude(), self.longitude()]

    def latitude(self):
        return self.lat

    def longitude(self):
        return self.lon

    def address(self):
        return self.addr

    def address_label(self):
        return str(self.formatted_address()).replace(", ", ",\n")

    def formatted_address(self):
        return str(self.formatted_addr)

# Check if running stand-alone or imported 
if __name__ == '__main__':
    postcode = raw_input('Enter Address, Location or Postcode: ').upper()
    gc = Geocode()
    gc.geocode_postcode(postcode)
    print "\nAddress:"
    print "         ", gc.address_label().replace("\n", "\n          ")
    print "\nLocation:"
    print "          Latitude: ", gc.latitude()
    print "          Longitude: ", gc.longitude()
    print "\nSingle-line Address:"
    print "         ", gc.formatted_address(), "\n"
    gc.image()

Ouput:

python geocode.py
Enter Address, Location or Postcode: SW1A 1AA

Address:
          London SW1A 1AA,
          UK

Location:
          latitude:   51.501009
          longitude:  -0.1415876

Single-line Address:
          London SW1A 1AA, UK

0 0 51.5014095689,-0.143875696751
0 1 51.5002073959,-0.143875696751
1 0 51.5014095689,-0.141585090252
1 1 51.5002073959,-0.141585090252
2 0 51.5014095689,-0.139294483753
2 1 51.5002073959,-0.139294483753

Image:

Geocode Image

Geocode Image

FB Like & Share