Created
January 16, 2016 06:49
-
-
Save devangmundhra/a42845095f093f23ecd5 to your computer and use it in GitHub Desktop.
Finding venues within a radius (relies on PostgresSQL PostGIS)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This file exposes a function to convert a GET request with location and radius into a GEOS object to be able to run Postgres query on it | |
""" | |
from geo import geocode_location | |
def bounding_circle(get_location_params): | |
""" | |
get_location_params- string that consists of comma separated query param "location name,radius", something like "Connaught Place,10" | |
radius in km | |
""" | |
try: | |
param_list = get_location_params.split(',') | |
# Get lng, lat from geocode method | |
lng, lat = geocode_location(param_list[0]) | |
# Sent latidude,longitude,radius | |
return Point(lng, lat), float(param_list[1]) | |
except (IndexError, AttributeError, ValueError): | |
return None, 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This file exposes two functions- | |
1. to use a crude bounding box method to get min/max coordinates for a radius when an advanced DB like Postgres is not available | |
2. to convert any address into latitude and longitude using Google's Geocoding API | |
""" | |
def calc_bounding_box(lat, lon, radius, use_miles=True): | |
""" retval -> lat_min, lat_max, lon_min, lon_max | |
Calculates the max and min lat and lon for an area. | |
It approximates a search area of radius r by using a box | |
For further details: | |
http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates (section 3.3) | |
For testing output | |
http://www.getlatlon.com/ | |
""" | |
# d = distance | |
# R = Radius of sphere (6378.1 km or 3,963.1676 miles) | |
# r = d/R angular radius of query circle | |
R_MILES = 3963.1676 | |
R_KM = 6378.1 | |
lat = float(math.radians(lat)) | |
lon = float(math.radians(lon)) | |
radius = float(radius) | |
R = use_miles and R_MILES or R_KM | |
r = radius / R | |
lat_T = math.asin( math.sin(lat) / math.cos(r) ) | |
delta_lon = math.asin( math.sin(r) / math.cos(lat) ) | |
lon_min = math.degrees(lon - delta_lon) | |
lon_max = math.degrees(lon + delta_lon) | |
lat_min = math.degrees(lat - r) | |
lat_max = math.degrees(lat + r) | |
return lat_min, lat_max, lon_min, lon_max | |
def geocode_location(location, full=False): | |
""" | |
Use google geocode library | |
""" | |
key = getattr(settings, 'GOOGLE_MAPS_V3_APIKEY', None) | |
location = urllib.quote_plus(location.encode('utf8')) | |
if key: | |
request = "https://maps.googleapis.com/maps/api/geocode/json?address=%s&sensor=false&key=%s" % (location, key) | |
else: | |
request = "https://maps.googleapis.com/maps/api/geocode/json?address=%s&sensor=false" % (location) | |
data = urllib.urlopen(request).read() | |
dlist = json.loads(data) | |
""" | |
Find the latitude and longiture, and more information if full=True | |
""" | |
if dlist['status'] == "OK": | |
if full: | |
result = { | |
'lng': float(dlist['results'][0]['geometry']['location']['lng']), | |
'lat': float(dlist['results'][0]['geometry']['location']['lat']), | |
'region': _get_location_address_parameter(dlist, ['administrative_area_level_1', 'administrative_area_level_2']), | |
'country': _get_location_address_parameter(dlist, ['country']), | |
'city': _get_location_address_parameter(dlist, ['postal_town']), | |
} | |
return result | |
else: | |
lng = float(dlist['results'][0]['geometry']['location']['lng']) | |
lat = float(dlist['results'][0]['geometry']['location']['lat']) | |
return (lat, lng) | |
else: | |
if full: | |
return {} | |
return (0, 0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This file exposes a method that gets the GET request and returns a list of merchants that satisfy the location filter | |
""" | |
def merchant_location_search(get_params_location): | |
center, radius = bounding_circle(get_params_location) | |
if not center: | |
return Merchants.objects.none() | |
else: | |
merchants = Merchant.objects.filter(location__distance_lte=(center, D(km=radius))) | |
return merchants | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment