diff --git a/src/Cockpit/dme.cxx b/src/Cockpit/dme.cxx index bc00b0f51..e9a10b21c 100644 --- a/src/Cockpit/dme.cxx +++ b/src/Cockpit/dme.cxx @@ -218,7 +218,7 @@ void FGDME::search() } FGILS ils; - FGNav nav; + FGNav *nav; if ( current_ilslist->query( lon, lat, elev, freq, &ils ) ) { if (ils.get_has_dme()) { @@ -232,17 +232,17 @@ void FGDME::search() y = ils.get_dme_y(); z = ils.get_dme_z(); } - } else if ( current_navlist->query( lon, lat, elev, freq, &nav ) ) { - if (nav.get_has_dme()) { + } else if ( (nav = current_navlist->findByFreq(freq, lon, lat, elev)) != NULL ) { + if (nav->get_has_dme()) { valid = true; - lon = nav.get_lon(); - lat = nav.get_lat(); - elev = nav.get_elev(); - range = nav.get_range(); + lon = nav->get_lon(); + lat = nav->get_lat(); + elev = nav->get_elev(); + range = nav->get_range(); effective_range = kludgeRange(elev, elev, range); - x = nav.get_x(); - y = nav.get_y(); - z = nav.get_z(); + x = nav->get_x(); + y = nav->get_y(); + z = nav->get_z(); } } else { valid = false; diff --git a/src/Cockpit/kr_87.cxx b/src/Cockpit/kr_87.cxx index da6cde50b..9c06f9a49 100644 --- a/src/Cockpit/kr_87.cxx +++ b/src/Cockpit/kr_87.cxx @@ -482,33 +482,34 @@ void FGKR_87::search() { double acft_elev = alt_node->getDoubleValue() * SG_FEET_TO_METER; // FIXME: the panel should handle this - FGNav nav; - static string last_ident = ""; //////////////////////////////////////////////////////////////////////// // ADF. //////////////////////////////////////////////////////////////////////// - if ( current_navlist->query( acft_lon, acft_lat, acft_elev, freq, &nav ) ) { + FGNav *nav + = current_navlist->findByFreq(freq, acft_lon, acft_lat, acft_elev); + + if ( nav != NULL ) { char sfreq[128]; snprintf( sfreq, 10, "%.0f", freq ); ident = sfreq; - ident += nav.get_ident(); -// cout << "adf ident = " << ident << endl; + ident += nav->get_ident(); + // cout << "adf ident = " << ident << endl; valid = true; if ( last_ident != ident ) { last_ident = ident; - trans_ident = nav.get_trans_ident(); - stn_lon = nav.get_lon(); - stn_lat = nav.get_lat(); - stn_elev = nav.get_elev(); - range = nav.get_range(); + trans_ident = nav->get_trans_ident(); + stn_lon = nav->get_lon(); + stn_lat = nav->get_lat(); + stn_elev = nav->get_elev(); + range = nav->get_range(); effective_range = kludgeRange(stn_elev, acft_elev, range); - x = nav.get_x(); - y = nav.get_y(); - z = nav.get_z(); + x = nav->get_x(); + y = nav->get_y(); + z = nav->get_z(); if ( globals->get_soundmgr()->exists( "adf-ident" ) ) { globals->get_soundmgr()->remove( "adf-ident" ); @@ -528,7 +529,7 @@ void FGKR_87::search() { // << globals->get_time_params()->get_cur_time() << endl; // cout << "Found an adf station in range" << endl; - // cout << " id = " << nav.get_ident() << endl; + // cout << " id = " << nav->get_ident() << endl; } } else { valid = false; diff --git a/src/Cockpit/navcom.cxx b/src/Cockpit/navcom.cxx index e621ddbf2..bf2e522ca 100644 --- a/src/Cockpit/navcom.cxx +++ b/src/Cockpit/navcom.cxx @@ -451,7 +451,7 @@ void FGNavCom::search() double elev = alt_node->getDoubleValue() * SG_FEET_TO_METER; FGILS ils; - FGNav nav; + FGNav *nav; //////////////////////////////////////////////////////////////////////// // Nav. @@ -515,27 +515,27 @@ void FGNavCom::search() // cout << "Found an ils station in range" << endl; // cout << " id = " << ils.get_locident() << endl; } - } else if ( current_navlist->query( lon, lat, elev, nav_freq, &nav ) ) { - nav_id = nav.get_ident(); + } else if ( (nav = current_navlist->findByFreq(nav_freq, lon, lat, elev)) != NULL ) { + nav_id = nav->get_ident(); nav_valid = true; if ( last_nav_id != nav_id || !last_nav_vor ) { last_nav_id = nav_id; last_nav_vor = true; - nav_trans_ident = nav.get_trans_ident(); + nav_trans_ident = nav->get_trans_ident(); nav_loc = false; - nav_has_dme = nav.get_has_dme(); + nav_has_dme = nav->get_has_dme(); nav_has_gs = false; - nav_loclon = nav.get_lon(); - nav_loclat = nav.get_lat(); - nav_elev = nav.get_elev(); - nav_magvar = nav.get_magvar(); - nav_range = nav.get_range(); + nav_loclon = nav->get_lon(); + nav_loclat = nav->get_lat(); + nav_elev = nav->get_elev(); + nav_magvar = nav->get_magvar(); + nav_range = nav->get_range(); nav_effective_range = adjustNavRange(nav_elev, elev, nav_range); nav_target_gs = 0.0; nav_radial = nav_sel_radial; - nav_x = nav.get_x(); - nav_y = nav.get_y(); - nav_z = nav.get_z(); + nav_x = nav->get_x(); + nav_y = nav->get_y(); + nav_z = nav->get_z(); if ( globals->get_soundmgr()->exists( nav_fx_name ) ) { globals->get_soundmgr()->remove( nav_fx_name ); @@ -566,7 +566,7 @@ void FGNavCom::search() // << globals->get_time_params()->get_cur_time() << endl; // cout << "Found a vor station in range" << endl; - // cout << " id = " << nav.get_ident() << endl; + // cout << " id = " << nav->get_ident() << endl; } } else { nav_valid = false; diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index 842509c54..57c590489 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -960,15 +960,15 @@ static void fgSetDistOrAltFromGlideSlope() { // Set current_options lon/lat given an airport id and heading (degrees) static bool fgSetPosFromNAV( const string& id, const double& freq ) { - FGNav nav; + FGNav *nav = current_navlist->findByIdentAndFreq( id.c_str(), freq ); // set initial position from runway and heading - if ( current_navlist->findByIdentAndFreq( id.c_str(), freq, &nav ) ) { + if ( nav != NULL ) { SG_LOG( SG_GENERAL, SG_INFO, "Attempting to set starting position for " << id << ":" << freq ); - double lon = nav.get_lon(); - double lat = nav.get_lat(); + double lon = nav->get_lon(); + double lat = nav->get_lat(); if ( fabs( fgGetDouble("/sim/presets/offset-distance") ) > SG_EPSILON ) { diff --git a/src/Navaids/nav.hxx b/src/Navaids/nav.hxx index 478c47e1e..2bfff9f1e 100644 --- a/src/Navaids/nav.hxx +++ b/src/Navaids/nav.hxx @@ -79,15 +79,6 @@ public: inline string get_trans_ident() { return trans_ident; } inline double get_magvar () const { return magvar; } - /* inline void set_type( char t ) { type = t; } - inline void set_lon( double l ) { lon = l; } - inline void set_lat( double l ) { lat = l; } - inline void set_elev( double e ) { elev = e; } - inline void set_freq( int f ) { freq = f; } - inline void set_range( int r ) { range = r; } - inline void set_dme( bool b ) { dme = b; } - inline void set_ident( char *i ) { strncpy( ident, i, 5 ); } */ - friend istream& operator>> ( istream&, FGNav& ); }; diff --git a/src/Navaids/navlist.cxx b/src/Navaids/navlist.cxx index aba88dddc..09395daa4 100644 --- a/src/Navaids/navlist.cxx +++ b/src/Navaids/navlist.cxx @@ -108,75 +108,74 @@ bool FGNavList::init( SGPath path ) { } -// query the database for the specified frequency, lon and lat are in -// degrees, elev is in meters -bool FGNavList::query( double lon, double lat, double elev, double freq, - FGNav *nav ) +// Query the database for the specified frequency. It is assumed that +// there will be multiple stations with matching frequencies so a +// position must be specified. Lon and lat are in degrees, elev is in +// meters. +FGNav *FGNavList::findByFreq( double freq, double lon, double lat, double elev ) { nav_list_type stations = navaids[(int)(freq*100.0 + 0.5)]; - - nav_list_iterator current = stations.begin(); - nav_list_iterator last = stations.end(); - Point3D aircraft = sgGeodToCart( Point3D(lon, lat, elev) ); - return findNavFromList(aircraft, current, last, nav); + + return findNavFromList( aircraft, stations ); } -bool FGNavList::findByIdent(const char* ident, double lon, double lat, - FGNav *nav) +FGNav *FGNavList::findByIdent( const char* ident, + const double lon, const double lat ) { nav_list_type stations = ident_navaids[ident]; - - nav_list_iterator current = stations.begin(); - nav_list_iterator last = stations.end(); - Point3D aircraft = sgGeodToCart( Point3D(lon, lat, 0.0) ); - return findNavFromList(aircraft, current, last, nav); + + return findNavFromList( aircraft, stations ); } -bool FGNavList::findByIdentAndFreq(const char* ident, const double& freq, - FGNav *nav) +// Given an Ident and optional freqency, return the first matching +// station. +FGNav *FGNavList::findByIdentAndFreq( const char* ident, const double freq ) { - cout << "ident = " << ident << endl; nav_list_type stations = ident_navaids[ident]; - cout << " matches = " << stations.size() << endl; - nav_list_iterator current = stations.begin(); - nav_list_iterator last = stations.end(); - if ( stations.size() > 1 ) { - // more than one match on this ident, use freq to refine + if ( freq > 0.0 ) { + // sometimes there can be duplicated idents. If a freq is + // specified, use it to refine the search. int f = (int)(freq*100.0 + 0.5); - for ( ; current != last ; ++current ) { - if ( f == (*current)->get_freq() ) { - *nav = (**current); - return true; + for ( unsigned int i = 0; i < stations.size(); ++i ) { + if ( f == stations[i]->get_freq() ) { + return stations[i]; } } } else { - *nav = (**current); - return true; + return stations[0]; } - return false; + return NULL; } -bool FGNavList::findNavFromList(const Point3D &aircraft, - nav_list_iterator current, - nav_list_iterator end, FGNav *nav) +// Given a point and a list of stations, return the closest one to the +// specified point. +FGNav *FGNavList::findNavFromList( const Point3D &aircraft, + const nav_list_type &stations ) { - // double az1, az2, s; - + FGNav *nav = NULL; Point3D station; double d2; - double min_dist = 99999999999999.9; - bool found_one = false; - for ( ; current != end ; ++current ) { + double min_dist; + + // prime the pump with info from stations[0] + if ( stations.size() > 0 ) { + nav = stations[0]; + station = Point3D( nav->get_x(), nav->get_y(), nav->get_z()); + min_dist = aircraft.distance3Dsquared( station ); + } + + // check if any of the remaining stations are closer + for ( unsigned int i = 1; i < stations.size(); ++i ) { // cout << "testing " << current->get_ident() << endl; - station = Point3D((*current)->get_x(), (*current)->get_y(), - (*current)->get_z()); + station = Point3D( stations[i]->get_x(), stations[i]->get_y(), + stations[i]->get_z()); d2 = aircraft.distance3Dsquared( station ); @@ -184,22 +183,11 @@ bool FGNavList::findNavFromList(const Point3D &aircraft, // << " range = " << current->get_range() * SG_NM_TO_METER // << endl; - // match d^2 < 2 * range^2 the published range so we can model - // reduced signal strength - double twiceRange = 2 * (*current)->get_range() * SG_NM_TO_METER; - if ( d2 < (twiceRange * twiceRange)) { - // cout << "d2 = " << d2 << " min_dist = " << min_dist << endl; - if ( d2 < min_dist ) { - min_dist = d2; - found_one = true; - *nav = (**current); - // cout << "matched = " << (*current)->get_ident() << endl; - } else { - // cout << "matched, but too far away = " - // << (*current)->get_ident() << endl; - } - } + if ( d2 < min_dist ) { + min_dist = d2; + nav = stations[i]; + } } - return found_one; + return nav; } diff --git a/src/Navaids/navlist.hxx b/src/Navaids/navlist.hxx index c890e0ef8..31e997276 100644 --- a/src/Navaids/navlist.hxx +++ b/src/Navaids/navlist.hxx @@ -54,12 +54,10 @@ class FGNavList { nav_map_type navaids; nav_ident_map_type ident_navaids; - // internal helper to pick a Nav item from a nav_list based on - // distance from the aircraft point - bool findNavFromList(const Point3D &aircraft, - nav_list_iterator current, - nav_list_iterator last, - FGNav *n); + // Given a point and a list of stations, return the closest one to + // the specified point. + FGNav *findNavFromList( const Point3D &aircraft, + const nav_list_type &stations ); public: @@ -69,15 +67,18 @@ public: // load the navaids and build the map bool init( SGPath path ); - // query the database for the specified frequency, lon and lat are - // in degrees, elev is in meters - bool query( double lon, double lat, double elev, double freq, FGNav *nav ); + // Query the database for the specified frequency. It is assumed + // that there will be multiple stations with matching frequencies + // so a position must be specified. Lon and lat are in degrees, + // elev is in meters. + FGNav *findByFreq( double freq, double lon, double lat, double elev ); // locate closest item in the DB matching the requested ident - bool findByIdent(const char* ident, double lon, double lat, FGNav *nav); + FGNav *findByIdent( const char* ident, const double lon, const double lat ); - // locate item in the DB matching the requested ident - bool findByIdentAndFreq(const char* ident, const double& freq, FGNav *nav); + // Given an Ident and optional freqency, return the first matching + // station. + FGNav *findByIdentAndFreq( const char* ident, const double freq = 0.0 ); }; diff --git a/src/Navaids/testnavs.cxx b/src/Navaids/testnavs.cxx index 3e95bbcff..b18455bf1 100644 --- a/src/Navaids/testnavs.cxx +++ b/src/Navaids/testnavs.cxx @@ -16,25 +16,27 @@ int main() { current_navlist->init( p_nav ); - FGNav n; - if ( current_navlist->query( -93.2 * SG_DEGREES_TO_RADIANS, - 45.14 * SG_DEGREES_TO_RADIANS, - 3000, 117.30, &n) ) + FGNav *n; + if ( (n = current_navlist->findByFreq( -93.2 * SG_DEGREES_TO_RADIANS, + 45.14 * SG_DEGREES_TO_RADIANS, + 3000, 117.30)) != NULL ) { cout << "Found a vor station in range" << endl; - cout << " id = " << n.get_ident() << endl; + cout << " id = " << n->get_ident() << endl; } else { cout << "not picking up vor. :-(" << endl; } - FGNav dcs; - if (current_navlist->findByIdent("DCS", -3.3 * SG_DEGREES_TO_RADIANS, - 55.9 * SG_DEGREES_TO_RADIANS, &dcs)) { + FGNav *dcs; + if ( (dcs = current_navlist->findByIdent( "DCS", + -3.3 * SG_DEGREES_TO_RADIANS, + 55.9 * SG_DEGREES_TO_RADIANS)) + != NULL ) { cout << "Found DCS by ident" << endl; - if (dcs.get_freq() != 11520) + if (dcs->get_freq() != 11520) cout << "Frequency for DCS VOR is wrong (should be 115.20), it's " - << dcs.get_freq() << endl; + << dcs->get_freq() << endl; } else { cout << "couldn't locate DCS (Dean-Cross) VOR" << endl; }