예제 #1
0
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
예제 #2
0
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)