From 8cc7b283d54d10150ad0883e96fd05ce020e7ed8 Mon Sep 17 00:00:00 2001 From: curt Date: Sat, 25 Jan 2003 20:45:39 +0000 Subject: [PATCH] Refactored some of the navlist code and removed the built in "fail to find" if the station is too far away. Instead, simply return the closest station. All the code that searches navaids does it's own range checking anyway. This will make the navlist query functions a bit more useful for other types of functionality where you may need to lookup a station without consideration of range (i.e. presetting your position relative to a navaid.) --- src/Cockpit/dme.cxx | 20 ++++---- src/Cockpit/kr_87.cxx | 29 +++++------ src/Cockpit/navcom.cxx | 28 +++++------ src/Main/fg_init.cxx | 8 +-- src/Navaids/nav.hxx | 9 ---- src/Navaids/navlist.cxx | 102 +++++++++++++++++---------------------- src/Navaids/navlist.hxx | 25 +++++----- src/Navaids/testnavs.cxx | 22 +++++---- 8 files changed, 113 insertions(+), 130 deletions(-) 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; }