Skip to content

Commit

Permalink
Generate geoJSON for QTH grid locator
Browse files Browse the repository at this point in the history
  • Loading branch information
ErofeevK committed Aug 27, 2024
1 parent ecb23ad commit be17f91
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 30 deletions.
2 changes: 1 addition & 1 deletion src/maidenhead/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
Beyond 8 characters is not defined for Maidenhead.
"""

from .to_location import to_location
from .to_location import to_location, to_location_rect, to_geoJSONObject
from .to_maiden import to_maiden


Expand Down
19 changes: 16 additions & 3 deletions src/maidenhead/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,26 @@
from copy import copy

import maidenhead
import json


def main(
loc: str | tuple[float, float],
precision: int = 6,
url: bool = False,
center: bool = False,
geojson: bool = False,
nosquare: bool = False
) -> str | tuple[float, float]:

if isinstance(loc, str): # maidenhead
maiden = copy(loc)
loc = maidenhead.to_location(loc, center)
print(f"{loc[0]:.7f} {loc[1]:.7f}")
if geojson:
obj = maidenhead.to_geoJSONObject(loc, center=center, square=not nosquare)
print(json.dumps(obj, indent=None))
else:
loc = maidenhead.to_location(loc, center)
print(f"{loc[0]:.7f} {loc[1]:.7f}")
elif len(loc) == 2: # lat lon
if isinstance(loc[0], str):
loc = (float(loc[0]), float(loc[1]))
Expand All @@ -39,18 +46,24 @@ def main(
)
p.add_argument("-p", "--precision", help="maidenhead precision", type=int, default=3)
p.add_argument("--url", help="also output Google Maps URL", action="store_true")
p.add_argument("--geojson", help="Output the geoJSON that describes given QTH lcoator", action="store_true")
p.add_argument(
"-c",
"--center",
help="output lat lon of the center of provided maidenhead grid square "
"(default output: lat lon of it's south-west corner)",
action="store_true",
)
p.add_argument(
"--nosquare",
help="Do not create square feature for geoJSON",
action="store_true",
)
args = p.parse_args()

if len(args.loc) == 1:
loc = args.loc[0]
else:
loc = args.loc

main(loc, args.precision, args.url, args.center)
main(loc, args.precision, args.url, args.center, args.geojson, args.nosquare)
93 changes: 67 additions & 26 deletions src/maidenhead/to_location.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,7 @@
import functools


def to_location(maiden: str, center: bool = False) -> tuple[float, float]:
"""
convert Maidenhead grid to latitude, longitude
Parameters
----------
maiden : str
Maidenhead grid locator of length 2 to 8
center : bool
If true, return the center of provided maidenhead grid square, instead of default south-west corner
Default value = False needed to maidenhead full backward compatibility of this module.
Returns
-------
latLon : tuple of float
Geographic latitude, longitude
"""

def to_location_rect(maiden: str) -> tuple[tuple[float, float], tuple[float, float], tuple[float, float]]:
maiden = maiden.strip().upper()
N = len(maiden)
if N < 2 or N % 2:
Expand All @@ -46,10 +26,71 @@ def convert(maiden: str) -> tuple[int, int]:
lat_nom, lat_den = convert(maiden[1::2])
lon_nom, lon_den = convert(maiden[::2])

center_offset_lat = 5 if center else 0
center_offset_lon = 10 if center else 0
center_offset_lat = 5
center_offset_lon = 10

lat = (10 * (lat_nom - 9 * lat_den) + center_offset_lat) / lat_den
lon = (20 * (lon_nom - 9 * lon_den) + center_offset_lon) / lon_den
lat_1 = (10 * (lat_nom - 9 * lat_den)) / lat_den
lon_1 = (20 * (lon_nom - 9 * lon_den)) / lon_den
lat_c = (10 * (lat_nom - 9 * lat_den) + center_offset_lat) / lat_den
lon_c = (20 * (lon_nom - 9 * lon_den) + center_offset_lon) / lon_den
lat_2 = (10 * (lat_nom - 9 * lat_den) + 2*center_offset_lat) / lat_den
lon_2 = (20 * (lon_nom - 9 * lon_den) + 2*center_offset_lon) / lon_den
return ((lat_1, lon_1), (lat_2, lon_2), (lat_c, lon_c))

return (lat, lon)

def to_location(maiden: str, center: bool = False) -> tuple[float, float]:
"""
convert Maidenhead grid to latitude, longitude
Parameters
----------
maiden : str
Maidenhead grid locator of length 2 to 8
center : bool
If true, return the center of provided maidenhead grid square, instead of default south-west corner
Default value = False needed to maidenhead full backward compatibility of this module.
Returns
-------
latLon : tuple of float
Geographic latitude, longitude
"""
bottomleft_point, (_, _), center_point = to_location_rect(maiden)

return center_point if center else bottomleft_point


def to_geoJSONObject(maiden: str, center: bool = True, square: bool = True) -> dict:
loc1, loc2, locc = to_location_rect(maiden)
center_point = {
"type": "Feature",
"properties": {"QTHLocator_Centerpoint": maiden},
"geometry": {
"type": "Point",
"coordinates": [locc[1], locc[0]]
}
}

rect = {
"type": "Feature",
"properties": {"QTHLocator": maiden},
"geometry": {
"type": "Polygon",
"coordinates": [[(loc1[1], loc1[0]), (loc1[1], loc2[0]), (loc2[1], loc2[0]), (loc2[1], loc1[0]), (loc1[1], loc1[0])]]
}
}

features: list = []
geo = {
"type": "FeatureCollection",
"features": features
}
if center:
features.append(center_point)
if square:
features.append(rect)
# geo["features"] = features
return geo

0 comments on commit be17f91

Please sign in to comment.