예제 #1
0
    def parse_map_coords_string(self, coords_string):
        split_string = coords_string.split(',')

        if "-" in split_string[0]:
            # dd mm ss.ss
            split_latlon = split_string[0].split(' ')
            lat_string = split_latlon[0].replace('N', '').replace('S', "-")
            lon_string = split_latlon[1].replace('£',
                                                 'E').replace('E', '').replace(
                                                     'W', "-")
            position = string2latlon(lat_string,
                                     lon_string,
                                     format_str="d%-%m%-%S")
        elif "°" not in split_string[0]:
            # mgrs
            mgrs_string = split_string[0].replace(" ", "")
            decoded_mgrs = mgrs.UTMtoLL(mgrs.decode(mgrs_string))
            position = LatLon(Latitude(degree=decoded_mgrs["lat"]),
                              Longitude(degree=decoded_mgrs["lon"]))
        else:
            raise ValueError(f"Invalid coordinate format: {split_string[0]}")

        elevation = split_string[1].replace(' ', '')
        if "ft" in elevation:
            elevation = int(elevation.replace("ft", ""))
        elif "m" in elevation:
            elevation = round(int(elevation.replace("m", "")) * 3.281)
        else:
            raise ValueError("Unable to parse elevation: " + elevation)

        self.captured_map_coords = str()
        self.logger.info("Parsed captured text: " + str(position))
        return position, elevation
예제 #2
0
    def run(self):
        while True:
            event, self.values = self.window.Read()
            self.logger.debug(f"Event: {event}")
            self.logger.debug(f"Values: {self.values}")

            if event is None or event == 'Exit':
                self.logger.info("Exiting...")
                break

            elif event == "Add":
                position, elevation, name = self.validate_coords()
                if position is not None:
                    self.add_waypoint(position, elevation, name)

            elif event == "Copy as string to clipboard":
                self.export_to_string()

            elif event == "Paste as string from clipboard":
                self.import_from_string()

            elif event == "Update":
                if self.values['activesList']:
                    waypoint = self.find_selected_waypoint()
                    position, elevation, name = self.validate_coords()
                    if position is not None:
                        waypoint.position = position
                        waypoint.elevation = elevation
                        waypoint.name = name
                        self.update_waypoints_list()

            elif event == "Remove":
                if self.values['activesList']:
                    self.remove_selected_waypoint()
                    self.update_waypoints_list()

            elif event == "activesList":
                if self.values['activesList']:
                    waypoint = self.find_selected_waypoint()
                    self.update_position(waypoint.position,
                                         waypoint.elevation,
                                         waypoint.name,
                                         waypoint_type=waypoint.wp_type)

            elif event == "Save profile":
                if self.profile.waypoints:
                    name = self.profile.profilename
                    if not name:
                        name = PyGUI.PopupGetText("Enter profile name",
                                                  "Saving profile")

                    if not name:
                        continue

                    self.profile.save(name)
                    self.update_profiles_list(name)

            elif event == "Delete profile":
                if not self.profile.profilename:
                    continue

                Profile.delete(self.profile.profilename)
                profiles = self.get_profile_names()
                self.window.Element("profileSelector").Update(values=[""] +
                                                              profiles)
                self.load_new_profile()
                self.update_waypoints_list()
                self.update_position()

            elif event == "profileSelector":
                try:
                    profile_name = self.values['profileSelector']
                    if profile_name != '':
                        self.profile = Profile.load(profile_name)
                    else:
                        self.profile = Profile('')
                    self.editor.set_driver(self.profile.aircraft)
                    self.update_waypoints_list()

                except DoesNotExist:
                    PyGUI.Popup("Profile not found")

            elif event == "Save as encoded file":
                filename = PyGUI.PopupGetFile("Enter file name",
                                              "Exporting profile",
                                              default_extension=".json",
                                              save_as=True,
                                              file_types=(("JSON File",
                                                           "*.json"), ))

                if filename is None:
                    continue

                with open(filename + ".json", "w+") as f:
                    f.write(str(self.profile))

            elif event == "Copy plain text to clipboard":
                profile_string = self.profile.to_readable_string()
                pyperclip.copy(profile_string)
                PyGUI.Popup("Profile copied as plain text to clipboard")

            elif event == "Load from encoded file":
                filename = PyGUI.PopupGetFile("Enter file name",
                                              "Importing profile")

                if filename is None:
                    continue

                with open(filename, "r") as f:
                    self.profile = Profile.from_string(f.read())
                self.update_waypoints_list()

                if self.profile.profilename:
                    self.update_profiles_list(self.profile.profilename)

            elif event == "capture":
                if not self.capturing:
                    self.start_quick_capture()
                else:
                    self.stop_quick_capture()

            elif event == "quick_capture":
                self.exit_quick_capture = False
                self.disable_coords_input()
                self.window.Element('capture').Update(text="Stop capturing")
                self.window.Element('quick_capture').Update(disabled=True)
                self.window.Element('capture_status').Update(
                    "Status: Capturing...")
                self.capturing = True
                self.window.Refresh()
                keyboard.add_hotkey(self.capture_key,
                                    self.add_wp_parsed_coords,
                                    timeout=1)

            elif event == "baseSelector":
                base = self.editor.default_bases.get(
                    self.values['baseSelector'])

                if base is not None:
                    self.update_position(base.position, base.elevation,
                                         base.name)

            elif event == "enter":
                self.enter_coords_to_aircraft()

            elif event in ("MSN", "WP", "HA", "FP", "ST", "DP", "IP", "HB"):
                self.select_wp_type(event)

            elif event == "elevFeet":
                self.update_altitude_elements("meters")

            elif event == "elevMeters":
                self.update_altitude_elements("feet")

            elif event in ("latDeg", "latMin", "latSec", "lonDeg", "lonMin",
                           "lonSec"):
                position, _, _ = self.validate_coords()

                if position is not None:
                    m = mgrs.encode(
                        mgrs.LLtoUTM(position.lat.decimal_degree,
                                     position.lon.decimal_degree), 5)
                    self.window.Element("mgrs").Update(m)

            elif event == "mgrs":
                mgrs_string = self.window.Element("mgrs").Get()
                if mgrs_string:
                    try:
                        decoded_mgrs = mgrs.UTMtoLL(
                            mgrs.decode(mgrs_string.replace(" ", "")))
                        position = LatLon(
                            Latitude(degree=decoded_mgrs["lat"]),
                            Longitude(degree=decoded_mgrs["lon"]))
                        self.update_position(position, update_mgrs=False)
                    except (TypeError, ValueError, UnboundLocalError) as e:
                        self.logger.error(f"Failed to decode MGRS: {e}")

            elif event in ("hornet", "tomcat", "harrier", "warthog", "mirage"):
                self.profile.aircraft = event
                self.editor.set_driver(event)
                self.update_waypoints_list()

            elif event == "filter":
                self.filter_preset_waypoints_dropdown()

        self.close()
