def parseMGRS(strMGRS, datum=Datums.WGS84, Mgrs=Mgrs): # MCCABE 13 '''Parse a string representing a MGRS grid reference, consisting of zoneBand, grid, easting and northing. @param strMGRS: MGRS grid reference (string). @keyword datum: Optional datum to use (L{Datum}). @keyword Mgrs: Optional Mgrs class to use for the MGRS grid reference (L{Mgrs}) or None. @return: The MGRS grid reference (L{Mgrs}) or 4-tuple (zone, ENdigraph, easting, northing) if I{Mgrs} is None. @raise ValueError: Invalid I{strMGRS}. @example: >>> m = parseMGRS('31U DQ 48251 11932') >>> str(m) # 31U DQ 48251 11932 >>> m = parseMGRS('31UDQ4825111932') >>> repr(m) # [Z:31U, G:DQ, E:48251, N:11932] ''' def _mg(cre, s): # return re.match groups m = cre.match(s) if not m: raise ValueError return m.groups() def _s2m(g): # e or n string to meter f = float(g) if f > 0: x = int(log10(f)) if 0 <= x < 4: # at least 5 digits f *= (10000, 1000, 100, 10)[x] return f m = tuple(strMGRS.strip().replace(',', ' ').split()) try: if len(m) == 1: # 01ABC1234512345' m = _mg(_MGRSre, m[0]) m = m[:2] + halfs(m[2]) elif len(m) == 2: # 01ABC 1234512345' m = _mg(_GZDre, m[0]) + halfs(m[1]) elif len(m) == 3: # 01ABC 12345 12345' m = _mg(_GZDre, m[0]) + m[1:] if len(m) != 4: # 01A BC 1234 12345 raise ValueError e, n = map(_s2m, m[2:]) except ValueError: raise ValueError('%s invalid: %r' % ('strMGRS', strMGRS)) if Mgrs is None: m = m[0], m[1].upper(), e, n else: m = Mgrs(m[0], m[1].upper(), e, n, datum=datum) return m
def parseOSGR(strOSGR, Osgr=Osgr): '''Parse an OSGR coordinate string to an Osgr instance. Accepts standard OS Grid References like 'SU 387 148', with or without whitespace separators, from 2- up to 10-digit references (1 m × 1 m square), or fully numeric, comma-separated references in metres, for example '438700,114800'. @param strOSGR: An OSGR coordinate (string). @keyword Osgr: Optional Osgr class to use for the OSGR coordinate (L{Osgr}) or None. @return: The OSGR coordinate (L{Osgr}) or the 2-tuple (easting, northing) if I{Osgr} is None. @raise ValueError: Invalid I{strOSGR}. @example: >>> g = parseOSGR('TG 51409 13177') >>> str(g) # TG 51409 13177 >>> g = parseOSGR('TG5140913177') >>> str(g) # TG 51409 13177 >>> g = parseOSGR('TG51409 13177') >>> str(g) # TG 51409 13177 >>> g = parseOSGR('651409,313177') >>> str(g) # TG 51409 13177 >>> g.toStr(prec=0) # 651409,313177 ''' def _c2i(G): g = ord(G.upper()) - ord('A') if g > 7: g -= 1 return g def _s2f(g): return float(g.strip()) def _s2i(G, g): g += '00000' # std to meter return int(str(G) + g[:5]) s = strOSGR.strip() try: g = s.split(',') if len(g) == 2: # "easting,northing" if len(s) < 13: raise ValueError # caught below e, n = map(_s2f, g) else: # "GR easting northing" g, s = s[:2], s[2:].strip() e, n = map(_c2i, g) n, m = divmod(n, 5) E = ((e - 2) % 5) * 5 + m N = 19 - (e // 5) * 5 - n if 0 > E or E > 6 or \ 0 > N or N > 12: raise ValueError # caught below g = s.split() if len(g) == 1: # no whitespace e, n = halfs(s) elif len(g) == 2: e, n = g else: raise ValueError # caught below e = _s2i(E, e) n = _s2i(N, n) except ValueError: raise ValueError('%s invalid: %r' % ('strOSGR', strOSGR)) return (e, n) if Osgr is None else Osgr(e, n)