"""
Bearing main module. Runs the user interface to allow entering the bearing
and azimuth values
"""
import PySimpleGUI as sg
from bearing.angle import Bearing
import pyperclip
import math
import webbrowser
DEGREE = u"\N{DEGREE SIGN}"
SIZE_X = 200
SIZE_Y = 200
NUMBER_MARKER_FREQUENCY = 25
[docs]class UI:
"""
The UI class defines the user interface dialog using PySimpleGUI. It
allows entering the bearing and azimuth values and performs the conversions
as text is entered into the form fields.
"""
def __init__(self):
"""
Run the user interface using PySimpleGUI
"""
# Theme must be defined before layout
# Reddit, SandyBeach, LightBrown1, SystemDefaultForReal, LightBrown12
sg.theme("SystemDefaultForReal")
self.canvas = sg.Graph(
canvas_size=[SIZE_X * 2, SIZE_Y * 2],
graph_top_right=[100, 100],
graph_bottom_left=[-100, -100],
key="graph",
)
layout = [
[sg.Text("Bearing:")],
[
sg.Spin(
values=["S", "N"],
initial_value="N",
key="northing",
enable_events=True,
),
sg.Input("00", size=(2, 1), key="degree", enable_events=True,),
sg.Text(DEGREE, size=(1, 1)),
sg.Input("00", size=(2, 1), key="minute", enable_events=True,),
sg.Text("'", size=(1, 1)),
sg.Input("00", size=(2, 1), key="second", enable_events=True,),
sg.Text('"', size=(1, 1)),
sg.Spin(
values=["W", "E"],
initial_value="E",
key="easting",
enable_events=True,
),
],
[sg.Text("Azimuth:")],
[sg.Input("0.0", size=(15, 2), key="azimuth", enable_events=True,)],
[
sg.Button("Copy Bearing", key="copy_bear"),
sg.Button("Copy Azimuth", key="copy_az"),
sg.Button("Docs", key="docs"),
sg.Button("Exit"),
],
[self.canvas],
]
window = sg.Window("Bearing - Azimuth", layout, font=("Ubuntu", 16))
self.direction = Bearing()
# Event dispatch handler
while True:
event, values = window.read()
if event in (None, "Exit"):
break
elif event in ("northing", "degree", "minute", "second", "easting"):
angle = self.direction.submit_bearing(
values["northing"],
values["degree"],
values["minute"],
values["second"],
values["easting"],
)
window["azimuth"].update(angle)
elif event == "azimuth":
bear = self.direction.submit_azimuth(values["azimuth"])
window["northing"].update(bear["northing"])
window["degree"].update(bear["degrees"])
window["minute"].update(bear["minutes"])
window["second"].update(bear["seconds"])
window["easting"].update(bear["easting"])
elif event == "copy_bear":
value = self.direction.get_bearing()
pyperclip.copy(value)
elif event == "copy_az":
value = str(self.direction.get_azimuth())
pyperclip.copy(value)
elif event == "docs":
webbrowser.open("https://bearingazimuth.readthedocs.io/en/latest/")
self.canvas.erase()
self.draw_axis()
self.draw_vector()
window.close()
[docs] def draw_axis(self):
"""
Draws the X and Y axis on the canvas for the graphical representation of
the angle on the user interface form.
"""
self.canvas.draw_line((-90, 0), (90, 0), color="blue") # axis lines
self.canvas.draw_line((0, -90), (0, 90), color="blue")
self.canvas.draw_text("E", location=(95, 0), color="blue")
self.canvas.draw_text("W", color="blue", location=(-95, 0))
self.canvas.draw_text("N", color="blue", location=(0, 95))
self.canvas.draw_text("S", color="blue", location=(0, -95))
[docs] def draw_vector(self):
"""
Draws the angle on the canvas. Adds a little arc to illustrate.
"""
angle = self.direction.get_azimuth()
radians = math.radians(angle)
x = y = 0
end_x = x + 90 * math.sin(radians)
end_y = y + 90 * math.cos(radians)
self.canvas.draw_arc(
top_left=(-50, 50),
bottom_right=(50, -50),
start_angle=90,
extent=angle * -1,
arc_color="green",
)
self.canvas.draw_line((x, y), (end_x, end_y), color="red", width=2)
if __name__ == "__main__":
UI()