Coverage for pygeodesy/dms.py : 96%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# -*- coding: utf-8 -*-
Functions to parse and format bearing, compass, lat- and longitudes in various forms of degrees, minutes and seconds with or without degrees, minute and second symbols plus a compass point suffix, including parsing of C{decimal} and C{sexagecimal} degrees.
After I{(C) Chris Veness 2011-2015} published under the same MIT Licence**, see U{Latitude/Longitude<https://www.Movable-Type.co.UK/scripts/latlong.html>} and U{Vector-based geodesy<https://www.Movable-Type.co.UK/scripts/latlong-vectors.html>}.
@var F_D: Format degrees as unsigned "deg°" with symbol, plus compass point suffix C{N, S, E} or C{W} (C{str}). @var F_DM: Format degrees as unsigned "deg°min′" with symbols, plus suffix (C{str}). @var F_DMS: Format degrees as unsigned "deg°min′sec″" with symbols, plus suffix (C{str}). @var F_DEG: Format degrees as unsigned "[D]DD" I{without} symbol, plus suffix (C{str}). @var F_MIN: Format degrees as unsigned "[D]DDMM" I{without} symbols, plus suffix (C{str}). @var F_SEC: Format degrees as unsigned "[D]DDMMSS" I{without} symbols, plus suffix (C{str}). @var F_D60: Format degrees as unsigned "[D]DD.MMSS" C{sexagecimal} I{without} symbols, plus suffix (C{str}). @var F__E: Format degrees as unsigned "%E" I{without} symbols, plus suffix (C{str}). @var F__F: Format degrees as unsigned "%F" I{without} symbols, plus suffix (C{str}). @var F__G: Format degrees as unsigned "%G" I{without} symbols, plus suffix (C{str}). @var F_RAD: Convert degrees to radians and format as unsigned "RR" with symbol, plus suffix (C{str}).
@var F_D_: Format degrees as signed "-/deg°" with symbol, I{without} suffix (C{str}). @var F_DM_: Format degrees as signed "-/deg°min′" with symbols, I{without} suffix (C{str}). @var F_DMS_: Format degrees as signed "-/deg°min′sec″" with symbols, I{without} suffix (C{str}). @var F_DEG_: Format degrees as signed "-/[D]DD" I{without} symbol, I{without} suffix (C{str}). @var F_MIN_: Format degrees as signed "-/[D]DDMM" I{without} symbols, I{without} suffix (C{str}). @var F_SEC_: Format degrees as signed "-/[D]DDMMSS" I{without} symbols, I{without} suffix (C{str}). @var F_D60_: Format degrees as signed "-/[D]DD.MMSS" C{sexagecimal} I{without} symbols, I{without} suffix (C{str}). @var F__E_: Format degrees as signed "-/%E" I{without} symbols, I{without} suffix (C{str}). @var F__F_: Format degrees as signed "-/%F" I{without} symbols, I{without} suffix (C{str}). @var F__G_: Format degrees as signed "-/%G" I{without} symbols, I{without} suffix (C{str}). @var F_RAD_: Convert degrees to radians and format as signed "-/RR" I{without} symbol, I{without} suffix (C{str}).
@var F_D__: Format degrees as signed "-/+deg°" with symbol, I{without} suffix (C{str}). @var F_DM__: Format degrees as signed "-/+deg°min′" with symbols, I{without} suffix (C{str}). @var F_DMS__: Format degrees as signed "-/+deg°min′sec″" with symbols, I{without} suffix (C{str}). @var F_DEG__: Format degrees as signed "-/+[D]DD" I{without} symbol, I{without} suffix (C{str}). @var F_MIN__: Format degrees as signed "-/+[D]DDMM" I{without} symbols, without suffix (C{str}). @var F_SEC__: Format degrees as signed "-/+[D]DDMMSS" I{without} symbols, I{without} suffix (C{str}). @var F_D60__: Format degrees as signed "-/+[D]DD.MMSS" C{sexagecimal} I{without} symbols, I{without} suffix (C{str}). @var F__E__: Format degrees as signed "-/+%E" I{without} symbols, I{without} suffix (C{str}). @var F__F__: Format degrees as signed "-/+%F" I{without} symbols, I{without} suffix (C{str}). @var F__G__: Format degrees as signed "-/+%G" I{without} symbols, I{without} suffix (C{str}). @var F_RAD__: Convert degrees to radians and format as signed "-/+RR" I{without} symbol, I{without} suffix (C{str}).
@var S_DEG: Degrees symbol, default C{"°"} @var S_MIN: Minutes symbol, default C{"′"} aka I{PRIME} @var S_SEC: Seconds symbol, default C{"″"} aka I{DOUBLE_PRIME} @var S_RAD: Radians symbol, default C{""} aka L{pygeodesy.NN} @var S_DMS: If C{True} include, otherwise cancel all DMS symbols, default C{True}. @var S_SEP: Separator between C{deg°|min′|sec″|suffix}, default C{""} aka L{pygeodesy.NN}
@note: In Python 2-, L{S_DEG}, L{S_MIN}, L{S_SEC}, L{S_RAD} and L{S_SEP} may be multi-byte, non-ascii characters and if so, I{not} C{unicode}. '''
neg as _neg # in .ups _ValueError, _xkwds, _xkwds_get _0_, _e_, _E_, _EW_, _f_, _F_, _g_, _invalid_, _MINUS_, \ _N_, _NE_, _NS_, _NSEW_, _NW_, _PERCENTDOTSTAR_, _PLUS_, \ _PLUSMINUS_, _QUOTE1_, _QUOTE2_, _radians_, _S_, _SE_, \ _SPACE_, _SW_, _W_
except ImportError: # Python 3+ from string import ascii_letters as _LETTERS
_d_, 'dm', 'dms', _deg_, 'min', 'sec', 'd60', _e_, _f_, _g_, 'rad') _MINUS_, _) for _ in _F_s) _PLUS_, _) for _ in _F_s)
F_DM: F_DM, F_MIN: F_DM, _deg_min_: F_DM, F_D60: F_D60, F_RAD: F_RAD, _radians_: F_RAD, F__E: F__E, F__F: F__F, F__G: F__G} # default F_DMS
F_DEG: 6, F_MIN: 4, F_SEC: 2, F_D60: 0, F__E: 8, F__F: 8, F__G: 8, F_RAD: 5}
# note: ord(_DEGREES_) == ord('°') == 176, ord('˚') == 730 S_MIN: _MINUTES_, '’': _MINUTES_, _QUOTE1_: _MINUTES_, # _r_: _RADIANS_ S_SEC: _SECONDS_, '”': _SECONDS_, _QUOTE2_: _SECONDS_}
_E_, 'EbS', 'ESE', 'SEbE', _SE_, 'SEbS', 'SSE', 'SbE', _S_, 'SbW', 'SSW', 'SWbS', _SW_, 'SWbW', 'WSW', 'WbS', _W_, 'WbN', 'WNW', 'NWbW', _NW_, 'NWbN', 'NNW', 'NbW')
'''(INTERNAL) Get the overridden or default pseudo-C{DMS} symbols. ''' else: # no overriden symbols return _DOT_, sep, S_NUL
'''(INTERNAL) Get the overridden or default C{DMS} symbols. '''
'''(INTERNAL) Format C{d} as (deg, min, sec) C{str}s with leading zeros. ''' _0wpF( 2, 0, m), _0wpF(w+2, p, s))
'''(INTERNAL) Pass-thru version of C{.streprs.fstrzs}. '''
'''(INTERNAL) Return sign, stripped B{C{strDMS}} and compass point. '''
'''(INTERNAL) Convert C{deg} to C{str}, with/-out sign, DMS symbols and/or suffix. ''' except (TypeError, ValueError) as x: raise _ValueError(deg=deg, form=form, prec=prec, txt=str(x))
_PLUS_ if deg > 0 and form[:1] == _PLUS_ else NN) else: # suffixed suff = NN(sep, suff) except KeyError: form = form.lower() # .strip() F = _F_case.get(form, F_DMS)
else:
m, M, sep, z(s), S, suff)
z(_0wpF(w+2, p, m)), M, suff)
else: # F in (F__E, F__F, F__G)
'''Convert bearing to a string (without compass point suffix).
@arg bearing: Bearing from North (compass C{degrees360}). @kwarg form: Format specifier for B{C{deg}} (C{str} or L{F_D}, L{F_DM}, L{F_DMS}, L{F_DEG}, L{F_MIN}, L{F_SEC}, L{F_D60}, L{F__E}, L{F__F}, L{F__G}, L{F_RAD}, L{F_D_}, L{F_DM_}, L{F_DMS_}, L{F_DEG_}, L{F_MIN_}, L{F_SEC_}, L{F_D60_}, L{F__E_}, L{F__F_}, L{F__G_}, L{F_RAD_}, L{F_D__}, L{F_DM__}, L{F_DMS__}, L{F_DEG__}, L{F_MIN__}, L{F_SEC__}, L{F_D60__}, L{F__E__}, L{F__F__}, L{F__G__} or L{F_RAD__}). @kwarg prec: Number of decimal digits (0..9 or C{None} for default). Trailing zero decimals are stripped for B{C{prec}} values of 1 and above, but kept for negative B{C{prec}}. @kwarg sep: Separator between degrees, minutes, seconds, suffix (C{str}). @kwarg s_D_M_S: Optional keyword arguments C{B{s_D}=str}, C{B{s_M}=str}, C{B{s_S}=str} and C{B{s_DMS}=True} to override any or cancel all DMS symbols, defaults L{S_DEG}, L{S_MIN} respectively L{S_SEC}.
@return: Compass degrees per the specified B{C{form}} (C{str}).
@see: Function L{pygeodesy.toDMS}. '''
'''(INTERNAL) Helper for C{clipDegrees} and C{clipRadians}. ''' copysign0(limit, angle), units) raise RangeError(t, txt=None)
'''Clip a lat- or longitude to the given range.
@arg deg: Unclipped lat- or longitude (C{scalar degrees}). @arg limit: Valid C{-/+B{limit}} range (C{degrees}).
@return: Clipped value (C{degrees}).
@raise RangeError: If B{C{deg}} outside the valid C{-/+B{limit}} range and L{pygeodesy.rangerrors} set to C{True}. '''
'''Clip a lat- or longitude to the given range.
@arg rad: Unclipped lat- or longitude (C{radians}). @arg limit: Valid C{-/+B{limit}} range (C{radians}).
@return: Clipped value (C{radians}).
@raise RangeError: If B{C{rad}} outside the valid C{-/+B{limit}} range and L{pygeodesy.rangerrors} set to C{True}. '''
'''Convert bearing to a string suffixed with compass point.
@arg bearing: Bearing from North (compass C{degrees360}). @kwarg form: Format specifier for B{C{deg}} (C{str} or L{F_D}, L{F_DM}, L{F_DMS}, L{F_DEG}, L{F_MIN}, L{F_SEC}, L{F_D60}, L{F__E}, L{F__F}, L{F__G}, L{F_RAD}, L{F_D_}, L{F_DM_}, L{F_DMS_}, L{F_DEG_}, L{F_MIN_}, L{F_SEC_}, L{F_D60_}, L{F__E_}, L{F__F_}, L{F__G_}, L{F_RAD_}, L{F_D__}, L{F_DM__}, L{F_DMS__}, L{F_DEG__}, L{F_MIN__}, L{F_SEC__}, L{F_D60__}, L{F__E__}, L{F__F__}, L{F__G__} or L{F_RAD__}). @kwarg prec: Number of decimal digits (0..9 or C{None} for default). Trailing zero decimals are stripped for B{C{prec}} values of 1 and above, but kept for negative B{C{prec}}. @kwarg sep: Separator between degrees, minutes, seconds, suffix (C{str}). @kwarg s_D_M_S: Optional keyword arguments C{B{s_D}=str}, C{B{s_M}=str} C{B{s_S}=str} and C{B{s_DMS}=True} to override any or cancel all DMS symbols, defaults L{S_DEG}, L{S_MIN} respectively L{S_SEC}.
@return: Compass degrees and point in the specified form (C{str}).
@see: Function L{pygeodesy.toDMS}. '''
'''Convert bearing to a compass point.
@arg bearing: Bearing from North (compass C{degrees360}). @kwarg prec: Precision, number of compass point characters: 1 for cardinal or basic winds, 2 for intercardinal or ordinal or principal winds, 3 for secondary-intercardinal or half-winds or 4 for quarter-winds).
@return: Compass point (1-, 2-, 3- or 4-letter C{str}).
@raise ValueError: Invalid B{C{prec}}.
@see: U{Dms.compassPoint <https://GitHub.com/ChrisVeness/geodesy/blob/master/dms.js>} and U{Compass rose<https://WikiPedia.org/wiki/Compass_rose>}.
@example:
>>> p = compassPoint(24, 1) # 'N' >>> p = compassPoint(24, 2) # 'NE' >>> p = compassPoint(24, 3) # 'NNE' >>> p = compassPoint(24) # 'NNE' >>> p = compassPoint(11, 4) # 'NbE' >>> p = compassPoint(30, 4) # 'NEbN'
>>> p = compassPoint(11.249) # 'N' >>> p = compassPoint(11.25) # 'NNE' >>> p = compassPoint(-11.25) # 'N' >>> p = compassPoint(348.749) # 'NNW' ''' # not round(), i.e. half-even rounding in Python 3+, # but round-away-from-zero as int(b + 0.5) iff b is # non-negative, otherwise int(b + copysign0(_0_5, b)) t = _invalid_ except (IndexError, TypeError, ValueError) as x: t = str(x) raise _ValueError(bearing=bearing, prec=prec, txt=t)
'''Convert degrees to a string in degrees, minutes I{or} seconds.
@arg deg: Value in degrees (C{scalar degrees}). @kwarg prec: Number of decimal digits (0..9 or C{None} for default). Trailing zero decimals are stripped for B{C{prec}} values of 1 and above, but kept for negative B{C{prec}}. @kwarg s_D: D symbol for degrees (C{str}). @kwarg s_M: M symbol for minutes (C{str}) or C{""}. @kwarg s_S: S symbol for seconds (C{str}) or C{""}. @kwarg neg: Optional sign for negative (C{'-'}). @kwarg pos: Optional sign for positive (C{''}).
@return: I{Either} degrees, minutes I{or} seconds (C{str}).
@see: Function L{pygeodesy.toDMS}. ''' except (TypeError, ValueError) as x: raise _ValueError(deg=deg, prec=prec, txt=str(x))
else:
'''Convert latitude to a string, optionally suffixed with N or S.
@arg deg: Latitude to be formatted (C{scalar degrees}). @kwarg form: Format specifier for B{C{deg}} (C{str} or L{F_D}, L{F_DM}, L{F_DMS}, L{F_DEG}, L{F_MIN}, L{F_SEC}, L{F_D60}, L{F__E}, L{F__F}, L{F__G}, L{F_RAD}, L{F_D_}, L{F_DM_}, L{F_DMS_}, L{F_DEG_}, L{F_MIN_}, L{F_SEC_}, L{F_D60_}, L{F__E_}, L{F__F_}, L{F__G_}, L{F_RAD_}, L{F_D__}, L{F_DM__}, L{F_DMS__}, L{F_DEG__}, L{F_MIN__}, L{F_SEC__}, L{F_D60__}, L{F__E__}, L{F__F__}, L{F__G__} or L{F_RAD__}). @kwarg prec: Number of decimal digits (0..9 or C{None} for default). Trailing zero decimals are stripped for B{C{prec}} values of 1 and above, but kept for negative B{C{prec}}. @kwarg sep: Separator between degrees, minutes, seconds, suffix (C{str}). @kwarg s_D_M_S: Optional keyword arguments C{B{s_D}=str}, C{B{s_M}=str} C{B{s_S}=str} and C{B{s_DMS}=True} to override any or cancel all DMS symbols, defaults L{S_DEG}, L{S_MIN} respectively L{S_SEC}.
@return: Degrees in the specified form (C{str}).
@see: Functions L{pygeodesy.toDMS} and L{pygeodesy.lonDMS}. '''
'''Convert one or more C{LatLon} instances to strings.
@arg lls: Single or list, sequence, tuple, etc. (C{LatLon}s). @kwarg m_form_prec_sep_s_D_M_S: Optional C{B{m}eter}, C{B{form}at}, C{B{prec}ision}, I{DEPRECATED} B{C{sep}}, B{C{s_D}}, B{C{s_M}}, B{C{s_S}} and B{C{s_DMS}} keyword arguments, see method C{LatLon.toStr} and functions L{pygeodesy.latDMS} and L{pygeodesy.lonDMS}.
@return: A C{tuple} of C{str}s if B{C{lls}} is a list, sequence, tuple, etc. of C{LatLon} instances or a single C{str} if B{C{lls}} is a single C{LatLon}.
@see: Functions L{pygeodesy.latDMS}, L{pygeodesy.latlonDMS_}, L{pygeodesy.lonDMS} and L{pygeodesy.toDMS} and method C{LatLon.toStr}.
@note: Keyword argument C{B{sep}=None} to return a C{str}ing instead of the C{tuple}, has been I{DEPRECATED}, use C{B{sep}.join(B{latlonDMS_}(...))}. ''' t = sep.join(t) else: raise _TypeError(lls=lls, **m_form_prec_sep_s_D_M_S)
'''Convert one or more C{LatLon} instances to strings.
@arg lls: The instances, all positional arguments (C{LatLon}s). @kwarg m_form_prec_sep_s_D_M_S: Optional C{B{m}eter}, C{B{form}at}, C{B{prec}ision}, I{DEPRECATED} B{C{sep}}, B{C{s_D}}, B{C{s_M}}, B{C{s_S}} and B{C{s_DMS}} keyword arguments, see method C{LatLon.toStr} and functions L{pygeodesy.latDMS} and L{pygeodesy.lonDMS}.
@return: A C{tuple} of C{str}s if 2 or more C{LatLon} instances or a single C{str} if only a single C{LatLon} instance is given in B{C{lls}}.
@see: Function L{pygeodesy.latlonDMS}.
@note: Keyword argument C{B{sep}=None} to return a C{str}ing instead of the C{tuple}, has been I{DEPRECATED}, use C{B{sep}.join(B{latlonDMS_}(...))}. ''' raise _ValueError(lls=lls, **m_form_prec_sep_s_D_M_S) lls, sep = lls[0], None
'''DEPRECATED, instead use: %r.join(%s(...))''' k = _SPACE_(_keyword_, _arg_, Fmt.EQUAL(sep=repr(sep)), _of_) n = where.__name__ t = _latlonDMS_sep2.__doc__ % (sep, n) _MODS.props._throwarning(k, n, t)
'''Convert longitude to a string, optionally suffixed with E or W.
@arg deg: Longitude to be formatted (C{scalar degrees}). @kwarg form: Format specifier for B{C{deg}} (C{str} or L{F_D}, L{F_DM}, L{F_DMS}, L{F_DEG}, L{F_MIN}, L{F_SEC}, L{F_D60}, L{F__E}, L{F__F}, L{F__G}, L{F_RAD}, L{F_D_}, L{F_DM_}, L{F_DMS_}, L{F_DEG_}, L{F_MIN_}, L{F_SEC_}, L{F_D60_}, L{F__E_}, L{F__F_}, L{F__G_}, L{F_RAD_}, L{F_D__}, L{F_DM__}, L{F_DMS__}, L{F_DEG__}, L{F_MIN__}, L{F_SEC__}, L{F_D60__}, L{F__E__}, L{F__F__}, L{F__G__} or L{F_RAD__}). @kwarg prec: Number of decimal digits (0..9 or C{None} for default). Trailing zero decimals are stripped for B{C{prec}} values of 1 and above, but kept for negative B{C{prec}}. @kwarg sep: Separator between degrees, minutes, seconds, suffix (C{str}). @kwarg s_D_M_S: Optional keyword arguments C{B{s_D}=str}, C{B{s_M}=str} C{B{s_S}=str} and C{B{s_DMS}=True} to override any or cancel all DMS symbols, defaults L{S_DEG}, L{S_MIN} respectively L{S_SEC}.
@return: Degrees in the specified form (C{str}).
@see: Functions L{pygeodesy.toDMS} and L{pygeodesy.latDMS}. '''
'''Normalize all degrees, minutes and seconds (DMS) symbols in a string to the default symbols L{S_DEG}, L{S_MIN}, L{S_SEC}.
@arg strDMS: Original DMS string (C{str}). @kwarg norm: Optional replacement symbol (C{str}) or C{None} for the default DMS symbols). Use C{B{norm}=""} to remove all DMS symbols. @kwarg s_D_M_S: Optional, alternate DMS symbols C{B{s_D}=str}, C{B{s_M}=str}, C{B{s_S}=str} and/or C{B{s_R}=str} for radians, each to be replaced by B{C{norm}}.
@return: Normalized DMS (C{str}). '''
# XXX strDMS isn't unicode in Python 2- and looping # thru strDMS will yield each byte, hence the loop # thru _s2S2 and replacing the DMS symbols in strDMS
else: # replace or remove all DMS
'''Parse a lat- or longitude represention forms as [D]DDMMSS in degrees.
@arg strDDDMMSS: Degrees in any of several forms (C{str}) and types (C{float}, C{int}, other). @kwarg suffix: Optional, valid compass points (C{str}, C{tuple}). @kwarg sep: Optional separator between "[D]DD", "MM", "SS", B{C{suffix}} (L{S_SEP}). @kwarg clip: Optionally, limit value to range C{-/+B{clip}} (C{degrees}). @kwarg sexagecimal: If C{True}, convert C{"D.MMSS"} or C{float(D.MMSS)} to C{base-60} "MM" and "SS" digits. See C{form}s L{F_D60}, L{F_D60_} and L{F_D60__}.
@return: Degrees (C{float}).
@raise ParseError: Invalid B{C{strDDDMMSS}} or B{C{clip}} or the form of B{C{strDDDMMSS}} is incompatible with the suffixed or B{C{suffix}} compass point.
@raise RangeError: Value of B{C{strDDDMMSS}} outside the valid C{-/+B{clip}} range and L{pygeodesy.rangerrors} set to C{True}.
@note: Type C{str} values "[D]DD", "[D]DDMM", "[D]DDMMSS" and "[D]DD.MMSS" for B{C{strDDDMMSS}} are parsed properly only if I{either} unsigned and suffixed with a valid, compatible, C{cardinal} L{compassPoint} I{or} signed I{or} unsigned, unsuffixed and with keyword argument B{C{suffix}="NS"}, B{C{suffix}="EW"} or a compatible L{compassPoint}.
@note: Unlike function L{parseDMS}, type C{float}, C{int} and other non-C{str} B{C{strDDDMMSS}} values are interpreted as C{form} [D]DDMMSS or [D]DD.MMSS. For example, C{int(1230)} is returned as 12.5 and I{not 1230.0} degrees. However, C{int(345)} is considered C{form} "DDD" 345 I{and not "DDMM" 0345}, unless B{C{suffix}} specifies the compass point. Also, C{float(15.0523)} is returned as 15.0523 decimal degrees and I{not 15°5′23″ sexagecimal}. To consider the latter, use C{float(15.0523)} or C{"15.0523"} and specify the keyword argument C{B{sexagecimal}=True}.
@see: Functions L{pygeodesy.parseDMS}, L{pygeodesy.parseDMS2} and L{pygeodesy.parse3llh}. ''' (P in S and s.isdigit()) or (P.isdigit() and s in _SDIGITS_ # PYCHOK indent and S in _WINDS)): # check [D]DDMMSS form and compass point raise ParseError('form %s applies %s' % t)
raise ParseError('%s digits (%s)' % (_sexagecimal_, n))
else: # float or int to [D]DDMMSS[.fff] s = P = _0_ # anything except NN, _S_, _SW_, _W_ f = -f s = _MINUS_ t = (_0_ * (m - n)) + t # ... match the given compass point # P = S # elif n > 1: # P = (_EW_ if isodd(n) else _NS_)[0]
else: else: # [D]DDMMSS[.sss]
strDDDMMSS=strDDDMMSS, suffix=suffix, sexagecimal=sexagecimal)
'''(INTERNAL) Helper for C{parseDDDMMSS} and C{_DMS2deg}. '''
'''(INTERNAL) Helper for C{parseDDDMMSS} and C{parseDMS}. '''
except (TypeError, ValueError): s, t, P = _split3(strDMS, suffix.upper()) if sep: # remove all DMS symbols t = t.replace(sep, _SPACE_) t = normDMS(t, norm=NN, **s_D_M_S) else: # replace all DMS symbols t = normDMS(t, norm=_SPACE_, **s_D_M_S) t = map2(float, t.strip().split()) d = _dms2deg(s, P, *t[:3])
'''Parse a lat- or longitude representation in C{degrees}.
This is very flexible on formats, allowing signed decimal degrees, degrees and minutes or degrees minutes and seconds optionally suffixed by a cardinal compass point.
A variety of symbols, separators and suffixes are accepted, for example "3°37′09″W". Minutes and seconds may be omitted.
@arg strDMS: Degrees in any of several forms (C{str}) and types (C{float}, C{int}, other). @kwarg suffix: Optional, valid compass points (C{str}, C{tuple}). @kwarg sep: Optional separator between deg°, min′, sec″, B{C{suffix}} (C{''}). @kwarg clip: Optionally, limit value to range C{-/+B{clip}} (C{degrees}). @kwarg s_D_M_S: Optional, alternate symbol for degrees C{B{s_D}=str}, minutes, C{B{s_M}=str} and/or seconds C{B{s_S}=str}.
@return: Degrees (C{float}).
@raise ParseError: Invalid B{C{strDMS}} or B{C{clip}}.
@raise RangeError: Value of B{C{strDMS}} outside the valid C{-/+B{clip}} range and L{pygeodesy.rangerrors} set to C{True}.
@note: Unlike function L{parseDDDMMSS}, type C{float}, C{int} and other non-C{str} B{C{strDMS}} values are considered decimal (and not sexagecimal) degrees. For example, C{int(1230)} is returned as 1230.0 I{and not as 12.5} degrees and C{float(345)} as 345.0 I{and not as 3.75} degrees!
@see: Functions L{pygeodesy.parseDDDMMSS}, L{pygeodesy.parseDMS2}, L{pygeodesy.parse3llh} and L{pygeodesy.toDMS}. '''
'''Parse a lat- and a longitude representions C{"lat, lon"} in C{degrees}.
@arg strLat: Latitude in any of several forms (C{str} or C{degrees}). @arg strLon: Longitude in any of several forms (C{str} or C{degrees}). @kwarg sep: Optional separator between deg°, min′, sec″, suffix (C{''}). @kwarg clipLat: Limit latitude to range C{-/+B{clipLat}} (C{degrees}). @kwarg clipLon: Limit longitude to range C{-/+B{clipLon}} (C{degrees}). @kwarg s_D_M_S: Optional, alternate symbol for degrees C{B{s_D}=str}, minutes, C{B{s_M}=str} and/or seconds C{B{s_S}=str}.
@return: A L{LatLon2Tuple}C{(lat, lon)} in C{degrees}.
@raise ParseError: Invalid B{C{strLat}} or B{C{strLon}}.
@raise RangeError: Value of B{C{strLat}} or B{C{strLon}} outside the valid C{-/+B{clipLat}} or C{-/+B{clipLon}} range and L{pygeodesy.rangerrors} set to C{True}.
@note: See the B{Notes} at function L{parseDMS}.
@see: Functions L{pygeodesy.parseDDDMMSS}, L{pygeodesy.parseDMS}, L{pygeodesy.parse3llh} and L{pygeodesy.toDMS}. '''
parseDMS(strLon, suffix=_EW_, sep=sep, clip=clipLon, **s_D_M_S))
'''Parse a string C{"lat, lon [, h]"} representing lat-, longitude in C{degrees} and optional height in C{meter}.
The lat- and longitude value must be separated by a separator character. If height is present it must follow, separated by another separator.
The lat- and longitude values may be swapped, provided at least one ends with the proper compass point.
@arg strllh: Latitude, longitude[, height] (C{str}, ...). @kwarg height: Optional, default height (C{meter}) or C{None}. @kwarg sep: Optional separator between C{"lat lon [h] suffix"} (C{str}). @kwarg clipLat: Limit latitude to range C{-/+B{clipLat}} (C{degrees}). @kwarg clipLon: Limit longitude to range C{-/+B{clipLon}} (C{degrees}). @kwarg s_D_M_S: Optional, alternate symbol for degrees C{B{s_D}=str}, minutes, C{B{s_M}=str} and/or seconds C{B{s_S}=str}.
@return: A L{LatLon3Tuple}C{(lat, lon, height)} in C{degrees}, C{degrees} and C{float}.
@raise RangeError: Lat- or longitude value of B{C{strllh}} outside the valid C{-/+B{clipLat}} or C{-/+B{clipLon}} range and L{pygeodesy.rangerrors} set to C{True}.
@raise ValueError: Invalid B{C{strllh}} or B{C{height}}.
@note: See the B{Notes} at function L{parseDMS}.
@see: Functions L{pygeodesy.parseDDDMMSS}, L{pygeodesy.parseDMS}, L{pygeodesy.parseDMS2} and L{pygeodesy.toDMS}.
@example:
>>> parse3llh('000°00′05.31″W, 51° 28′ 40.12″ N') (51.4778°N, 000.0015°W, 0) '''
else: raise ValueError
parseDMS(b, suffix=_EW_, clip=clipLon, **s_D_M_S), h)
'''Parse a string representing angle in C{radians}.
@arg strRad: Degrees in any of several forms (C{str} or C{radians}). @kwarg suffix: Optional, valid compass points (C{str}, C{tuple}). @kwarg clip: Optionally, limit value to range C{-/+B{clip}} (C{radians}).
@return: Radians (C{float}).
@raise ParseError: Invalid B{C{strRad}} or B{C{clip}}.
@raise RangeError: Value of B{C{strRad}} outside the valid C{-/+B{clip}} range and L{pygeodesy.rangerrors} set to C{True}. '''
except (TypeError, ValueError): s, t, P = _split3(strRad, suffix.upper()) r = _dms2deg(s, P, float(t))
'''Set the default precison for a given F_ form.
@arg form: L{F_D}, L{F_DM}, L{F_DMS}, L{F_DEG}, L{F_MIN}, L{F_SEC}, L{F_D60}, L{F__E}, L{F__F}, L{F__G} or L{F_RAD} (C{str}). @kwarg prec: Number of decimal digits (0..9 or C{None} for default). Trailing zero decimals are stripped for B{C{prec}} values of 1 and above, but kept for negative B{C{prec}}.
@return: Previous precision for the B{C{form}} (C{int}).
@raise ValueError: Invalid B{C{form}} or B{C{prec}} or B{C{prec}} outside the valid range C{-/+9}. ''' except KeyError: raise _ValueError(form=form)
'''Convert I{signed} C{degrees} to string, without suffix.
@arg deg: Degrees to be formatted (C{scalar degrees}). @kwarg form: Format specifier for B{C{deg}} (C{str} or L{F_D}, L{F_DM}, L{F_DMS}, L{F_DEG}, L{F_MIN}, L{F_SEC}, L{F_D60}, L{F__E}, L{F__F}, L{F__G}, L{F_RAD}, L{F_D_}, L{F_DM_}, L{F_DMS_}, L{F_DEG_}, L{F_MIN_}, L{F_SEC_}, L{F_D60_}, L{F__E_}, L{F__F_}, L{F__G_}, L{F_RAD_}, L{F_D__}, L{F_DM__}, L{F_DMS__}, L{F_DEG__}, L{F_MIN__}, L{F_SEC__}, L{F_D60__}, L{F__E__}, L{F__F__}, L{F__G__} or L{F_RAD__}). @kwarg prec: Number of decimal digits (0..9 or C{None} for default). Trailing zero decimals are stripped for B{C{prec}} values of 1 and above, but kept for negative B{C{prec}}. @kwarg sep: Separator between degrees, minutes, seconds, suffix (C{str}). @kwarg ddd: Number of digits for B{C{deg}°} (2 or 3). @kwarg neg: Prefix for negative B{C{deg}} (C{'-'}). @kwarg pos: Prefix for positive B{C{deg}} and signed B{C{form}} (C{'+'}). @kwarg s_D_M_S: Optional keyword arguments C{B{s_D}=str}, C{B{s_M}=str} C{B{s_S}=str} and C{B{s_DMS}=True} to override any or cancel all DMS symbols, defaults L{S_DEG}, L{S_MIN} respectively L{S_SEC}. See B{Notes} below.
@return: Degrees in the specified form (C{str}).
@note: The degrees, minutes and seconds (DMS) symbol can be overridden in this and other C{*DMS} functions by using optional keyword argments C{B{s_D}="d"}, C{B{s_M}="'"} respectively C{B{s_S}='"'}. Using keyword argument B{C{s_DMS}=None} cancels all C{DMS} symbols to C{B{S_NUL}=NN}.
@note: Sexagecimal format B{C{F_D60}} supports overridable pseudo-DMS symbols positioned at C{"[D]DD<B{s_D}>MM<B{s_M}>SS<B{s_S}>"} with defaults C{B{s_D}="."}, C{B{s_M}=B{sep}} and C{B{s_S}=}L{pygeodesy.NN}.
@note: Formats B{C{F__E}}, B{C{F__F}} and B{C{F__G}} can be extended with a C{D}-only symbol if defined with keyword argument C{B{s_D}=str}. Likewise for B{C{F_RAD}} formats with keyword argument C{B{s_R}=str}.
@see: Function L{pygeodesy.degDMS} '''
# **) MIT License # # Copyright (C) 2016-2022 -- mrJean1 at Gmail -- All Rights Reserved. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. |