mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2025-10-27 08:49:27 +00:00
Infer location from WAB/WAI grid. Closes #62
This commit is contained in:
@@ -25,7 +25,7 @@ SIGS = [
|
||||
SIG(name="WCA", description="World Castles Award", icon="chess-rook", ref_regex=r"[A-Z0-9]{1,3}\-\d+"),
|
||||
SIG(name="ZLOTA", description="New Zealand on the Air", icon="kiwi-bird", ref_regex=r"ZL[A-Z]/[A-Z]{2}\-\d+"),
|
||||
SIG(name="KRMNPA", description="Keith Roget Memorial National Parks Award", icon="earth-oceania", ref_regex=r""),
|
||||
SIG(name="WAB", description="Worked All Britain", icon="table-cells-large", ref_regex=r"[A-Z]{2}[0-9]{2}"),
|
||||
SIG(name="WAB", description="Worked All Britain", icon="table-cells-large", ref_regex=r"[A-Z]{1,2}[0-9]{2}"),
|
||||
SIG(name="WAI", description="Worked All Ireland", icon="table-cells-large", ref_regex=r"[A-Z][0-9]{2}")
|
||||
]
|
||||
|
||||
|
||||
103
core/geo_utils.py
Normal file
103
core/geo_utils.py
Normal file
@@ -0,0 +1,103 @@
|
||||
import logging
|
||||
import re
|
||||
from math import floor
|
||||
|
||||
from pyproj import Transformer
|
||||
|
||||
TRANSFORMER_OS_GRID_TO_WGS84 = Transformer.from_crs("EPSG:27700", "EPSG:4326")
|
||||
TRANSFORMER_IRISH_GRID_TO_WGS84 = Transformer.from_crs("EPSG:29903", "EPSG:4326")
|
||||
TRANSFORMER_CI_UTM_GRID_TO_WGS84 = Transformer.from_crs("+proj=utm +zone=30 +ellps=WGS84", "EPSG:4326")
|
||||
|
||||
|
||||
# Convert a Worked All Britain or Worked All Ireland reference to a lat/lon point.
|
||||
def wab_wai_square_to_lat_lon(ref):
|
||||
# First check we have a valid grid square, and based on what it looks like, use either the Ordnance Survey, Irish,
|
||||
# or UTM grid systems to perform the conversion.
|
||||
if re.match(r"^[HNOST][ABCDEFGHJKLMNOPQRSTUVWXYZ][0-9]{2}$", ref):
|
||||
return os_grid_square_to_lat_lon(ref)
|
||||
elif re.match(r"^[ABCDEFGHJKLMNOPQRSTUVWXYZ][0-9]{2}$", ref):
|
||||
return irish_grid_square_to_lat_lon(ref)
|
||||
elif re.match(r"^W[AV][0-9]{2}$", ref):
|
||||
return utm_grid_square_to_lat_lon(ref)
|
||||
else:
|
||||
logging.warn("Invalid WAB/WAI square: " + ref)
|
||||
return None
|
||||
|
||||
|
||||
# Get a lat/lon point for the centre of an Ordnance Survey grid square
|
||||
def os_grid_square_to_lat_lon(ref):
|
||||
# Convert the letters into multipliers for the 500km squares and 100km squares
|
||||
offset_500km_multiplier = ord(ref[0]) - 65
|
||||
offset_100km_multiplier = ord(ref[1]) - 65
|
||||
|
||||
# The letter "I" is not used in the grid, so any offset of 8 or more needs to be reduced by 1.
|
||||
if offset_500km_multiplier >= 8:
|
||||
offset_500km_multiplier = offset_500km_multiplier - 1
|
||||
if offset_100km_multiplier >= 8:
|
||||
offset_100km_multiplier = offset_100km_multiplier - 1
|
||||
|
||||
# Convert the offsets into increments of 100km from the false origin (grid square SV):
|
||||
easting_100km = ((offset_500km_multiplier - 2) % 5) * 5 + (offset_100km_multiplier % 5)
|
||||
northing_100km = (19 - floor(offset_500km_multiplier / 5) * 5) - floor(offset_100km_multiplier / 5)
|
||||
|
||||
# Take the numeric parts of the grid square and multiply by 10000 to get metres, then combine with the 100km
|
||||
# box offsets
|
||||
easting = int(ref[2]) * 10000 + easting_100km * 100000
|
||||
northing = int(ref[3]) * 10000 + northing_100km * 100000
|
||||
|
||||
# Add 5000m to each value to get the middle of the box rather than the south-west corner
|
||||
easting = easting + 5000
|
||||
northing = northing + 5000
|
||||
|
||||
# Reproject to WGS84 lat/lon
|
||||
lat, lon = TRANSFORMER_OS_GRID_TO_WGS84.transform(easting, northing)
|
||||
return lat, lon
|
||||
|
||||
|
||||
# Get a lat/lon point for the centre of an Irish Grid square.
|
||||
def irish_grid_square_to_lat_lon(ref):
|
||||
# Convert the letters into multipliers for the 100km squares
|
||||
offset_100km_multiplier = ord(ref[0]) - 65
|
||||
|
||||
# The letter "I" is not used in the grid, so any offset of 8 or more needs to be reduced by 1.
|
||||
if offset_100km_multiplier >= 8:
|
||||
offset_100km_multiplier = offset_100km_multiplier - 1
|
||||
|
||||
# Convert the offsets into increments of 100km from the false origin:
|
||||
easting_100km = offset_100km_multiplier % 5
|
||||
northing_100km = 4 - floor(offset_100km_multiplier / 5)
|
||||
|
||||
# Take the numeric parts of the grid square and multiply by 10000 to get metres, then combine with the 100km
|
||||
# box offsets
|
||||
easting = int(ref[1]) * 10000 + easting_100km * 100000
|
||||
northing = int(ref[2]) * 10000 + northing_100km * 100000
|
||||
|
||||
# Add 5000m to each value to get the middle of the box rather than the south-west corner
|
||||
easting = easting + 5000
|
||||
northing = northing + 5000
|
||||
|
||||
# Reproject to WGS84 lat/lon
|
||||
lat, lon = TRANSFORMER_IRISH_GRID_TO_WGS84.transform(easting, northing)
|
||||
return lat, lon
|
||||
|
||||
|
||||
# Get a lat/lon point for the centre of a UTM grid square (supports only squares WA & WV for the Channel Islands, nothing else implemented)
|
||||
def utm_grid_square_to_lat_lon(ref):
|
||||
# Take the numeric parts of the grid square and multiply by 10000 to get metres from the corner of the letter-based grid square
|
||||
easting = int(ref[2]) * 10000
|
||||
northing = int(ref[3]) * 10000
|
||||
|
||||
# Apply the appropriate offset based on whether the square is WA or WV
|
||||
easting = easting + 500000
|
||||
if ref[1] == "A":
|
||||
northing = northing + 5500000
|
||||
else:
|
||||
northing = northing + 5400000
|
||||
|
||||
# Add 5000m to each value to get the middle of the box rather than the south-west corner
|
||||
easting = easting + 5000
|
||||
northing = northing + 5000
|
||||
|
||||
# Reproject to WGS84 lat/lon
|
||||
lat, lon = TRANSFORMER_CI_UTM_GRID_TO_WGS84.transform(easting, northing)
|
||||
return lat, lon
|
||||
Reference in New Issue
Block a user