Exemple #1
0
def _to3zBll(lat, lon, cmoff=True):
    '''(INTERNAL) Return zone, Band and lat- and (central) longitude in degrees.

       @param lat: Latitude (C{degrees}).
       @param lon: Longitude (C{degrees}).
       @keyword cmoff: Offset I{lon} from zone's central meridian.

       @return: 4-Tuple (zone, Band, lat, lon).
    '''
    z, lat, lon = _to3zll(lat, lon)  # in .ellipsoidalBase

    if _UTM_LAT_MIN > lat or lat >= _UTM_LAT_MAX:  # [-80, 84)
        x = '%s [%s, %s)' % ('range', _UTM_LAT_MIN, _UTM_LAT_MAX)
        raise RangeError('%s outside UTM %s: %s' % ('lat', x, degDMS(lat)))
    B = _Bands[int(lat + 80) >> 3]

    x = lon - _cmlon(z)  # z before Norway/Svaldbard
    if abs(x) > _UTM_ZONE_OFF_MAX:
        x = '%s %d by %s' % ('zone', z, degDMS(x, prec=6))
        raise RangeError('%s outside UTM %s: %s' % ('lon', x, degDMS(lon)))

    if B == 'X':  # and 0 <= int(lon) < 42: z = int(lon + 183) // 6 + 1
        x = {32: 9, 34: 21, 36: 33}.get(z, None)
        if x:  # Svalbard
            z += 1 if lon >= x else -1
    elif B == 'V' and z == 31 and lon >= 3:
        z += 1  # SouthWestern Norway

    if cmoff:  # lon off central meridian
        lon -= _cmlon(z)  # z after Norway/Svaldbard
    return z, B, lat, lon
Exemple #2
0
    def __init__(self, zone, hemisphere, easting, northing, band='',
                             datum=Datums.WGS84, convergence=None,
                             scale=None, name=''):
        '''New UTM coordinate.

           @param zone: UTM 6° longitudinal zone (C{int}, 1..60 covering
                        180°W..180°E) or '00B' (C{str}) zone and band letter.
           @param hemisphere: N for the northern or S for the southern
                              hemisphere (C{str}).
           @param easting: Easting from false easting (C{meter}), -500km
                           from central meridian.
           @param northing: Northing from equator (C{meter}), N or from
                            false northing -10,000km S.
           @keyword band: Optional, latitudinal band (string, C..X).
           @keyword datum: Optional, this coordinate's datum (L{Datum}).
           @keyword convergence: Optional meridian convergence, bearing
                                 of grid North, clockwise from true
                                 North (C{degrees} or C{None}).
           @keyword scale: Optional grid scale factor (C{scalar} or C{None}).
           @keyword name: Optional name (C{str}).

           @raise RangeError: If I{easting} or I{northing} is outside
                              the valid UTM range.

           @raise UTMError: Invalid I{band}, I{hemishere} or I{zone}.

           @example:

           >>> import pygeodesy
           >>> u = pygeodesy.Utm(31, 'N', 448251, 5411932)
        '''
        if name:
            self.name = name

        self._zone, B, _ = _toZBlat3(zone, band)

        h = str(hemisphere)[:1].upper()
        if not h or h not in ('N', 'S'):
            raise UTMError('%s invalid: %r' % ('hemisphere', hemisphere))

        e, n = float(easting), float(northing)
        # check easting/northing (with 40km overlap
        # between zones) - is this worthwhile?
        if 120e3 > e or e > 880e3:
            raise RangeError('%s invalid: %r' % ('easting', easting))
        if 0 > n or n > _FalseNorthing:
            raise RangeError('%s invalid: %r' % ('northing', northing))

        self._hemi        = h
        self._easting     = e
        self._northing    = n
        self._band        = B
        self._datum       = datum
        self._convergence = convergence
        self._scale       = scale
Exemple #3
0
def _toZBab4(lat, lon, cmoff=True):
    '''(INTERNAL) Return zone, Band and central lat- and longitude in radians.

       @param lat: Latitude (C{degrees}).
       @param lon: Longitude (C{degrees}).
       @keyword cmoff: Offset i{lon} from zone's central meridian.

       @return: 4-Tuple (zone, Band, a, b).
    '''
    # return zone, Band and lat- and medidian (in C{radians})
    lat = wrap90(lat)
    if -80 > lat or lat > 84:
        raise RangeError('%s outside UTM: %s' % ('lat', lat))
    B = _Bands[int(lat + 80) >> 3]

    lon = wrap180(lon)
    z = int((lon + 180) / 6) + 1  # longitudinal zone
    if B == 'X':
        x = {32: 9, 34: 21, 36: 33}.get(z, None)
        if x:  # Svalbard
            z += 1 if lon >= x else -1
    elif B == 'V' and z == 31 and lon >= 3:
        z += 1  # southern Norway

    a = radians(lat)  # lat off equator
    if cmoff:  # lon off central meridian
        lon -= _cmlon(z)
    return z, B, a, radians(lon)
