""" Maidenhead locator helpers. latlon_to_subsquare(lat, lon) -> str e.g. "JO78ai" subsquare_bounds(sq) -> dict {lat_min, lon_min, lat_max, lon_max} """ def latlon_to_subsquare(lat: float, lon: float) -> str: """Convert WGS84 coordinates to 6-character Maidenhead subsquare.""" lon_n = lon + 180.0 lat_n = lat + 90.0 field_lon = int(lon_n / 20) field_lat = int(lat_n / 10) lon_n = lon_n % 20 lat_n = lat_n % 10 sq_lon = int(lon_n / 2) sq_lat = int(lat_n / 1) lon_n = (lon_n % 2) * 12 lat_n = (lat_n % 1) * 24 sub_lon = int(lon_n) sub_lat = int(lat_n) return ( chr(ord("A") + field_lon) + chr(ord("A") + field_lat) + str(sq_lon) + str(sq_lat) + chr(ord("a") + sub_lon) + chr(ord("a") + sub_lat) ) def subsquare_bounds(sq: str) -> dict: """ Return bounding box for a 6-character Maidenhead subsquare. Each subsquare is 5' longitude ?? 2.5' latitude (~10 ?? 4.6 km in Sweden). """ lon = (ord(sq[0]) - ord("A")) * 20.0 lat = (ord(sq[1]) - ord("A")) * 10.0 lon += int(sq[2]) * 2.0 lat += int(sq[3]) * 1.0 lon += (ord(sq[4]) - ord("a")) * (1.0 / 12.0) lat += (ord(sq[5]) - ord("a")) * (1.0 / 24.0) lon -= 180.0 lat -= 90.0 return { "lat_min": lat, "lon_min": lon, "lat_max": lat + (1.0 / 24.0), "lon_max": lon + (2.0 / 12.0), }