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
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
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)
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
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)
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