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
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()
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
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()