Manipulating Geo Coordinates in Python and Foursquare Cheating

Sunday, February 21, 2010 11:21 PM

I've been tinkering with the Foursquare API. It's a lot of fun to play with and is as clean as the Twitter API. Anyway, the reason for all of this madness is this guy. He's funny and decided "wouldn't it be cool if.." he became mayor of the North Pole. I thought a lot about this and decided that eventually Foursquare will attempt to battle this "fake check-in" issue. I think another way to cheat the system is by using a venue's supplied geo coordinates, and a bounding box I could "fake" a geo coordinate, and use it to check-in.

My "Strategery"

Pick a Fourquare venue, query the Foursquare API for the venue data. Use the venue's associated "geolat" and "geolong" as a starting geo coordinate. Then all you need is a bearing (in degrees), and a distance (in kilometers). This problem should take you all the way back to high school trigonometry (it did for me). Take those 4 values and plug them into the "move_lat_long" function (below), and voila your geo coordinate has been moved!

import math

def move_lat_long(latitude, longitude, distance, bearing):
        bearing = convert_to_radians(bearing)
        latitude = convert_to_radians(latitude)
        longitude = convert_to_radians(longitude)
        # earths radius in kilometers
        earth_radius = 6371
        d = float(distance)/float(earth_radius)
        latitude2 = math.asin( math.sin(latitude) * math.cos(d) + math.cos(latitude) * math.sin(d) * math.cos(bearing) )
        longitude2 = longitude + math.atan2( math.sin(bearing) * math.sin(d) * math.cos(latitude), math.cos(d) - math.sin(latitude) * math.sin(latitude2) )
        return convert_to_degrees(latitude2), convert_to_degrees(longitude2)

def convert_to_degrees(number):
        return (float(number) * (180/math.pi))

def convert_to_radians(number):
        return (float(number) * (math.pi/180))

For extra credit (I'm lame it's okay) I pulled apart the geo coordinates that are usually expressed in degrees ... into degrees, minutes, seconds.

def expand_geo_coordinate(coordinate):
        geo_coordinate = float(coordinate)
        geo_degrees = int(geo_coordinate)
        geo_minutes = (abs(geo_coordinate) % abs(geo_degrees)) * 60
        geo_seconds = (geo_minutes % int(geo_minutes)) * 60
        random_format = "[%s]  %d degress   %d minutes   %d seconds"
        return random_format % (coordinate, geo_degrees, geo_minutes, geo_seconds)

The only part that's left of "my diabolical plan" is picking a random distance, and a random bearing. There will be another post on the full project once I've successfully become mayor of a targeted venue.