예제 #3
0
    def parse_map_coords_string(self, coords_string, tomcat_mode=False):
        coords_string = coords_string.upper()
        # "X-00199287 Z+00523070, 0 ft"   Not sure how to convert this yet

        # "37 T FJ 36255 11628, 5300 ft"  Tessaract did not like this one because the DCS font J looks too much like )
        res = re.match("^(\d+ [a-zA-Z] [a-zA-Z][a-zA-Z] \d+ \d+), (\d+) (FT|M)$", coords_string)
        if res is not None:
            mgrs_string = res.group(1).replace(" ", "")
            decoded_mgrs = mgrs.UTMtoLL(mgrs.decode(mgrs_string))
            position = LatLon(Latitude(degree=decoded_mgrs["lat"]), Longitude(
                degree=decoded_mgrs["lon"]))
            elevation = float(res.group(2))

            if res.group(3) == "M":
                elevation = elevation * 3.281

            return position, elevation

        # "N43°10.244 E40°40.204, 477 ft"  Degrees and decimal minutes
        res = re.match("^([NS])(\d+)°([^\s]+) ([EW])(\d+)°([^,]+), (\d+) (FT|M)$", coords_string)
        if res is not None:
            lat_str = res.group(2) + " " + res.group(3) + " " + res.group(1)
            lon_str = res.group(5) + " " + res.group(6) + " " + res.group(4)
            position = string2latlon(lat_str, lon_str, "d% %M% %H")
            elevation = float(res.group(7))

            if res.group(8) == "M":
                elevation = elevation * 3.281

            return position, elevation

        # "N42-43-17.55 E40-38-21.69, 0 ft" Degrees, minutes and decimal seconds
        res = re.match("^([NS])(\d+)-(\d+)-([^\s]+) ([EW])(\d+)-(\d+)-([^,]+), (\d+) (FT|M)$", coords_string)
        if res is not None:
            lat_str = res.group(2) + " " + res.group(3) + " " + res.group(4) + " " + res.group(1)
            lon_str = res.group(6) + " " + res.group(7) + " " + res.group(8) + " " + res.group(5)
            position = string2latlon(lat_str, lon_str, "d% %m% %S% %H")
            elevation = float(res.group(9))

            if res.group(10) == "M":
                elevation = elevation * 3.281

            return position, elevation

        # "43°34'37"N 29°11'18"E, 0 ft" Degrees minutes and seconds
        res = re.match("^(\d+)°(\d+)'([^\"]+)\"([NS]) (\d+)°(\d+)'([^\"]+)\"([EW]), (\d+) (FT|M)$", coords_string)
        if res is not None:
            lat_str = res.group(1) + " " + res.group(2) + " " + res.group(3) + " " + res.group(4)
            lon_str = res.group(5) + " " + res.group(6) + " " + res.group(7) + " " + res.group(8)
            position = string2latlon(lat_str, lon_str, "d% %m% %S% %H")
            elevation = float(res.group(9))

            if res.group(10) == "M":
                elevation = elevation * 3.281

            return position, elevation

        split_string = coords_string.split(',')

        if tomcat_mode:
            latlon_string = coords_string.replace("\\", "").replace("F", "")
            split_string = latlon_string.split(' ')
            lat_string = split_string[1]
            lon_string = split_string[3]
            position = string2latlon(
                lat_string, lon_string, format_str="d%°%m%'%S")

        if not tomcat_mode:
            elevation = split_string[1].replace(' ', '')
            if "ft" in elevation:
                elevation = int(elevation.replace("ft", ""))
            elif "m" in elevation:
                elevation = round(int(elevation.replace("m", ""))*3.281)
            else:
                raise ValueError("Unable to parse elevation: " + elevation)
        else:
            elevation = self.capture_map_coords(2074, 97, 966, 32)

        self.captured_map_coords = str()
        self.logger.info("Parsed captured text: " + str(position))
        return position, elevation
예제 #4
0
    def run(self):
        while True:
            event, self.values = self.window.Read()
            self.logger.debug(f"Event: {event}")
            self.logger.debug(f"Values: {self.values}")

            if event is None or event == 'Exit':
                self.logger.info("Exiting...")
                break

            elif event == "Add":
                position, elevation, name = self.validate_coords()
                if position is not None:
                    self.add_waypoint(position, elevation, name)

            elif event == "Update":
                if self.values['activesList']:
                    waypoint = self.find_selected_waypoint()
                    position, elevation, name = self.validate_coords()
                    if position is not None:
                        waypoint.position = position
                        waypoint.elevation = elevation
                        waypoint.name = name
                        self.update_waypoints_list()

            elif event == "Remove":
                if self.values['activesList']:
                    self.remove_selected_waypoint()
                    self.update_waypoints_list()

            elif event == "activesList":
                if self.values['activesList']:
                    waypoint = self.find_selected_waypoint()
                    self.update_position(waypoint.position, waypoint.elevation,
                                         waypoint.name)

            elif event == "Save profile":
                if self.profile.waypoints:
                    name = self.profile.profilename
                    if not name:
                        name = PyGUI.PopupGetText("Enter profile name",
                                                  "Saving profile")

                    if not name:
                        continue

                    self.profile.save(name)
                    self.update_profiles_list(name)

            elif event == "Delete profile":
                if not self.profile.profilename:
                    continue

                self.profile.delete()
                profiles = self.editor.get_profile_names()
                self.window.Element("profileSelector").Update(values=[""] +
                                                              profiles)
                self.profile = self.editor.get_profile("")
                self.update_waypoints_list()
                self.update_position()

            elif event == "profileSelector":
                try:
                    self.profile = self.editor.get_profile(
                        self.values['profileSelector'])
                    self.update_waypoints_list()

                except DoesNotExist:
                    PyGUI.Popup("Profile not found")

            elif event == "Export to file":
                e = dict(waypoints=[
                    waypoint.to_dict()
                    for waypoint in self.profile.waypoints_as_list +
                    self.profile.msns_as_list
                ],
                         name=self.profile.profilename,
                         aircraft=self.profile.aircraft)

                filename = PyGUI.PopupGetFile("Enter file name",
                                              "Exporting profile",
                                              default_extension=".json",
                                              save_as=True,
                                              file_types=(("JSON File",
                                                           "*.json"), ))

                if filename is None:
                    continue

                with open(filename + ".json", "w+") as f:
                    json.dump(e, f, indent=4)

            elif event == "Import from file":
                filename = PyGUI.PopupGetFile("Enter file name",
                                              "Importing profile")

                if filename is None:
                    continue

                with open(filename, "r") as f:
                    d = json.load(f)

                self.profile = self.editor.get_profile("")
                self.profile.aircraft = d.get('aircraft', "hornet")

                waypoints = dict()
                waypoints_list = d.get('waypoints', list())
                for wp in waypoints_list:
                    wp_object = Wp(position=LatLon(Latitude(wp['latitude']),
                                                   Longitude(wp['longitude'])),
                                   name=wp.get("name", ""),
                                   elevation=wp['elevation'],
                                   sequence=wp.get("sequence", 0),
                                   wp_type=wp.get("wp_type", "WP"),
                                   station=wp.get("station", 0))

                    if wp.get("wp_type") != "MSN":
                        wp_type_list = waypoints.get(wp.get("wp_type", "WP"),
                                                     list())
                        wp_type_list.append(wp_object)
                        waypoints[wp.get("wp_type", "WP")] = wp_type_list
                    else:
                        stations = waypoints.get("MSN", dict())
                        station = stations.get(wp_object.station, list())
                        station.append(wp_object)
                        stations[wp_object.station] = station
                        waypoints["MSN"] = stations

                self.profile.waypoints = waypoints
                self.update_waypoints_list()

                if d.get("name", ""):
                    self.profile.save(d.get("name"))
                    self.update_profiles_list(d.get("name"))

            elif event == "capture":
                if not self.capturing:
                    self.disable_coords_input()
                    self.window.Element('capture').Update(
                        text="Stop capturing")
                    self.window.Element('quick_capture').Update(disabled=True)
                    self.window.Element('capture_status').Update(
                        "Status: Capturing...")
                    self.window.Refresh()
                    keyboard.add_hotkey(self.capture_key,
                                        self.input_parsed_coords,
                                        timeout=1)
                    self.capturing = True
                else:
                    self.stop_quick_capture()

            elif event == "quick_capture":
                self.exit_quick_capture = False
                self.disable_coords_input()
                self.window.Element('capture').Update(text="Stop capturing")
                self.window.Element('quick_capture').Update(disabled=True)
                self.window.Element('capture_status').Update(
                    "Status: Capturing...")
                self.capturing = True
                self.window.Refresh()
                keyboard.add_hotkey(self.capture_key,
                                    self.add_wp_parsed_coords,
                                    timeout=1)

            elif event == "baseSelector":
                base = self.editor.default_bases.get(
                    self.values['baseSelector'])

                if base is not None:
                    self.update_position(base.position, base.elevation,
                                         base.name)

            elif event == "enter":
                self.window.Element('enter').Update(disabled=True)
                self.editor.enter_all(self.profile)
                self.window.Element('enter').Update(disabled=False)

            elif event == "WP":
                self.set_sequence_station_selector("sequence")

            elif event in "MSN":
                self.set_sequence_station_selector("station")

            elif event == "elevFeet":
                self.update_altitude_elements("meters")

            elif event == "elevMeters":
                self.update_altitude_elements("feet")

            elif event in ("latDeg", "latMin", "latSec", "lonDeg", "lonMin",
                           "lonSec"):
                position, _, _ = self.validate_coords()

                if position is not None:
                    m = mgrs.encode(
                        mgrs.LLtoUTM(position.lat.decimal_degree,
                                     position.lon.decimal_degree), 5)
                    self.window.Element("mgrs").Update(m)

            elif event == "mgrs":
                mgrs_string = self.window.Element("mgrs").Get()
                if mgrs_string:
                    try:
                        decoded_mgrs = mgrs.UTMtoLL(mgrs.decode(mgrs_string))
                        position = LatLon(
                            Latitude(degree=decoded_mgrs["lat"]),
                            Longitude(degree=decoded_mgrs["lon"]))
                        self.update_position(position, update_mgrs=False)
                    except (TypeError, ValueError) as e:
                        self.logger.error(f"Failed to decode MGRS: {e}")

            elif event in ("hornet", "tomcat", "harrier", "warthog", "mirage"):
                self.profile.aircraft = event
                self.update_waypoints_list()

            elif event == "filter":
                self.filter_preset_waypoints_dropdown()

        self.close()