141 lines
4.2 KiB
Python
141 lines
4.2 KiB
Python
"""
|
|
latitude/longitude functions
|
|
"""
|
|
|
|
import re
|
|
from math import radians, sin, cos, atan2, sqrt
|
|
|
|
def convert_lat_long_to_dms(lat_long, is_latitude=False, is_longitude=False):
|
|
"""
|
|
convert the LR format of N.N to the Exif GPS format
|
|
|
|
Args:
|
|
lat_long(str): latLong in (-)N.N format
|
|
is_latitude (bool, optional): flag, else we can't set North/Sout. Defaults to False.
|
|
is_longitude (bool, optional): flag, else we can't set West/East. Defaults to False.
|
|
|
|
Returns:
|
|
string: Deg,Min.Sec(NESW) format
|
|
"""
|
|
# minus part before . and then multiply rest by 60
|
|
degree = int(abs(lat_long))
|
|
minutes = round((float(abs(lat_long)) - int(abs(lat_long))) * 60, 10)
|
|
if is_latitude is True:
|
|
direction = 'S' if int(lat_long) < 0 else 'N'
|
|
elif is_longitude is True:
|
|
direction = 'W' if int(lat_long) < 0 else 'E'
|
|
else:
|
|
direction = '(INVALID)'
|
|
return f"{degree},{minutes}{direction}"
|
|
|
|
def convert_lat_to_dms(lat_long):
|
|
"""
|
|
wrapper functions for Long/Lat calls: latitude
|
|
|
|
Args:
|
|
lat_long(str): latLong in (-)N.N format
|
|
|
|
Returns:
|
|
string: Deg,Min.Sec(NESW) format
|
|
"""
|
|
return convert_lat_long_to_dms(lat_long, is_latitude=True)
|
|
|
|
|
|
# wrapper for Long/Lat call: longitute
|
|
def convert_long_to_dms(lat_long):
|
|
"""
|
|
wrapper for Long/Lat call: longitute
|
|
|
|
Args:
|
|
lat_long(str): latLong in (-)N.N format
|
|
|
|
Returns:
|
|
string: Deg,Min.Sec(NESW) format
|
|
"""
|
|
return convert_lat_long_to_dms(lat_long, is_longitude=True)
|
|
|
|
def long_lat_reg(longitude, latitude):
|
|
"""
|
|
converts the XMP/EXIF formatted GPS Long/Lat coordinates
|
|
from the <Degree>,<Minute.Second><NSEW> to the normal float
|
|
number used in google/lr internal
|
|
|
|
Args:
|
|
longitude(str): n,n.nNSEW format
|
|
latitude(str): n,n.nNSEW format
|
|
|
|
Returns:
|
|
dictionary: dict with converted lat/long
|
|
"""
|
|
# regex
|
|
latlong_re = re.compile(r'^(\d+),(\d+\.\d+)([NESW]{1})$')
|
|
# dict for loop
|
|
lat_long = {
|
|
'longitude': longitude,
|
|
'latitude': latitude
|
|
}
|
|
# for element in lat_long:
|
|
for index, element in lat_long.items():
|
|
# match if it is exif GPS format
|
|
_match = latlong_re.match(element)
|
|
if _match is not None:
|
|
# convert from Degree, Min.Sec into float format
|
|
lat_long[index] = float(_match.group(1)) + (float(_match.group(2)) / 60)
|
|
# if S or W => inverse to negative
|
|
if _match.group(3) == 'S' or _match.group(3) == 'W':
|
|
lat_long[index] *= -1
|
|
return lat_long
|
|
|
|
def convert_dms_to_lat(lat_long):
|
|
"""
|
|
rapper calls for DMS to Lat/Long: latitude
|
|
|
|
Args:
|
|
lat_long(str): n,n.nNSEW format
|
|
|
|
Returns:
|
|
dict: dict with converted lat/long
|
|
"""
|
|
return long_lat_reg('0,0.0N', lat_long)['latitude']
|
|
|
|
def convert_dms_to_long(lat_long):
|
|
"""
|
|
wrapper calls for DMS to Lat/Long: longitude
|
|
|
|
Args:
|
|
lat_long(str): n,n.nNSEW format
|
|
|
|
Returns:
|
|
dict: dict with converted lat/long
|
|
"""
|
|
return long_lat_reg(lat_long, '0,0.0N')['longitude']
|
|
|
|
def get_distance(from_longitude, from_latitude, to_longitude, to_latitude):
|
|
"""
|
|
calculates the difference between two coordinates
|
|
|
|
Args:
|
|
from_longitude(str): from longitude
|
|
from_latitude(str): from latitude
|
|
to_longitude(str): to longitude
|
|
to_latitude(str): to latitude
|
|
|
|
Returns:
|
|
float: distance in meters
|
|
"""
|
|
# earth radius in meters
|
|
earth_radius = 6378137.0
|
|
# convert all from radians with pre convert DMS to long and to float
|
|
from_longitude = radians(float(convert_dms_to_long(from_longitude)))
|
|
from_latitude = radians(float(convert_dms_to_lat(from_latitude)))
|
|
to_longitude = radians(float(convert_dms_to_long(to_longitude)))
|
|
to_latitude = radians(float(convert_dms_to_lat(to_latitude)))
|
|
# distance from - to
|
|
distance_longitude = from_longitude - to_longitude
|
|
distance_latitude = from_latitude - to_latitude
|
|
# main distance calculation
|
|
distance = sin(distance_latitude / 2)**2 + cos(from_latitude) * \
|
|
cos(to_latitude) * sin(distance_longitude / 2)**2
|
|
distance = 2 * atan2(sqrt(distance), sqrt(1 - distance))
|
|
return earth_radius * distance
|