def parseMGRS(strMGRS, datum=Datums.WGS84, Mgrs=Mgrs, name=''): '''Parse a string representing a MGRS grid reference, consisting of zoneBand, grid, easting and northing. @param strMGRS: MGRS grid reference (C{str}). @keyword datum: Optional datum to use (L{Datum}). @keyword Mgrs: Optional (sub-)class to return the MGRS grid reference (L{Mgrs}) or C{None}. @keyword name: Optional B{C{Mgrs}} name (C{str}). @return: The MGRS grid reference (B{L{Mgrs}}) or an L{Mgrs4Tuple}C{(zone, digraph, easting, northing)} if B{C{Mgrs}} is C{None}. @raise MGRSError: Invalid B{C{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] >>> m = mgrs.parseMGRS('42SXD0970538646') >>> str(m) # 42S XD 09705 38646 >>> m = mgrs.parseMGRS('42SXD9738') # Km >>> str(m) # 42S XD 97000 38000 ''' 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 float meter # convert to meter if less than 5 digits m = g + '00000' return float(m[:5]) m = tuple(strMGRS.strip().replace(',', ' ').split()) try: if len(m) == 1: # 01ABC1234512345' m = _mg(_MGRSre, m[0]) m = m[:2] + halfs2(m[2]) elif len(m) == 2: # 01ABC 1234512345' m = _mg(_GZDre, m[0]) + halfs2(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 (TypeError, ValueError): raise MGRSError('%s invalid: %r' % ('strMGRS', strMGRS)) z, EN = m[0], m[1].upper() r = Mgrs4Tuple(z, EN, e, n) if Mgrs is None else \ Mgrs(z, EN, e, n, datum=datum) return _xnamed(r, name)
def parseOSGR(strOSGR, Osgr=Osgr, name=''): '''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 (C{str}). @keyword Osgr: Optional (sub-)class to return the OSGR coordinate (L{Osgr}) or C{None}. @keyword name: Optional B{C{Osgr}} name (C{str}). @return: The OSGR coordinate (B{C{Osgr}}) or an L{EasNor2Tuple}C{(easting, northing)} if B{C{Osgr}} is C{None}. @raise OSGRError: Invalid B{C{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 = halfs2(s) elif len(g) == 2: e, n = g else: raise ValueError # caught below e = _s2i(E, e) n = _s2i(N, n) except ValueError: raise OSGRError('%s invalid: %r' % ('strOSGR', strOSGR)) r = EasNor2Tuple(e, n) if Osgr is None else Osgr(e, n) return _xnamed(r, name)