import math
'''
Synapse module with helpers for earth based geospatial calculations.
'''
# base earth geo distances will be in mm
r_mm = 6371008800.0
r_km = 6371.0088
# investigate perf impact of using WGS-84 ellipsoid for dist calc
[docs]
def latlong(text):
'''
Chop a latlong string and return (float,float).
Does not perform validation on the coordinates.
Args:
text (str): A longitude,latitude string.
Returns:
(float,float): A longitude, latitude float tuple.
'''
nlat, nlon = text.split(',')
return (float(nlat), float(nlon))
[docs]
def near(point, dist, points):
'''
Determine if the given point is within dist of any of points.
Args:
point ((float,float)): A latitude, longitude float tuple.
dist (int): A distance in mm ( base units )
points (list): A list of latitude, longitude float tuples to compare against.
'''
for cmpt in points:
if haversine(point, cmpt) <= dist:
return True
return False
[docs]
def haversine(px, py, r=r_mm):
'''
Calculate the haversine distance between two points
defined by (lat,lon) tuples.
Args:
px ((float,float)): lat/long position 1
py ((float,float)): lat/long position 2
r (float): Radius of sphere
Returns:
(int): Distance in mm.
'''
lat1, lon1 = px
lat2, lon2 = py
dlat = math.radians(lat2 - lat1)
dlon = math.radians(lon2 - lon1)
lat1 = math.radians(lat1)
lat2 = math.radians(lat2)
a = math.sin(dlat / 2) ** 2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon / 2) ** 2
c = 2 * math.asin(math.sqrt(a))
return c * r
[docs]
def bbox(lat, lon, dist):
'''
Calculate a min/max bounding box for the circle defined by lat/lon/dist.
Args:
lat (float): The latitude in degrees
lon (float): The longitude in degrees
dist (int): A distance in geo:dist base units (mm)
Returns:
(float,float,float,float): (latmin, latmax, lonmin, lonmax)
'''
latr = math.radians(lat)
lonr = math.radians(lon)
rad = r_mm
prad = rad * math.cos(latr)
latd = dist / rad
lond = dist / prad
latmin = math.degrees(latr - latd)
latmax = math.degrees(latr + latd)
lonmin = math.degrees(lonr - lond)
lonmax = math.degrees(lonr + lond)
return (latmin, latmax, lonmin, lonmax)
[docs]
def dms2dec(degs, mins, secs):
'''
Convert degrees, minutes, seconds lat/long form to degrees float.
Args:
degs (int): Degrees
mins (int): Minutes
secs (int): Seconds
Returns:
(float): Degrees
'''
return degs + (mins / 60.0) + (secs / 3600.0)