Exemple #4
0
def upsZoneBand5(lat, lon, strict=True):
    '''Return the UTM/UPS zone number, (polar) Band letter, pole and
       clipped lat- and longitude for a given location.

       @param lat: Latitude in degrees (C{scalar} or C{str}).
       @param lon: Longitude in degrees (C{scalar} or C{str}).
       @keyword strict: Restrict I{lat} to UPS ranges (C{bool}).

       @return: 5-Tuple (C{zone, Band, hemisphere, lat, lon}) as
                (C{int, str, 'N'|'S', degrees90, degrees180}) where
                C{zone} is always C{0} for UPS and polar C{Band} is
                C{""} or C{'A'|'B'|'Y'|'Z'}.

       @raise RangeError: If I{strict} and I{lat} in UTM and not UPS
                          range or if I{lat} or I{lon} outside the valid
                          range and I{rangerrrors} set to C{True}.

       @raise ValueError: Invalid I{lat} or I{lon}.
    '''
    z, lat, lon = _to3zll(*parseDMS2(lat, lon))
    if lat < _UPS_LAT_MIN:  # includes 30' overlap
        return _UPS_ZONE, _Band(lat, lon), 'S', lat, lon

    elif lat > _UPS_LAT_MAX:  # includes 30' overlap
        return _UPS_ZONE, _Band(lat, lon), 'N', lat, lon

    elif strict:
        x = '%s [%s, %s]' % ('range', _UPS_LAT_MIN, _UPS_LAT_MAX)
        raise RangeError('%s inside UTM %s: %s' % ('lat', x, degDMS(lat)))

    return z, '', _hemi(lat), lat, lon
Exemple #5
0
def upsZoneBand5(lat, lon, strict=True):
    '''Return the UTM/UPS zone number, (polar) Band letter, pole and
       clipped lat- and longitude for a given location.

       @param lat: Latitude in degrees (C{scalar} or C{str}).
       @param lon: Longitude in degrees (C{scalar} or C{str}).
       @keyword strict: Restrict B{C{lat}} to UPS ranges (C{bool}).

       @return: A L{UtmUpsLatLon5Tuple}C{(zone, band, hemipole,
                lat, lon)} where C{hemipole} is the C{'N'|'S'} pole,
                the UPS projection top/center.

       @raise RangeError: If B{C{strict}} and B{C{lat}} in the UTM
                          and not the UPS range or if B{C{lat}} or
                          B{C{lon}} outside the valid range and
                          L{rangerrors} set to C{True}.

       @raise ValueError: Invalid B{C{lat}} or B{C{lon}}.
    '''
    z, lat, lon = _to3zll(*parseDMS2(lat, lon))
    if lat < _UPS_LAT_MIN:  # includes 30' overlap
        z, B, p = _UPS_ZONE, _Band(lat, lon), 'S'

    elif lat > _UPS_LAT_MAX:  # includes 30' overlap
        z, B, p = _UPS_ZONE, _Band(lat, lon), 'N'

    elif strict:
        x = '%s [%s, %s]' % ('range', _UPS_LAT_MIN, _UPS_LAT_MAX)
        raise RangeError('%s inside UTM %s: %s' % ('lat', x, degDMS(lat)))

    else:
        B, p = '', _hemi(lat)
    return UtmUpsLatLon5Tuple(z, B, p, lat, lon)
Exemple #6
0
    def __init__(
            self,
            zone,
            hemisphere,
            easting,
            northing,
            band='',  # PYCHOK expected
            datum=Datums.WGS84,
            falsed=True,
            convergence=None,
            scale=None,
            name=''):
        '''New UTM coordinate.

           @param zone: Longitudinal UTM zone (C{int}, 1..60) or zone
                        with/-out (latitudinal) Band letter (C{str},
                        '01C'..'60X').
           @param hemisphere: Northern or southern hemisphere (C{str},
                              C{'N[orth]'} or C{'S[outh]'}).
           @param easting: Easting from false easting (C{meter}, -500km
                           from central meridian).
           @param northing: Northing from equator (C{meter}, N or from
                            false northing -10,000km S).
           @keyword band: Optional, (latitudinal) band (C{str}, 'C'..'X').
           @keyword datum: Optional, this coordinate's datum (L{Datum}).
           @keyword falsed: Both I{easting} and I{northing} are falsed (C{str}).
           @keyword convergence: Optional meridian convergence, bearing
                                 off grid North, clockwise from true
                                 North (C{degrees}) or C{None}.
           @keyword scale: Optional grid scale factor (C{scalar}) or C{None}.
           @keyword name: Optional name (C{str}).

           @raise RangeError: If I{easting} or I{northing} outside the
                              valid UTM range.

           @raise UTMError: Invalid I{zone}, I{hemishere} or I{band}.

           @example:

           >>> import pygeodesy
           >>> u = pygeodesy.Utm(31, 'N', 448251, 5411932)
        '''
        if name:
            self.name = name

        self._zone, B, _ = _to3zBlat(zone, band)

        h = str(hemisphere)[:1].upper()
        if h not in ('N', 'S'):
            raise UTMError('%s invalid: %r' % ('hemisphere', hemisphere))

        e, n = float(easting), float(northing)
        if not falsed:
            e += _FalseEasting  # relative to central meridian
            if h == 'S':  # relative to equator
                n += _FalseNorthing
        # check easting/northing (with 40km overlap
        # between zones) - is this worthwhile?
        if 120e3 > e or e > 880e3:
            raise RangeError('%s invalid: %r' % ('easting', easting))
        if 0 > n or n > _FalseNorthing:
            raise RangeError('%s invalid: %r' % ('northing', northing))

        self._band = B
        self._convergence = convergence
        self._datum = datum
        self._easting = e
        self._hemisphere = h
        self._northing = n
        self._scale = scale