def check_valid_zone(zone_number, zone_letter): if not 1 <= zone_number <= 60: raise OutOfRangeError( 'zone number out of range (must be between 1 and 60)') if zone_letter: zone_letter = zone_letter.upper() if not 'C' <= zone_letter <= 'X' or zone_letter in ['I', 'O']: raise OutOfRangeError( 'zone letter out of range (must be between C and X)')
def to_latlon(easting, northing, zone_number, zone_letter=None, northern=None, strict=True): """This function convert an UTM coordinate into Latitude and Longitude Parameters ---------- easting: int Easting value of UTM coordinate northing: int Northing value of UTM coordinate zone number: int Zone Number is represented with global map numbers of an UTM Zone Numbers Map. More information see utmzones [1]_ zone_letter: str Zone Letter can be represented as string values. Where UTM Zone Designators can be accessed in [1]_ northern: bool You can set True or False to set this parameter. Default is None .. _[1]: http://www.jaworski.ca/utmzones.htm """ if not zone_letter and northern is None: raise ValueError('either zone_letter or northern needs to be set') elif zone_letter and northern is not None: raise ValueError('set either zone_letter or northern, but not both') if strict: if not in_bounds(easting, 100000, 1000000, upper_strict=True): raise OutOfRangeError( 'easting out of range (must be between 100.000 m and 999.999 m)' ) if not in_bounds(northing, 0, 10000000): raise OutOfRangeError( 'northing out of range (must be between 0 m and 10.000.000 m)') check_valid_zone(zone_number, zone_letter) if zone_letter: zone_letter = zone_letter.upper() northern = (zone_letter >= 'N') x = easting - 500000 y = northing if not northern: y -= 10000000 m = y / K0 mu = m / (R * M1) p_rad = (mu + P2 * mathlib.sin(2 * mu) + P3 * mathlib.sin(4 * mu) + P4 * mathlib.sin(6 * mu) + P5 * mathlib.sin(8 * mu)) p_sin = mathlib.sin(p_rad) p_sin2 = p_sin * p_sin p_cos = mathlib.cos(p_rad) p_tan = p_sin / p_cos p_tan2 = p_tan * p_tan p_tan4 = p_tan2 * p_tan2 ep_sin = 1 - E * p_sin2 ep_sin_sqrt = mathlib.sqrt(1 - E * p_sin2) n = R / ep_sin_sqrt r = (1 - E) / ep_sin c = _E * p_cos**2 c2 = c * c d = x / (n * K0) d2 = d * d d3 = d2 * d d4 = d3 * d d5 = d4 * d d6 = d5 * d latitude = ( p_rad - (p_tan / r) * (d2 / 2 - d4 / 24 * (5 + 3 * p_tan2 + 10 * c - 4 * c2 - 9 * E_P2)) + d6 / 720 * (61 + 90 * p_tan2 + 298 * c + 45 * p_tan4 - 252 * E_P2 - 3 * c2)) longitude = ( d - d3 / 6 * (1 + 2 * p_tan2 + c) + d5 / 120 * (5 - 2 * c + 28 * p_tan2 - 3 * c2 + 8 * E_P2 + 24 * p_tan4)) / p_cos return (mathlib.degrees(latitude), mathlib.degrees(longitude) + zone_number_to_central_longitude(zone_number))
def from_latlon(latitude, longitude, force_zone_number=None, force_zone_letter=None): """This function convert Latitude and Longitude to UTM coordinate Parameters ---------- latitude: float Latitude between 80 deg S and 84 deg N, e.g. (-80.0 to 84.0) longitude: float Longitude between 180 deg W and 180 deg E, e.g. (-180.0 to 180.0). force_zone number: int Zone Number is represented with global map numbers of an UTM Zone Numbers Map. You may force conversion including one UTM Zone Number. More information see utmzones [1]_ .. _[1]: http://www.jaworski.ca/utmzones.htm """ if not in_bounds(latitude, -80.0, 84.0): raise OutOfRangeError( 'latitude out of range (must be between 80 deg S and 84 deg N)') if not in_bounds(longitude, -180.0, 180.0): raise OutOfRangeError( 'longitude out of range (must be between 180 deg W and 180 deg E)') if force_zone_number is not None: check_valid_zone(force_zone_number, force_zone_letter) lat_rad = mathlib.radians(latitude) lat_sin = mathlib.sin(lat_rad) lat_cos = mathlib.cos(lat_rad) lat_tan = lat_sin / lat_cos lat_tan2 = lat_tan * lat_tan lat_tan4 = lat_tan2 * lat_tan2 if force_zone_number is None: zone_number = latlon_to_zone_number(latitude, longitude) else: zone_number = force_zone_number if force_zone_letter is None: zone_letter = latitude_to_zone_letter(latitude) else: zone_letter = force_zone_letter lon_rad = mathlib.radians(longitude) central_lon = zone_number_to_central_longitude(zone_number) central_lon_rad = mathlib.radians(central_lon) n = R / mathlib.sqrt(1 - E * lat_sin**2) c = E_P2 * lat_cos**2 a = lat_cos * (lon_rad - central_lon_rad) a2 = a * a a3 = a2 * a a4 = a3 * a a5 = a4 * a a6 = a5 * a m = R * (M1 * lat_rad - M2 * mathlib.sin(2 * lat_rad) + M3 * mathlib.sin(4 * lat_rad) - M4 * mathlib.sin(6 * lat_rad)) easting = K0 * n * ( a + a3 / 6 * (1 - lat_tan2 + c) + a5 / 120 * (5 - 18 * lat_tan2 + lat_tan4 + 72 * c - 58 * E_P2)) + 500000 northing = K0 * (m + n * lat_tan * (a2 / 2 + a4 / 24 * (5 - lat_tan2 + 9 * c + 4 * c**2) + a6 / 720 * (61 - 58 * lat_tan2 + lat_tan4 + 600 * c - 330 * E_P2))) if mixed_signs(latitude): raise ValueError("latitudes must all have the same sign") elif negative(latitude): northing += 10000000 return easting, northing, zone_number, zone_letter