#include "navlist.hxx"
+// Return true if the nav record matches the type
+static bool isTypeMatch(const FGNavRecord* n, fg_nav_types type) {
+ switch(type) {
+ case FG_NAV_ANY: return(true);
+ case FG_NAV_VOR: return(n->get_type() == 3);
+ case FG_NAV_NDB: return(n->get_type() == 2);
+ case FG_NAV_ILS: return(n->get_type() == 4); // Note - very simplified, only matches loc as part of full ILS.
+ default: return false;
+ }
+}
+
+
// Constructor
FGNavList::FGNavList( void ) {
}
}
+nav_list_type FGNavList::findFirstByIdent( string ident, fg_nav_types type, bool exact)
+{
+ nav_list_type n2;
+ n2.clear();
+
+ int iType;
+ if(type == FG_NAV_VOR) iType = 3;
+ else if(type == FG_NAV_NDB) iType = 2;
+ else return(n2);
+
+ nav_ident_map_iterator it;
+ if(exact) {
+ it = ident_navaids.find(ident);
+ } else {
+ bool typeMatch = false;
+ int safety_count = 0;
+ it = ident_navaids.lower_bound(ident);
+ while(!typeMatch) {
+ nav_list_type n0 = it->second;
+ // local copy, so we should be able to do anything with n0.
+ // Remove the types that don't match request.
+ for(nav_list_iterator it0 = n0.begin(); it0 != n0.end();) {
+ FGNavRecord* nv = *it0;
+ if(nv->get_type() == iType) {
+ typeMatch = true;
+ ++it0;
+ } else {
+ it0 = n0.erase(it0);
+ }
+ }
+ if(typeMatch) {
+ return(n0);
+ }
+ if(it == ident_navaids.begin()) {
+ // We didn't find a match before reaching the beginning of the map
+ n0.clear();
+ return(n0);
+ }
+ safety_count++;
+ if(safety_count == 1000000) {
+ SG_LOG(SG_INSTR, SG_ALERT,
+ "safety_count triggered exit from while loop in findFirstByIdent!");
+ break;
+ }
+ ++it;
+ if(it == ident_navaids.end()) {
+ n0.clear();
+ return(n0);
+ }
+ }
+ }
+ if(it == ident_navaids.end()) {
+ n2.clear();
+ return(n2);
+ } else {
+ nav_list_type n1 = it->second;
+ n2.clear();
+ for(nav_list_iterator it2 = n1.begin(); it2 != n1.end(); ++it2) {
+ FGNavRecord* nv = *it2;
+ if(nv->get_type() == iType) n2.push_back(nv);
+ }
+ return(n2);
+ }
+}
+
+
// Given an Ident and optional freqency, return the first matching
// station.
FGNavRecord *FGNavList::findByIdentAndFreq( const char* ident, const double freq )
// returns the closest entry to the give lon/lat/elev
FGNavRecord *FGNavList::findClosest( double lon_rad, double lat_rad,
- double elev_m )
+ double elev_m, fg_nav_types type)
{
FGNavRecord *result = NULL;
double diff;
latidx += 90;
int master_index = lonidx * 1000 + latidx;
-
+
nav_list_type navs = navaids_by_tile[ master_index ];
// cout << "Master index = " << master_index << endl;
// cout << "beacon search length = " << beacons.size() << endl;
double min_dist = 999999999.0;
for ( ; current != last ; ++current ) {
- // cout << " testing " << (*current)->get_ident() << endl;
- Point3D station = Point3D( (*current)->get_x(),
- (*current)->get_y(),
- (*current)->get_z() );
- // cout << " aircraft = " << aircraft << " station = " << station
- // << endl;
-
- double d = aircraft.distance3Dsquared( station ); // meters^2
- // cout << " distance = " << d << " ("
- // << FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER
- // * FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER
- // << ")" << endl;
-
- // cout << " range = " << sqrt(d) << endl;
-
- if ( d < min_dist ) {
- min_dist = d;
- result = (*current);
+ if(isTypeMatch(*current, type)) {
+ // cout << " testing " << (*current)->get_ident() << endl;
+ Point3D station = Point3D( (*current)->get_x(),
+ (*current)->get_y(),
+ (*current)->get_z() );
+ // cout << " aircraft = " << aircraft << " station = " << station
+ // << endl;
+
+ double d = aircraft.distance3Dsquared( station ); // meters^2
+ // cout << " distance = " << d << " ("
+ // << FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER
+ // * FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER
+ // << ")" << endl;
+
+ // cout << " range = " << sqrt(d) << endl;
+
+ if ( d < min_dist ) {
+ min_dist = d;
+ result = (*current);
+ }
}
}
typedef nav_map_type::const_iterator nav_map_const_iterator;
typedef map < string, nav_list_type > nav_ident_map_type;
+typedef nav_ident_map_type::iterator nav_ident_map_iterator;
typedef map < string, tacan_list_type > tacan_ident_map_type;
class FGNavList {
- nav_list_type navlist;
+ //nav_list_type navlist; // DCL - this doesn't appear to be used any more
+ // and can probably be removed.
nav_list_type carrierlist;
nav_map_type navaids;
nav_map_type navaids_by_tile;
// locate closest item in the DB matching the requested ident
FGNavRecord *findByIdent( const char* ident, const double lon, const double lat );
+
+ // Find items of requested type with closest exact or subsequent ident
+ // (by ASCII code value) to that supplied.
+ // Supplying true for exact forces only exact matches to be returned (similar to above function)
+ // Returns an empty list if no match found - calling function should check for this!
+ nav_list_type findFirstByIdent( string ident, fg_nav_types type, bool exact = false );
// Given an Ident and optional freqency, return the first matching
// station.
const double freq = 0.0 );
// returns the closest entry to the give lon/lat/elev
- FGNavRecord *findClosest( double lon_rad, double lat_rad, double elev_m );
+ FGNavRecord *findClosest( double lon_rad, double lat_rad, double elev_m, fg_nav_types type = FG_NAV_ANY );
// given a frequency returns the first matching entry
FGNavRecord *findStationByFreq( double frequency );
#define FG_DME_DEFAULT_RANGE 50 // nm
#define FG_NAV_MAX_RANGE 300 // nm
+// Shield the rest of FG from possibly changing details of Robins navaid type numbering system.
+// Currently only the GPS code uses this - extra types (LOC, GS etc) may need to be added
+// should other FG code choose to use this.
+enum fg_nav_types {
+ FG_NAV_VOR,
+ FG_NAV_NDB,
+ FG_NAV_ILS,
+ FG_NAV_ANY
+};
class FGNavRecord {
int type;
- double lon, lat; // location in geodetic coords
+ double lon, lat; // location in geodetic coords (degrees)
double elev_ft;
double x, y, z; // location in cartesian coords (earth centered)
int freq;
inline ~FGNavRecord(void) {}
inline int get_type() const { return type; }
- inline double get_lon() const { return lon; }
- inline void set_lon( double l ) { lon = l; }
- inline double get_lat() const { return lat; }
- inline void set_lat( double l ) { lat = l; }
+ inline fg_nav_types get_fg_type() const;
+ inline double get_lon() const { return lon; } // degrees
+ inline void set_lon( double l ) { lon = l; } // degrees
+ inline double get_lat() const { return lat; } // degrees
+ inline void set_lat( double l ) { lat = l; } // degrees
inline double get_elev_ft() const { return elev_ft; }
inline void set_elev_ft( double e ) { elev_ft = e; }
inline double get_x() const { return x; }
}
+inline fg_nav_types FGNavRecord::get_fg_type() const {
+ switch(type) {
+ case 2: return(FG_NAV_NDB);
+ case 3: return(FG_NAV_VOR);
+ case 4: return(FG_NAV_ILS);
+ default: return(FG_NAV_ANY);
+ }
+}
+
+
inline istream&
operator >> ( istream& in, FGNavRecord& n )
{