123 lines
2.8 KiB
Python
123 lines
2.8 KiB
Python
|
from geopy import units
|
||
|
|
||
|
# Unicode characters for symbols that appear in coordinate strings.
|
||
|
DEGREE = chr(176)
|
||
|
PRIME = chr(8242)
|
||
|
DOUBLE_PRIME = chr(8243)
|
||
|
ASCII_DEGREE = ''
|
||
|
ASCII_PRIME = "'"
|
||
|
ASCII_DOUBLE_PRIME = '"'
|
||
|
LATIN1_DEGREE = chr(176)
|
||
|
HTML_DEGREE = '°'
|
||
|
HTML_PRIME = '′'
|
||
|
HTML_DOUBLE_PRIME = '″'
|
||
|
XML_DECIMAL_DEGREE = '°'
|
||
|
XML_DECIMAL_PRIME = '′'
|
||
|
XML_DECIMAL_DOUBLE_PRIME = '″'
|
||
|
XML_HEX_DEGREE = '&xB0;'
|
||
|
XML_HEX_PRIME = '&x2032;'
|
||
|
XML_HEX_DOUBLE_PRIME = '&x2033;'
|
||
|
ABBR_DEGREE = 'deg'
|
||
|
ABBR_ARCMIN = 'arcmin'
|
||
|
ABBR_ARCSEC = 'arcsec'
|
||
|
|
||
|
DEGREES_FORMAT = (
|
||
|
"%(degrees)d%(deg)s %(minutes)d%(arcmin)s %(seconds)g%(arcsec)s"
|
||
|
)
|
||
|
|
||
|
UNICODE_SYMBOLS = {
|
||
|
'deg': DEGREE,
|
||
|
'arcmin': PRIME,
|
||
|
'arcsec': DOUBLE_PRIME
|
||
|
}
|
||
|
ASCII_SYMBOLS = {
|
||
|
'deg': ASCII_DEGREE,
|
||
|
'arcmin': ASCII_PRIME,
|
||
|
'arcsec': ASCII_DOUBLE_PRIME
|
||
|
}
|
||
|
LATIN1_SYMBOLS = {
|
||
|
'deg': LATIN1_DEGREE,
|
||
|
'arcmin': ASCII_PRIME,
|
||
|
'arcsec': ASCII_DOUBLE_PRIME
|
||
|
}
|
||
|
HTML_SYMBOLS = {
|
||
|
'deg': HTML_DEGREE,
|
||
|
'arcmin': HTML_PRIME,
|
||
|
'arcsec': HTML_DOUBLE_PRIME
|
||
|
}
|
||
|
XML_SYMBOLS = {
|
||
|
'deg': XML_DECIMAL_DEGREE,
|
||
|
'arcmin': XML_DECIMAL_PRIME,
|
||
|
'arcsec': XML_DECIMAL_DOUBLE_PRIME
|
||
|
}
|
||
|
ABBR_SYMBOLS = {
|
||
|
'deg': ABBR_DEGREE,
|
||
|
'arcmin': ABBR_ARCMIN,
|
||
|
'arcsec': ABBR_ARCSEC
|
||
|
}
|
||
|
|
||
|
|
||
|
def format_degrees(degrees, fmt=DEGREES_FORMAT, symbols=None):
|
||
|
"""
|
||
|
TODO docs.
|
||
|
"""
|
||
|
symbols = symbols or ASCII_SYMBOLS
|
||
|
arcminutes = units.arcminutes(degrees=degrees - int(degrees))
|
||
|
arcseconds = units.arcseconds(arcminutes=arcminutes - int(arcminutes))
|
||
|
format_dict = dict(
|
||
|
symbols,
|
||
|
degrees=degrees,
|
||
|
minutes=abs(arcminutes),
|
||
|
seconds=abs(arcseconds)
|
||
|
)
|
||
|
return fmt % format_dict
|
||
|
|
||
|
|
||
|
DISTANCE_FORMAT = "%(magnitude)s%(unit)s"
|
||
|
DISTANCE_UNITS = {
|
||
|
'km': lambda d: d,
|
||
|
'm': lambda d: units.meters(kilometers=d),
|
||
|
'mi': lambda d: units.miles(kilometers=d),
|
||
|
'ft': lambda d: units.feet(kilometers=d),
|
||
|
'nm': lambda d: units.nautical(kilometers=d),
|
||
|
'nmi': lambda d: units.nautical(kilometers=d)
|
||
|
}
|
||
|
|
||
|
|
||
|
def format_distance(kilometers, fmt=DISTANCE_FORMAT, unit='km'):
|
||
|
"""
|
||
|
TODO docs.
|
||
|
"""
|
||
|
magnitude = DISTANCE_UNITS[unit](kilometers)
|
||
|
return fmt % {'magnitude': magnitude, 'unit': unit}
|
||
|
|
||
|
|
||
|
_DIRECTIONS = [
|
||
|
('north', 'N'),
|
||
|
('north by east', 'NbE'),
|
||
|
('north-northeast', 'NNE'),
|
||
|
('northeast by north', 'NEbN'),
|
||
|
('northeast', 'NE'),
|
||
|
('northeast by east', 'NEbE'),
|
||
|
('east-northeast', 'ENE'),
|
||
|
('east by north', 'EbN'),
|
||
|
('east', 'E'),
|
||
|
('east by south', 'EbS'),
|
||
|
('east-southeast', 'ESE'),
|
||
|
('southeast by east', 'SEbE'),
|
||
|
('southeast', 'SE'),
|
||
|
('southeast by south', 'SEbS'),
|
||
|
]
|
||
|
|
||
|
DIRECTIONS, DIRECTIONS_ABBR = zip(*_DIRECTIONS)
|
||
|
ANGLE_DIRECTIONS = {
|
||
|
n * 11.25: d
|
||
|
for n, d
|
||
|
in enumerate(DIRECTIONS)
|
||
|
}
|
||
|
ANGLE_DIRECTIONS_ABBR = {
|
||
|
n * 11.25: d
|
||
|
for n, d
|
||
|
in enumerate(DIRECTIONS_ABBR)
|
||
|
}
|