Example #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
Example #2
0
    def toStr(self, prec=0, sep=' ', B=False, cs=False):  # PYCHOK expected
        '''Return a string representation of this UTM coordinate.

           To distinguish from MGRS grid zone designators, a
           space is left between the zone and the hemisphere.

           Note that UTM coordinates are rounded, not truncated
           (unlike MGRS grid references).

           @keyword prec: Optional number of decimals, unstripped (C{int}).
           @keyword sep: Optional separator to join (C{str}).
           @keyword B: Optionally, include latitudinal band (C{bool}).
           @keyword cs: Optionally, include meridian convergence and
                        grid scale factor (C{bool}).

           @return: This UTM as a string with I{zone[band], hemisphere,
                    easting, northing, [convergence, scale]} in
                    C{"00 N|S meter meter"} plus C{" degrees float"} if
                    I{cs} is C{True} (C{str}).

           @example:

           >>> u = Utm(3, 'N', 448251, 5411932.0001)
           >>> u.toStr(4)  # 03 N 448251.0 5411932.0001
           >>> u.toStr(sep=', ')  # 03 N, 448251, 5411932
        '''
        z = '%02d%s' % (self.zone, self.band if B else '')
        t = (z, self.hemisphere, fStr(self.easting,
                                      prec=prec), fStr(self.northing,
                                                       prec=prec))
        if cs:
            t += ('n/a' if self.convergence is None else degDMS(
                self.convergence, prec=8, pos='+'),
                  'n/a' if self.scale is None else fStr(self.scale, prec=8))
        return sep.join(t)
Example #3
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
Example #4
0
    def toStr(self, prec=0, sep=' ', B=False, cs=False):  # PYCHOK expected
        '''Return a string representation of this UPS coordinate.

           Note that UPS coordinates are rounded, not truncated
           (unlike MGRS grid references).

           @keyword prec: Optional number of decimals, unstripped (C{int}).
           @keyword sep: Optional separator to join (C{str}).
           @keyword B: Optionally, include and polar band letter (C{bool}).
           @keyword cs: Optionally, include gamma meridian convergence
                        and point scale factor (C{bool}).

           @return: This UPS as a string with I{00[Band] pole, easting,
                    northing, [convergence, scale]} as C{"00[B] N|S
                    meter meter"} plus C{" DMS float"} if I{cs} is C{True},
                    where C{[Band]} is present and C{'A'|'B'|'Y'|'Z'} only
                    if I{B} is C{True} and convergence C{DMS} is in
                    I{either} degrees, minutes I{or} seconds (C{str}).

           @note: Zone zero (C{"00"}) for UPS follows Karney's U{zone UPS
                  <http://GeographicLib.SourceForge.io/html/classGeographicLib_1_1UTMUPS.html>}.
        '''
        z = _UPS_ZONE_STR + (self.band if B else '')
        t = (z, self.pole, fStr(self.easting,  prec=prec),
                           fStr(self.northing, prec=prec))
        if cs:
            t += ('n/a' if self.convergence is None else
                    degDMS(self.convergence, prec=8, pos='+'),
                  'n/a' if self.scale is None else
                      fStr(self.scale, prec=8))
        return sep.join(t)
Example #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)
Example #6
0
 def _toStr4_6(self, hemipole, B, cs, prec, sep):
     '''(INTERNAL) Return a string representation of this UTM/UPS coordinate.
     '''
     z = '%02d%s' % (self.zone, (self.band if B else ''))  # PYCHOK band
     t = (z, hemipole, fStr(self.easting,
                            prec=prec), fStr(self.northing, prec=prec))
     if cs:
         t += ('n/a' if self.convergence is None else degDMS(
             self.convergence, prec=8, pos='+'),
               'n/a' if self.scale is None else fStr(self.scale, prec=8))
     return sep.join(t)