Exemplo n.º 1
0
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)
Exemplo n.º 2
0
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)