def __init__(self, lat=0.0, lon=0.0, altitude=None, name="n/d", topo_access_mode="srtm", topo_path=None, topo_data=None, auto_topo_access=True): LatLon.__init__(self, float(lat), float(lon), name) self.altitude = altitude #altitude in m self.altitude_err = 0.0 self.topo_access_mode = topo_access_mode self.local_topo_path = topo_path self.topo_data = None if topo_data is not None: self.set_topo_data(topo_data) if self.altitude is None or isnan(self.altitude): if auto_topo_access: self.get_altitude() else: self.altitude = 0.0 self.altitude_err = self._ALTERR_DEFAULT
def offset(self, azimuth, dist_hor, dist_vert=0.0, ellipse="WGS84", **kwargs): """Returns new GeoPoint at offset position Parameters ----------- azimuth : float azimuth direction angle (in decimal degrees, e.g. 90 for E direction, -90 or 270 for west) dist_hor : float horizontal offset to this point in km dist_vert : float vertical offset to this point in m (positive if point is higher, negative, if it is lower) ellipse : float geodetic system (ellipsoid), default is "WGS84", i.e. `World Geodetic System <https://confluence.qps.nl/pages/view page. action?pageId=29855173>`__ **kwargs : additional keyword arguments passed to init of new :class:`GeoPoint` object Returns ------- GeoPoint new location at offset position """ p = LatLon(self.lat.decimal_degree, self.lon.decimal_degree) p1 = p.offset(azimuth, dist_hor, ellipse) return GeoPoint(p1.lat.decimal_degree, p1.lon.decimal_degree, self.altitude + dist_vert, **kwargs)
def load(profile_name): profile = ProfileModel.get(ProfileModel.name == profile_name) aircraft = profile.aircraft wps = list() for waypoint in profile.waypoints: try: sequence = waypoint.sequence.identifier except AttributeError: sequence = 0 if waypoint.wp_type != "MSN": wp = Waypoint(LatLon(Latitude(waypoint.latitude), Longitude(waypoint.longitude)), elevation=waypoint.elevation, name=waypoint.name, sequence=sequence, wp_type=waypoint.wp_type) else: wp = MSN(LatLon(Latitude(waypoint.latitude), Longitude(waypoint.longitude)), elevation=waypoint.elevation, name=waypoint.name, sequence=sequence, wp_type=waypoint.wp_type, station=waypoint.station) wps.append(wp) profile = Profile(profile_name, waypoints=wps, aircraft=aircraft) profile.update_waypoint_numbers() logger.debug( f"Fetched {profile_name} from DB, with {len(wps)} waypoints") return profile
def test_LatLon_complex(): ''' Test LatLon method complex ''' palmyra = LatLon(5.8833, -162.0833) # test location is Palmyra Atoll complex_coords = palmyra.complex() # Convert lat/lon coordinate to single complex number assert complex_coords.real == 5.8833 # Failed to retrieve latitude from complex coordinate assert complex_coords.imag == -162.0833 # Failed to retrieve longitude from complex coordinate
def test_LatLon_project(): ''' Test LatLon method project ''' palmyra = LatLon(5.8833, -162.0833) # test location is Palmyra Atoll projection = pyproj.Proj(proj='utm',zone=3,ellps='WGS84') x, y = palmyra.project(projection) utm_x, utm_y = 822995, 651147 # True projected coordinates to the nearest meter assert int(x) == utm_x and int(y) == utm_y # Error in computing projected coordinates for Palmyra Atoll'
def test_LatLon_tostring(): ''' Test LatLon method to_string ''' palmyra = LatLon(5.8833, -162.0833) # test location is Palmyra Atoll # Built-in string conversion (calls to_string): assert str(palmyra) == '5.8833, -162.0833' # Failure of __str__ method # to_string method with decimal degrees: assert palmyra.to_string('D') == ('5.8833', '-162.0833') # Failure of degree decimal output # to_string method with degree minute seconds: assert palmyra.to_string('d%, %m%, %S%, %H') == ('5, 52, 59.88, N', '162, 4, 59.88, W') # to_string method with fancy separators: assert palmyra.to_string('H%_%d%deg %M%"') == ('N_5deg 52.998"', 'W_162deg 4.998"')
def test_LatLon_offset(): ''' Test LatLon method offset ''' palmyra, honolulu = LatLon(5.8833, -162.0833), LatLon(21.3, -157.8167) # locations: Palmyra Atoll and Honolulu, HI distance = palmyra.distance(honolulu) # WGS84 distance is 1766.69130376 km initial_heading = palmyra.heading_initial(honolulu) # Initial heading to Honolulu on WGS84 ellipsoid offset_hnl = palmyra.offset(initial_heading, distance) # Reconstruct lat/lon for Honolulu based on offset from Palmyra # Equality could also be tested with honolulu == offset_hnl, but would be subject to float errors assert honolulu.almost_equal(offset_hnl) vector = honolulu - palmyra # Same process with GeoVectors vector_hnl = palmyra + vector # Reconstruct lat/lon for Honolulu based on offset from Palmyra assert honolulu.almost_equal(vector_hnl)
def test_LatLon_distance(): ''' Test LatLon method distance ''' palmyra, honolulu = LatLon(5.8833, -162.0833), LatLon(21.3, -157.8167) # locations: Palmyra Atoll and Honolulu, HI true_distance = '1766.691' # Distance from Palmyra to Honolulu in km wgs84_distance = palmyra.distance(honolulu) assert '%.3f' %(wgs84_distance) == true_distance # Failed to calculate WGS84 distance from Palmyra to Honolulu wgs84_distance = honolulu.distance(palmyra) assert '%.3f' %(wgs84_distance) == true_distance # Failed to calculate WGS84 distance from Honolulu to Palmyra # Now including the north pole: geographic_north = LatLon(90, 0) # Longitude is meaningless in this case true_distance = '7645.673' # Distance from Honolulu to North Pole in km wgs84_distance = honolulu.distance(geographic_north) assert '%.3f' %(wgs84_distance) == true_distance # Failed to calculate WGS84 distance from north pole
def resolution(self): """Returns tuple (lat, lon) of the current grid resolution in km Note ---- The resolution is determined at the center of this grid """ if not LATLON_AVAILABLE: raise ImportError('Feature disabled: Neither LatLon nor ' 'LatLon23 are installed') x_lon, x_lat = int(len(self.lons) / 2), int(len(self.lats) / 2) p0 = LatLon(self.lats[x_lat], self.lons[x_lon]) r_lon = (p0 - LatLon(self.lats[x_lat], self.lons[x_lon + 1])).magnitude r_lat = (p0 - LatLon(self.lats[x_lat + 1], self.lons[x_lon])).magnitude return (r_lat, r_lon)
def to_object(waypoint): return Waypoint(LatLon(Latitude(waypoint.get('latitude')), Longitude(waypoint.get('longitude'))), elevation=waypoint.get('elevation'), name=waypoint.get('name'), sequence=waypoint.get('sequence'), wp_type=waypoint.get('wp_type'))
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 to_readable_string(self): readable_string = "Waypoints:\n\n" for wp in self.waypoints: if wp.wp_type != "MSN": position = LatLon(Latitude(wp.latitude), Longitude( wp.longitude)).to_string("d%°%m%'%S%\"%H") readable_string += str(wp) readable_string += f": {position[0]} {position[1]} | {wp.elevation}ft\n" readable_string += "\nPreplanned missions:\n\n" for wp in sorted(self.waypoints_of_type("MSN"), key=lambda waypoint: waypoint.station): if wp.wp_type == "MSN": position = LatLon(Latitude(wp.latitude), Longitude( wp.longitude)).to_string("d%°%m%'%S%\"%H") readable_string += str(wp) readable_string += f": {position[0]} {position[1]} | {wp.elevation}ft\n" return readable_string
def projection(location, distance, bearing): """Make a projection from location = (latitude, longitude) by distance (in feet) and by bearing (in degrees) returning at LatLon object """ km = distance / FEET_TO_KM latlon = LatLon(*location) + \ GeoVector(initial_heading=bearing, distance=km) return latlon
def move_vector(fix, vector): """ accepts a starting fix in lat lon determines destination after travelling a certain distance for a particular start heading """ distance = vector[1] * 1.852 # convert NM to KM heading = vector[0] # is this radians or degrees? # print "**********\ndebugging travel\n*********" # print "Checking on the start_point" # print start_point # print type(start_point) lat1 = fix[0] lon1 = fix[1] origin = LatLon(lat1, lon1) destination_obj = origin.offset(heading, distance) destination_tup = destination_obj.to_string() lat2 = round(float(destination_tup[0]), 2) lon2 = round(float(destination_tup[1]), 2) return((lat2, lon2))
def move_vector(fix, vector): """ accepts a starting fix in lat lon determines destination after travelling a certain distance for a particular start heading """ distance = vector[1] * 1.852 # convert NM to KM heading = vector[0] # is this radians or degrees? # print "**********\ndebugging travel\n*********" # print "Checking on the start_point" # print start_point # print type(start_point) lat1 = fix[0] lon1 = fix[1] origin = LatLon(lat1, lon1) destination_obj = origin.offset(heading, distance) destination_tup = destination_obj.to_string() lat2 = round(float(destination_tup[0]), 2) lon2 = round(float(destination_tup[1]), 2) return ((lat2, lon2))
def __init__(self, lat=0.0, lon=0.0, altitude=None, name="n/d", topo_access_mode="srtm", topo_path=None, topo_data=None, auto_topo_access=True): """Class initialisation :param float lat: latitude of point (decimal degrees) :param float lon: longitude of point (decimal degrees) :param float altitude: elevation (above surface) of point in m :param str name: name (ID) of this point :param str topo_access_mode: string specifying the current access mode for topographic data (in v1, choose between "srtm" or "etopo1") :param str topo_path: specify path where etopo1 data files are stored :param TopoData topo_data: you can assign an existing topo dataset to this point (can save time, e.g. for altitude access) """ lat, lon = float(lat), float(lon) if not all([isnum(x) for x in [lat, lon]]): raise ValueError("Invalid input for lat, lon in GeoPoint, got " "%s, %s (%s, %s) need non-NaN numeric" % (lat, lon, type(lat), type(lon))) #super(GeoPoint, self).__init__(lon, lat, name) LatLon.__init__(self, lat, lon, name) self.altitude = altitude #altitude in m self.altitude_err = 0.0 self._topo_access = TopoDataAccess(mode=topo_access_mode, local_path=topo_path) self.topo_data = None self.set_topo_data(topo_data) if auto_topo_access and (self.altitude is None or\ isnan(self.altitude)): self.get_altitude()
def test_LatLon_heading(): ''' Test LatLon methods heading_initial and heading_reverse ''' palmyra, honolulu = LatLon(5.8833, -162.0833), LatLon(21.3, -157.8167) # locations: Palmyra Atoll and Honolulu, HI true_heading = '14.691' # Correct heading in from Palmyra to Honolulu to 3 decimal places forward_heading = palmyra.heading_initial(honolulu) # Initial heading from palmyra to honolulu # Check heading from Palmyra Atoll to Honolulu using heading_initial: assert '%.3f' %(forward_heading) == true_heading reverse_heading = honolulu.heading_reverse(palmyra) # Reverse heading from honolulu to palmyra # Check heading from Palmyra Atoll to Honolulu using heading_reverse: assert '%.3f' %(reverse_heading) == true_heading # Now for two locations with (for our purposes) the same longitude - Washington, DC and Lima, Peru: washington, lima = LatLon(Latitude(38, 54), Longitude(-77, -2)), LatLon(Latitude(-12, -3), Longitude(-77, -2)) true_heading = '180.000' # Heading for directly south forward_heading = washington.heading_initial(lima) # Check handling of equal longitude coordinates by heading_initial: assert '%.3f' %(forward_heading) == true_heading reverse_heading = lima.heading_reverse(washington) # Check handling of equal longitude coordinates by heading_reverse: assert '%.3f' %(reverse_heading) == true_heading # Now for two locations with (for our purposes) the same latitude - Alexandria, Egypt and Shanghai, China: alexandria, shanghai = LatLon(Latitude(31, 12), Longitude(29, 55)), LatLon(Latitude(31, 12), Longitude(121, 30)) true_heading = '61.941' # Correct heading in from Alexandria to Shanghai to 3 decimal places forward_heading = alexandria.heading_initial(shanghai) # Initial heading from Alexandria to Shanghai # Check handling of equal latitude coordinates by heading_initial: assert '%.3f' %(forward_heading) == true_heading reverse_heading = shanghai.heading_reverse(alexandria) # Reverse heading from Shanghai to Alexandria # Check handling of equal latitude coordinates by heading_initial: assert '%.3f' %(reverse_heading) == true_heading
def load_base_data(basedata, basedict): waypoints_list = basedata.get("waypoints") if type(waypoints_list) == list: basedata = {i: wp for i, wp in enumerate(waypoints_list)} for _, base in basedata.items(): name = base.get('name') if name not in ("Stennis", "Kuznetsov", "Kuznetsov North", "Kuznetsov South"): lat = base.get("latitude") or base.get('locationDetails').get('lat') lon = base.get("longitude") or base.get('locationDetails').get('lon') elev = base.get("elevation") if elev is None: elev = base.get('locationDetails').get('altitude') position = LatLon(Latitude(degree=lat), Longitude(degree=lon)) basedict[name] = Wp(position=position, name=name, elevation=elev)
def validate_coords(self): lat_deg = self.window.Element("latDeg").Get() lat_min = self.window.Element("latMin").Get() lat_sec = self.window.Element("latSec").Get() lon_deg = self.window.Element("lonDeg").Get() lon_min = self.window.Element("lonMin").Get() lon_sec = self.window.Element("lonSec").Get() try: position = LatLon(Latitude(degree=lat_deg, minute=lat_min, second=lat_sec), Longitude(degree=lon_deg, minute=lon_min, second=lon_sec)) elevation = int(self.window.Element("elevFeet").Get()) name = self.window.Element("msnName").Get() return position, elevation, name except ValueError as e: self.logger.error(f"Failed to validate coords: {e}") return None, None, None
def get_profile(self, profilename): profile = ProfileModel.get(ProfileModel.name == profilename) aircraft = profile.aircraft wps = dict() for waypoint in profile.waypoints: if waypoint.wp_type == "MSN": wps_list = wps.get(waypoint.wp_type, dict()).get(waypoint.station, list()) else: wps_list = wps.get(waypoint.wp_type, list()) if waypoint.sequence: sequence = waypoint.sequence.identifier else: sequence = None wp = Wp(LatLon(Latitude(waypoint.latitude), Longitude(waypoint.longitude)), elevation=waypoint.elevation, name=waypoint.name, sequence=sequence, wp_type=waypoint.wp_type, station=waypoint.station) if waypoint.wp_type == "MSN": stations = wps.get("MSN", dict()) station = stations.get(waypoint.station, list()) station.append(wp) stations[waypoint.station] = station wps["MSN"] = stations else: wps_list.append(wp) wps[waypoint.wp_type] = wps_list self.logger.debug( f"Fetched {profilename} from DB, with {len(wps)} waypoints") return wps, aircraft
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 __init__(self, lat, lon): self.latlon = LatLon(Latitude(lat), Longitude(lon))
def increase_grid_resolution(self, res=0.2, polyorder=2): """Gaussian pyramide based upscaling of topographic grid This function checks the current topographic resolution in the center of the grid. Based on this, an upsacling factor is determined and the :func:`cv2.pyrUp` is used to increase the resolution using interpolation. Note, that this does not increase the actual resolution of the topographic data grid. Note ---- Requires that opencv library is installed. Parameters ---------- res : int or float, optional desired grid resolution in km (default: 0.2) polyorder : int, optional order of polynomial used for interpolation (default: 2) Returns ------- TopoData new object with desired grid resolution Raises ------ ImportError if opencv is not installed. """ if not CV2_AVAILABLE or not LATLON_AVAILABLE: raise ImportError('Feature disabled: Require opencv and ' 'LatLon (or LatLon23) library to change ' 'grid resolution ') from cv2 import pyrUp lons = self.lons lats = self.lats vals = self.data if not all(np.mod(x, 2) == 0 for x in [len(lons), len(lats)]): print( "Fatal error, odd array size detected, no upscaling possible." " Return current data dict") return False c_lon = len(lons) / 2 - 1 #center longitude index c_lat = len(lats) / 2 - 1 #center latitude index p1 = LatLon(lats[c_lat], lons[c_lon]) p2 = LatLon(lats[c_lat + 1], lons[c_lon + 1]) dist = (p2 - p1).magnitude #distance between 2 points on grid res_fac = dist / res #factor for increasing the spatial resolution if res_fac <= 1: print( ("No interpolation of topodata necessary: topo raw data " "already has desired resolution...\nCurrent resolution: %s" + str(dist) + "km\nDesired resolution: %s km" % (dist, res))) return self fac = int(np.ceil(np.log2( res_fac))) #the corresponding up-factor for the scale space print(("Increasing spatial topography resolution by factor %s" % (2**fac))) for k in range(fac): vals = pyrUp(vals) p_lons = np.poly1d(np.polyfit(np.arange(len(lons)), lons, polyorder)) p_lats = np.poly1d(np.polyfit(np.arange(len(lats)), lats, polyorder)) lons_new = p_lons(np.linspace(0, len(lons) - 1, vals.shape[1])) lats_new = p_lats(np.linspace(0, len(lats) - 1, vals.shape[0])) return TopoData(lats_new, lons_new, vals, self.data_id + "_interp")
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()
class Location: """ Parameters ---------- lat : LatLon.lat lon : LatLon.lon Attributes ---------- latlon : LatLon """ def __init__(self, lat, lon): self.latlon = LatLon(Latitude(lat), Longitude(lon)) def get_distance_in_km(self, snd_location): """ Parameters ---------- snd_location : Location Returns ------- int """ return self.latlon.distance(snd_location.latlon) def get_distance_in_m(self, snd_location): """ Parameters ---------- snd_location : Location Returns ------- int """ return self.get_distance_in_km(snd_location) * 1000 def get_heading(self, snd_location): """ Parameters ---------- snd_location : Location Returns ------- LatLon.heading """ return self.latlon.heading_initial(snd_location.latlon) def get_lat_lon(self): """ Returns ------- LatLon """ return self.latlon def lat_lon_to_string(self): """ Returns ------- String """ return self.latlon.to_string('D') def offset_in_m(self, heading, distance): """ Parameters ---------- heading : LatLon.heading distance : int Returns ------- Location """ latlon = self.latlon.offset(heading, distance / 1000) return Location(latlon.to_string('D')[0], latlon.to_string('D')[1])
def coordinates(self): pos = LatLon(self.latitude, self.longitude) return str(latlon_to_string(pos))
def distance_calculation(lat1, lng1, lat2, lng2): """A function to calculate distance.""" return LatLon(lat1, lng1).distance(LatLon(lat2, lng2))
#print(', '.join(row)) print(row[0]) #Name print(row[3]) #Lat DDMM.MMM print(row[4]) #Long DDDMM.MMM print(row[5]) #Height m print(str(uuid.uuid1())) latdeg = row[3][:2] print(latdeg) latmin = row[3][2:].replace('N', '') print(latmin) longdeg = row[4][:3] print(longdeg) longmin = row[4][3:].replace('E', '') print(longmin) latlonobj = LatLon(Latitude(degree=latdeg, minute=latmin), Longitude(degree=longdeg, minute=longmin)) print(latlonobj.to_string( 'D')) # Print coordinates to degree minute second lat = str(latlonobj.lat) long = str(latlonobj.lon) alt = float(row[5].replace('m', '')) * 0.1 alt = str(alt) newline = " <LandmarkLocation instanceId=\"{" + str(uuid.uuid1( )) + "}\" type=\"POI\" name=\"" + row[ 0] + "\" lat=\"" + lat + "\" lon=\"" + long + "\" alt=\"" + alt + "\"/>" with open('file.xml', 'a') as f: print(newline, file=f) f.close() with open('file.xml', 'a') as f: print("</FSData>", file=f)
def full_coordinates(self): pos = LatLon(self.latitude, self.longitude) return str(latlon_to_string(pos)) + ' (' + str( self.longitude) + ', ' + str(self.latitude) + ')'
def get_standard_coord_data(cls, match): """Creates LatLon from regular coords""" lat_lon = LatLon(float(match.group(1)), float(match.group(2))) return lat_lon
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 handle(self, sample): assert type(sample) == dict result = [] if sample["mdesc"] == "dst200depth": # $--DBT,x.x,f,x.x,M,x.x,F*hh<CR><LF> result += [("$SDDBT", "", "f", "%s" % sample["depth"], "m", "", "F")] # $--VHW,x.x,T,x.x,M,x.x,N,x.x,K*hh<CR><LF> result += [("$SDVHW", "0.0", "T", "0.0", "M", "%.2f" % sample["stw"], "N", "0.0", "K")] elif sample["mdesc"] == "gpstime": if isinstance(sample["utctime"], str): # For the test cases. sample["utctime"] = datetime.strptime(sample["utctime"], "%Y-%m-%dT%H:%M:%S") # Will be used later on. if isinstance(sample["utctime"], datetime): self.gpstime = sample["utctime"] assert self.gpstime is None or isinstance(self.gpstime, datetime) elif sample["mdesc"] == "gpspos": lat = sample["lat"] lon = sample["lon"] if isnan(lat) or isnan(lon): pass else: self.gpspos = LatLon(lat, lon) elif sample["mdesc"] == "gpscog": if self.gpstime is None or self.gpspos is None: # Not enough data yet. pass else: rmc = ["$GPRMC", self.gpstime.strftime("%H%M%S"), "A"] rmc += nmeapos(self.gpspos) rmc += [ "%.2f" % sample["sog"], "%.2f" % sample["cog"], self.gpstime.strftime("%d%m%y"), "0.0", # magn var "E" ] result.append(tuple(rmc)) # $--HDT,x.x,T*hh<CR><LF> result.append(("$GPHDT", "%.2f" % sample["cog"], "T")) elif sample["mdesc"] == "wsi0": # $--MWV,x.x,a,x.x,a*hh<CR><LF> result += [( "$FVMWV", "%.2f" % sample["awa"], "R", # (R)elative, not (T)rue. "%.2f" % sample["aws_lo"], "K", # knots "A") # (valid) ] elif sample["mdesc"] == "environment": # $IIXDR,P,1.02481,B,Barometer*0D # $IIXDR,C,19.52,C,TempAir*3D result += [("$ZZXDR", "P", "%.5f" % sample["airpressure"], "B", "Barometer"), ("$ZZXDR", "C", "%.2f" % sample.get("temp_c", 0.0), "C", "TempDir")] result = [",".join(x) for x in result] # Make it a string. return self.checksum(result or None)