kopia lustrzana https://github.com/ctjacobs/pyqso
Added a new Maidenhead class for plotting grid squares on the world map. Work in progress. Addresses issue #59.
rodzic
f222d5cc30
commit
0a4b3da902
|
@ -19,6 +19,7 @@
|
|||
|
||||
from gi.repository import GObject
|
||||
import logging
|
||||
import re
|
||||
from os.path import expanduser
|
||||
from datetime import datetime
|
||||
try:
|
||||
|
@ -33,6 +34,7 @@ try:
|
|||
import cartopy
|
||||
logging.info("Using version %s of cartopy." % (cartopy.__version__))
|
||||
from matplotlib.backends.backend_gtk3cairo import FigureCanvasGTK3Cairo as FigureCanvas
|
||||
from matplotlib.backends.backend_gtk3 import NavigationToolbar2GTK3
|
||||
have_necessary_modules = True
|
||||
except ImportError as e:
|
||||
logging.warning(e)
|
||||
|
@ -46,6 +48,10 @@ except ImportError:
|
|||
have_geocoder = False
|
||||
|
||||
|
||||
class NavigationToolbar(NavigationToolbar2GTK3):
|
||||
toolitems = [t for t in NavigationToolbar2GTK3.toolitems if t[0] in ("Home", "Zoom", "Save")]
|
||||
|
||||
|
||||
class Point:
|
||||
""" A point on the grey line map. """
|
||||
def __init__(self, name, latitude, longitude, style="yo"):
|
||||
|
@ -64,6 +70,66 @@ class Point:
|
|||
return
|
||||
|
||||
|
||||
class Maidenhead:
|
||||
|
||||
""" The Maidenhead Locator System. """
|
||||
|
||||
def __init__(self):
|
||||
self.upper = "ABCDEFGHIJKLMNOPQR"
|
||||
self.lower = "abcdefghijklmnopqrstuvwx"
|
||||
return
|
||||
|
||||
def ll2gs(self, latitude, longitude):
|
||||
""" Convert latitude-longitude coordinates to a Maidenhead grid square locator.
|
||||
This is based on the code by Walter Underwood, K6WRU (https://ham.stackexchange.com/questions/221/how-can-one-convert-from-lat-long-to-grid-square).
|
||||
|
||||
:arg float latitude: The latitude.
|
||||
:arg float longitude: The longitude.
|
||||
:rtype: str
|
||||
:returns: The Maidenhead grid square locator.
|
||||
"""
|
||||
|
||||
adjusted_latitude = latitude + 90
|
||||
adjusted_longitude = longitude + 180
|
||||
field_latitude = self.upper[int(adjusted_latitude/10)]
|
||||
field_longitude = self.upper[int(adjusted_longitude/20)]
|
||||
square_latitude = int(adjusted_latitude % 10)
|
||||
square_longitude = int((adjusted_longitude/2) % 10)
|
||||
|
||||
return ("%s"*4) % (field_longitude, field_latitude, square_longitude, square_latitude)
|
||||
|
||||
def gs2ll(self, grid_square):
|
||||
""" Convert a Maidenhead grid square locator to latitude-longitude coordinates.
|
||||
This is based on the gridSquareToLatLon function in HamGridSquare.js by Paul Brewer, KI6CQ (https://gist.github.com/DrPaulBrewer/4279e9d234a1bd6dd3c0), released under the MIT license.
|
||||
|
||||
:arg str grid_square: The Maidenhead grid square locator.
|
||||
:rtype: tuple
|
||||
:returns: The latitude-longitude coordinates in a tuple.
|
||||
"""
|
||||
|
||||
m = re.match(r"^[A-X][A-X][0-9][0-9]$", grid_square)
|
||||
if(m):
|
||||
gs = m.group(0)
|
||||
latitude = self.latitude4(gs)+0.5
|
||||
longitude = self.longitude4(gs)+1.0
|
||||
else:
|
||||
m = re.match(r"^[A-X][A-X][0-9][0-9][a-x][a-x]$", grid_square)
|
||||
if(m):
|
||||
gs = m.group(0)
|
||||
latitude = self.latitude4(gs) + (1.0/60.0)*2.5*(ord(gs[5])-ord("a")+0.5)
|
||||
longitude = self.longitude4(gs) + (1.0/60.0)*5*(ord(gs[4])-ord("a")+0.5)
|
||||
else:
|
||||
raise ValueError("Unable to parse grid square string.")
|
||||
|
||||
return (latitude, longitude)
|
||||
|
||||
def latitude4(self, g):
|
||||
return 10*(ord(g[1]) - ord("A")) + int(g[3])-90
|
||||
|
||||
def longitude4(self, g):
|
||||
return 20*(ord(g[0]) - ord("A")) + 2*int(g[2])-180
|
||||
|
||||
|
||||
class WorldMap:
|
||||
|
||||
""" A tool for visualising the world map. """
|
||||
|
@ -83,6 +149,8 @@ class WorldMap:
|
|||
self.fig = matplotlib.figure.Figure()
|
||||
self.canvas = FigureCanvas(self.fig) # For embedding in the Gtk application
|
||||
self.builder.get_object("worldmap").pack_start(self.canvas, True, True, 0)
|
||||
toolbar = NavigationToolbar(self.canvas, self.application.window)
|
||||
self.builder.get_object("worldmap").pack_start(toolbar, False, False, 0)
|
||||
self.refresh_event = GObject.timeout_add(1800000, self.draw) # Re-draw the world map automatically after 30 minutes (if the world map tool is visible).
|
||||
|
||||
# Add the QTH coordinates for plotting, if available.
|
||||
|
@ -99,6 +167,9 @@ class WorldMap:
|
|||
except ValueError:
|
||||
logging.warning("Unable to get the QTH name, latitude and/or longitude. The QTH will not be pinpointed on the world map. Check preferences?")
|
||||
|
||||
self.maidenhead = Maidenhead()
|
||||
self.grid_square_count = numpy.zeros((len(self.maidenhead.upper), len(self.maidenhead.upper)), dtype=bool)
|
||||
|
||||
self.builder.get_object("worldmap").show_all()
|
||||
|
||||
logging.debug("World map ready!")
|
||||
|
@ -212,6 +283,21 @@ class WorldMap:
|
|||
ax.plot(p.longitude, p.latitude, p.style, transform=cartopy.crs.PlateCarree())
|
||||
ax.text(p.longitude+0.02*p.longitude, p.latitude+0.02*p.latitude, p.name, color="white", size="small", weight="bold")
|
||||
|
||||
# Draw Maidenhead grid squares.
|
||||
xx = numpy.linspace(-180, 180, len(list(self.maidenhead.upper))+1)
|
||||
yy = numpy.linspace(-90, 90, len(list(self.maidenhead.upper))+1)
|
||||
A = self.grid_square_count.copy()
|
||||
A[10, 10] = True
|
||||
A[12, 12] = True
|
||||
A[10, 5] = True
|
||||
A[9, 5] = True
|
||||
z = numpy.ma.masked_array(A, A == 0)
|
||||
ax.pcolormesh(xx, yy, z, transform=cartopy.crs.PlateCarree(), cmap='Purples', vmin=0, vmax=1, edgecolors="k", linewidth=2, alpha=0.6)
|
||||
for i in range(len(self.maidenhead.upper)):
|
||||
for j in range(len(self.maidenhead.upper)):
|
||||
text = self.maidenhead.upper[i]+self.maidenhead.upper[j]
|
||||
ax.text((xx[i]+xx[i+1])/2.0, (yy[j]+yy[j+1])/2.0, text, ha="center", va="center", size=8, color="w")
|
||||
|
||||
return True
|
||||
else:
|
||||
return False # Don't try to re-draw the canvas if the necessary modules to do so could not be imported.
|
||||
|
|
Ładowanie…
Reference in New Issue