diff --git a/src/Airports/runways.hxx b/src/Airports/runways.hxx index 7bb21b6b4..8e40f9e76 100644 --- a/src/Airports/runways.hxx +++ b/src/Airports/runways.hxx @@ -44,6 +44,10 @@ class FGRunway : public FGPositioned double _width; double _displ_thresh; double _stopway; + + /** surface, as defined by: + * http://www.x-plane.org/home/robinp/Apt810.htm#RwySfcCodes + */ int _surface_code; public: diff --git a/src/Airports/simple.hxx b/src/Airports/simple.hxx index 7c7445947..9a295b251 100644 --- a/src/Airports/simple.hxx +++ b/src/Airports/simple.hxx @@ -71,6 +71,9 @@ public: bool isSeaport() const; bool isHeliport() const; + virtual const std::string& name() const + { return _name; } + const SGGeod& getTowerLocation() const { return _tower_location; } void setMetar(bool value) { _has_metar = value; } diff --git a/src/Instrumentation/KLN89/kln89_page_ndb.cxx b/src/Instrumentation/KLN89/kln89_page_ndb.cxx index 7bc6f2848..d118e5abb 100644 --- a/src/Instrumentation/KLN89/kln89_page_ndb.cxx +++ b/src/Instrumentation/KLN89/kln89_page_ndb.cxx @@ -90,7 +90,7 @@ void KLN89NDBPage::Update(double dt) { } if(_subPage == 0) { // TODO - trim VOR-DME from the name, convert to uppercase, abbreviate, etc - _kln89->DrawText(np->get_name(), 2, 0, 2); + _kln89->DrawText(np->name(), 2, 0, 2); _kln89->DrawLatitude(np->get_lat(), 2, 3, 1); _kln89->DrawLongitude(np->get_lon(), 2, 3, 0); } else { diff --git a/src/Instrumentation/KLN89/kln89_page_vor.cxx b/src/Instrumentation/KLN89/kln89_page_vor.cxx index 1b9fb0ace..c0caaba72 100644 --- a/src/Instrumentation/KLN89/kln89_page_vor.cxx +++ b/src/Instrumentation/KLN89/kln89_page_vor.cxx @@ -92,7 +92,7 @@ void KLN89VorPage::Update(double dt) { //// TODO - will almost certainly have to process freq below for FG _kln89->DrawFreq(np->get_freq(), 2, 9, 3); // TODO - trim VOR-DME from the name, convert to uppercase, abbreviate, etc - _kln89->DrawText(np->get_name(), 2, 0, 2); + _kln89->DrawText(np->name(), 2, 0, 2); //cout << np->lat << "... "; _kln89->DrawLatitude(np->get_lat(), 2, 3, 1); _kln89->DrawLongitude(np->get_lon(), 2, 3, 0); diff --git a/src/Instrumentation/adf.cxx b/src/Instrumentation/adf.cxx index e8c20710f..053812a0d 100644 --- a/src/Instrumentation/adf.cxx +++ b/src/Instrumentation/adf.cxx @@ -217,16 +217,15 @@ ADF::search (double frequency_khz, double longitude_rad, _time_before_search_sec = 1.0; // try the ILS list first - FGNavRecord *nav = - globals->get_navlist()->findByFreq(frequency_khz, longitude_rad, - latitude_rad, altitude_m); + FGNavRecord *nav = globals->get_navlist()->findByFreq(frequency_khz, + SGGeod::fromRadM(longitude_rad, latitude_rad, altitude_m)); _transmitter_valid = (nav != NULL); if ( _transmitter_valid ) { ident = nav->get_trans_ident(); if ( ident != _last_ident ) { - _transmitter_pos = nav->get_pos(); - _transmitter_cart = nav->get_cart(); + _transmitter_pos = nav->geod(); + _transmitter_cart = nav->cart(); _transmitter_range_nm = nav->get_range(); } } diff --git a/src/Instrumentation/dme.cxx b/src/Instrumentation/dme.cxx index f12b4f80e..5685dbabe 100644 --- a/src/Instrumentation/dme.cxx +++ b/src/Instrumentation/dme.cxx @@ -165,14 +165,14 @@ DME::search (double frequency_mhz, double longitude_rad, _time_before_search_sec = 1.0; // try the ILS list first - FGNavRecord *dme - = globals->get_dmelist()->findByFreq( frequency_mhz, longitude_rad, - latitude_rad, altitude_m); + + FGNavRecord *dme = globals->get_dmelist()->findByFreq( frequency_mhz, + SGGeod::fromRadM(longitude_rad, latitude_rad, altitude_m)); _transmitter_valid = (dme != NULL); if ( _transmitter_valid ) { - _transmitter = dme->get_cart(); + _transmitter = dme->cart(); _transmitter_elevation_ft = dme->get_elev_ft(); _transmitter_range_nm = dme->get_range(); _transmitter_bias = dme->get_multiuse(); diff --git a/src/Instrumentation/kr_87.cxx b/src/Instrumentation/kr_87.cxx index 2188c08c9..6683f8f93 100644 --- a/src/Instrumentation/kr_87.cxx +++ b/src/Instrumentation/kr_87.cxx @@ -494,10 +494,9 @@ void FGKR_87::update( double dt_sec ) { // Update current nav/adf radio stations based on current postition void FGKR_87::search() { - double acft_lon = lon_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS; - double acft_lat = lat_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS; - double acft_elev = alt_node->getDoubleValue() * SG_FEET_TO_METER; - + SGGeod pos = SGGeod::fromDegFt(lon_node->getDoubleValue(), + lat_node->getDoubleValue(), alt_node->getDoubleValue()); + // FIXME: the panel should handle this static string last_ident = ""; @@ -508,9 +507,8 @@ void FGKR_87::search() { // ADF. //////////////////////////////////////////////////////////////////////// - FGNavRecord *adf - = globals->get_navlist()->findByFreq( freq, acft_lon, acft_lat, - acft_elev ); + + FGNavRecord *adf = globals->get_navlist()->findByFreq( freq, pos); if ( adf != NULL ) { char sfreq[128]; snprintf( sfreq, 10, "%d", freq ); @@ -526,8 +524,8 @@ void FGKR_87::search() { stn_lat = adf->get_lat(); stn_elev = adf->get_elev_ft(); range = adf->get_range(); - effective_range = kludgeRange(stn_elev, acft_elev, range); - xyz = adf->get_cart(); + effective_range = kludgeRange(stn_elev, pos.getElevationM(), range); + xyz = adf->cart(); if ( globals->get_soundmgr()->exists( "adf-ident" ) ) { globals->get_soundmgr()->remove( "adf-ident" ); diff --git a/src/Instrumentation/marker_beacon.cxx b/src/Instrumentation/marker_beacon.cxx index 822ef4e3d..e636704fb 100644 --- a/src/Instrumentation/marker_beacon.cxx +++ b/src/Instrumentation/marker_beacon.cxx @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -210,20 +211,20 @@ FGMarkerBeacon::update(double dt) static bool check_beacon_range( const SGGeod& pos, - FGNavRecord *b ) + FGPositioned *b ) { - double d = distSqr(b->get_cart(), SGVec3d::fromGeod(pos)); + double d = distSqr(b->cart(), SGVec3d::fromGeod(pos)); // 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; + //std::cout << " range = " << sqrt(d) << std::endl; // cout << "elev = " << elev * SG_METER_TO_FEET // << " current->get_elev() = " << current->get_elev() << endl; double elev_ft = pos.getElevationFt(); - double delev = elev_ft - b->get_elev_ft(); + double delev = elev_ft - b->elevation(); // max range is the area under r = 2.4 * alt or r^2 = 4000^2 - alt^2 // whichever is smaller. The intersection point is 1538 ... @@ -236,7 +237,7 @@ static bool check_beacon_range( const SGGeod& pos, maxrange2 = 0.0; } maxrange2 *= SG_FEET_TO_METER * SG_FEET_TO_METER; // convert to meter^2 - // cout << "delev = " << delev << " maxrange = " << maxrange << endl; + //std::cout << "delev = " << delev << " maxrange = " << sqrt(maxrange2) << std::endl; // match up to twice the published range so we can model // reduced signal strength @@ -247,10 +248,18 @@ static bool check_beacon_range( const SGGeod& pos, } } +class BeaconFilter : public FGPositioned::Filter +{ +public: + virtual bool pass(FGPositioned* aPos) const + { + return (aPos->type() >= FGPositioned::OM) && (aPos->type() <= FGPositioned::IM); + } +}; + // Update current nav/adf radio stations based on current postition void FGMarkerBeacon::search() { - // reset search time _time_before_search_sec = 1.0; @@ -264,14 +273,10 @@ void FGMarkerBeacon::search() // Beacons. //////////////////////////////////////////////////////////////////////// - // get closest marker beacon - FGNavRecord *b - = globals->get_mkrlist()->findClosest( pos.getLongitudeRad(), - pos.getLatitudeRad(), - pos.getElevationM() ); - - // cout << "marker beacon = " << b << " (" << b->get_type() << ")" << endl; - + // get closest marker beacon - within a 1nm cutoff + BeaconFilter filter; + FGPositionedRef b = FGPositioned::findClosest(pos, 1.0, &filter); + fgMkrBeacType beacon_type = NOBEACON; bool inrange = false; if ( b != NULL ) { @@ -282,8 +287,7 @@ void FGMarkerBeacon::search() } else if ( b->type() == FGPositioned::IM ) { beacon_type = INNER; } - inrange = check_beacon_range( pos, b ); - // cout << " inrange = " << inrange << endl; + inrange = check_beacon_range( pos, b.ptr() ); } outer_marker = middle_marker = inner_marker = false; diff --git a/src/Instrumentation/navradio.cxx b/src/Instrumentation/navradio.cxx index 1b870dd1a..b4455be10 100644 --- a/src/Instrumentation/navradio.cxx +++ b/src/Instrumentation/navradio.cxx @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -764,10 +765,8 @@ void FGNavRadio::search() _time_before_search_sec = 1.0; // cache values locally for speed - double lon = lon_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS; - double lat = lat_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS; - double elev = alt_node->getDoubleValue() * SG_FEET_TO_METER; - + SGGeod pos = SGGeod::fromDegFt(lon_node->getDoubleValue(), + lat_node->getDoubleValue(), alt_node->getDoubleValue()); FGNavRecord *nav = NULL; FGNavRecord *loc = NULL; FGNavRecord *dme = NULL; @@ -778,11 +777,11 @@ void FGNavRadio::search() //////////////////////////////////////////////////////////////////////// double freq = freq_node->getDoubleValue(); - nav = globals->get_navlist()->findByFreq(freq, lon, lat, elev); - dme = globals->get_dmelist()->findByFreq(freq, lon, lat, elev); + nav = globals->get_navlist()->findByFreq(freq, pos); + dme = globals->get_dmelist()->findByFreq(freq, pos); if ( nav == NULL ) { - loc = globals->get_loclist()->findByFreq(freq, lon, lat, elev); - gs = globals->get_gslist()->findByFreq(freq, lon, lat, elev); + loc = globals->get_loclist()->findByFreq(freq, pos); + gs = globals->get_gslist()->findByFreq(freq, pos); } string nav_id = ""; @@ -799,7 +798,7 @@ void FGNavRadio::search() while ( target_radial > 360.0 ) { target_radial -= 360.0; } loc_lon = loc->get_lon(); loc_lat = loc->get_lat(); - nav_xyz = loc->get_cart(); + nav_xyz = loc->cart(); last_nav_id = nav_id; last_nav_vor = false; loc_node->setBoolValue( true ); @@ -811,7 +810,7 @@ void FGNavRadio::search() nav_elev = gs->get_elev_ft(); int tmp = (int)(gs->get_multiuse() / 1000.0); target_gs = (double)tmp / 100.0; - gs_xyz = gs->get_cart(); + gs_xyz = gs->cart(); // derive GS baseline (perpendicular to the runay // along the ground) @@ -884,10 +883,10 @@ void FGNavRadio::search() nav_elev = nav->get_elev_ft(); twist = nav->get_multiuse(); range = nav->get_range(); - effective_range = adjustNavRange(nav_elev, elev, range); + effective_range = adjustNavRange(nav_elev, pos.getElevationM(), range); target_gs = 0.0; target_radial = sel_radial_node->getDoubleValue(); - nav_xyz = nav->get_cart(); + nav_xyz = nav->cart(); if ( globals->get_soundmgr()->exists( nav_fx_name ) ) { globals->get_soundmgr()->remove( nav_fx_name ); diff --git a/src/Instrumentation/tacan.cxx b/src/Instrumentation/tacan.cxx index 59066c453..92bb7df0e 100755 --- a/src/Instrumentation/tacan.cxx +++ b/src/Instrumentation/tacan.cxx @@ -293,7 +293,7 @@ TACAN::search (double frequency_mhz, double longitude_rad, if ( freq_valid ) { - string str1( mobile_tacan->get_name() ); + string str1( mobile_tacan->name() ); SGPropertyNode * branch = fgGetNode("ai/models", true); vector carrier = branch->getChildren("carrier"); @@ -315,7 +315,7 @@ TACAN::search (double frequency_mhz, double longitude_rad, _mobile_elevation_ft = mobile_tacan->get_elev_ft(); _mobile_range_nm = mobile_tacan->get_range(); _mobile_bias = mobile_tacan->get_multiuse(); - _mobile_name = mobile_tacan->get_name(); + _mobile_name = mobile_tacan->name(); _mobile_ident = mobile_tacan->get_trans_ident(); _mobile_valid = true; SG_LOG( SG_INSTR, SG_DEBUG, " carrier transmitter valid " << _mobile_valid ); @@ -353,7 +353,7 @@ TACAN::search (double frequency_mhz, double longitude_rad, _mobile_elevation_ft = tanker[i]->getDoubleValue("position/altitude-ft"); _mobile_range_nm = mobile_tacan->get_range(); _mobile_bias = mobile_tacan->get_multiuse(); - _mobile_name = mobile_tacan->get_name(); + _mobile_name = mobile_tacan->name(); _mobile_ident = mobile_tacan->get_trans_ident(); _mobile_valid = true; SG_LOG( SG_INSTR, SG_DEBUG, " tanker transmitter valid " << _mobile_valid ); @@ -392,7 +392,7 @@ TACAN::search (double frequency_mhz, double longitude_rad, _mobile_elevation_ft = mp_tanker[i]->getDoubleValue("position/altitude-ft"); _mobile_range_nm = mobile_tacan->get_range(); _mobile_bias = mobile_tacan->get_multiuse(); - _mobile_name = mobile_tacan->get_name(); + _mobile_name = mobile_tacan->name(); _mobile_ident = mobile_tacan->get_trans_ident(); _mobile_valid = true; @@ -415,19 +415,18 @@ TACAN::search (double frequency_mhz, double longitude_rad, } // try the TACAN/VORTAC list next - FGNavRecord *tacan - = globals->get_tacanlist()->findByFreq( frequency_mhz, longitude_rad, - latitude_rad, altitude_m); + FGNavRecord *tacan = globals->get_tacanlist()->findByFreq( frequency_mhz, + SGGeod::fromRadM(longitude_rad, latitude_rad, altitude_m)); _transmitter_valid = (tacan != NULL); if ( _transmitter_valid ) { SG_LOG( SG_INSTR, SG_DEBUG, "transmitter valid " << _transmitter_valid ); - _transmitter_pos = tacan->get_pos(); + _transmitter_pos = tacan->geod(); _transmitter_range_nm = tacan->get_range(); _transmitter_bias = tacan->get_multiuse(); - _transmitter_name = tacan->get_name(); + _transmitter_name = tacan->name(); _name_node->setStringValue(_transmitter_name.c_str()); _transmitter_ident = tacan->get_trans_ident(); _ident_node->setStringValue(_transmitter_ident.c_str()); diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index 4dd8fdcf8..2bb9b477e 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -102,6 +102,7 @@ #include #include #include +#include #include #include #include @@ -974,7 +975,6 @@ fgInitNav () FGNavList *loclist = new FGNavList; FGNavList *gslist = new FGNavList; FGNavList *dmelist = new FGNavList; - FGNavList *mkrlist = new FGNavList; FGNavList *tacanlist = new FGNavList; FGNavList *carrierlist = new FGNavList; FGTACANList *channellist = new FGTACANList; @@ -983,12 +983,11 @@ fgInitNav () globals->set_loclist( loclist ); globals->set_gslist( gslist ); globals->set_dmelist( dmelist ); - globals->set_mkrlist( mkrlist ); globals->set_tacanlist( tacanlist ); globals->set_carrierlist( carrierlist ); globals->set_channellist( channellist ); - if ( !fgNavDBInit(navlist, loclist, gslist, dmelist, mkrlist, tacanlist, carrierlist, channellist) ) { + if ( !fgNavDBInit(navlist, loclist, gslist, dmelist, tacanlist, carrierlist, channellist) ) { SG_LOG( SG_GENERAL, SG_ALERT, "Problems loading one or more navigational database" ); } diff --git a/src/Main/globals.cxx b/src/Main/globals.cxx index 8cf9d171d..1bcbbea67 100644 --- a/src/Main/globals.cxx +++ b/src/Main/globals.cxx @@ -104,7 +104,6 @@ FGGlobals::FGGlobals() : loclist( NULL ), gslist( NULL ), dmelist( NULL ), - mkrlist( NULL ), tacanlist( NULL ), carrierlist( NULL ), channellist( NULL ), @@ -155,7 +154,6 @@ FGGlobals::~FGGlobals() delete loclist; delete gslist; delete dmelist; - delete mkrlist; delete tacanlist; delete carrierlist; delete channellist; diff --git a/src/Main/globals.hxx b/src/Main/globals.hxx index 64291971f..4b21c77f8 100644 --- a/src/Main/globals.hxx +++ b/src/Main/globals.hxx @@ -183,7 +183,6 @@ private: FGNavList *loclist; FGNavList *gslist; FGNavList *dmelist; - FGNavList *mkrlist; FGNavList *tacanlist; FGNavList *carrierlist; FGTACANList *channellist; @@ -331,8 +330,6 @@ public: inline void set_tacanlist( FGNavList *n ) { tacanlist = n; } inline FGNavList *get_carrierlist() const { return carrierlist; } inline void set_carrierlist( FGNavList *n ) { carrierlist = n; } - inline FGNavList *get_mkrlist() const { return mkrlist; } - inline void set_mkrlist( FGNavList *n ) { mkrlist = n; } inline FGTACANList *get_channellist() const { return channellist; } inline void set_channellist( FGTACANList *c ) { channellist = c; } diff --git a/src/Navaids/navdb.cxx b/src/Navaids/navdb.cxx index dc95774e4..40f487c5c 100644 --- a/src/Navaids/navdb.cxx +++ b/src/Navaids/navdb.cxx @@ -31,10 +31,12 @@ #include #include #include +#include #include #include #include "navrecord.hxx" +#include "navlist.hxx" #include "navdb.hxx" #include "Main/globals.hxx" @@ -43,7 +45,7 @@ using std::string; // load and initialize the navigational databases bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist, - FGNavList *dmelist, FGNavList *mkrlist, + FGNavList *dmelist, FGNavList *tacanlist, FGNavList *carrierlist, FGTACANList *channellist) { @@ -97,14 +99,14 @@ bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist, case FGPositioned::OM: case FGPositioned::MM: case FGPositioned::IM: - mkrlist->add(r); + // no need to add this to a list, never searched by frequency break; case FGPositioned::DME: { dmelist->add(r); - string::size_type loc1= r->get_name().find( "TACAN", 0 ); - string::size_type loc2 = r->get_name().find( "VORTAC", 0 ); + string::size_type loc1= r->name().find( "TACAN", 0 ); + string::size_type loc2 = r->name().find( "VORTAC", 0 ); if( loc1 != string::npos || loc2 != string::npos) { tacanlist->add(r); diff --git a/src/Navaids/navdb.hxx b/src/Navaids/navdb.hxx index cd524300f..87e510825 100644 --- a/src/Navaids/navdb.hxx +++ b/src/Navaids/navdb.hxx @@ -26,14 +26,13 @@ #include -#include -#include "navlist.hxx" -#include "fixlist.hxx" +class FGNavList; +class FGTACANList; // load and initialize the navigational databases bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist, - FGNavList *dmelist, FGNavList *mkrbeacons, + FGNavList *dmelist, FGNavList *tacanlist, FGNavList *carrierlist, FGTACANList *channellist ); diff --git a/src/Navaids/navlist.cxx b/src/Navaids/navlist.cxx index eb2ef38ef..66d990d5c 100644 --- a/src/Navaids/navlist.cxx +++ b/src/Navaids/navlist.cxx @@ -26,20 +26,12 @@ #endif #include -#include #include +#include #include "navlist.hxx" - -// Return true if the nav record matches the type -static bool isTypeMatch(const FGNavRecord* n, fg_nav_types type) -{ - if (type == FG_NAV_ANY) return true; - return type == n->type(); -} - - +using std::string; // FGNavList ------------------------------------------------------------------ @@ -50,7 +42,6 @@ FGNavList::FGNavList( void ) FGNavList::~FGNavList( void ) { - navaids_by_tile.erase( navaids_by_tile.begin(), navaids_by_tile.end() ); nav_list_type navlist = navaids.begin()->second; navaids.erase( navaids.begin(), navaids.end() ); } @@ -63,133 +54,55 @@ bool FGNavList::init() // since we're using an SGSharedPointer nav_list_type navlist = navaids.begin()->second; navaids.erase( navaids.begin(), navaids.end() ); - navaids_by_tile.erase( navaids_by_tile.begin(), navaids_by_tile.end() ); - ident_navaids.erase( ident_navaids.begin(), ident_navaids.end() ); - return true; } - -// real add a marker beacon -static void real_add( nav_map_type &navmap, const int master_index, - FGNavRecord *n ) -{ - navmap[master_index].push_back( n ); -} - - -// front end for add a marker beacon -static void tile_add( nav_map_type &navmap, FGNavRecord *n ) -{ - double diff = 0; - - double lon = n->get_lon(); - double lat = n->get_lat(); - - int lonidx = (int)lon; - diff = lon - (double)lonidx; - if ( (lon < 0.0) && (fabs(diff) > SG_EPSILON) ) { - lonidx -= 1; - } - double lonfrac = lon - (double)lonidx; - lonidx += 180; - - int latidx = (int)lat; - diff = lat - (double)latidx; - if ( (lat < 0.0) && (fabs(diff) > SG_EPSILON) ) { - latidx -= 1; - } - double latfrac = lat - (double)latidx; - latidx += 90; - - int master_index = lonidx * 1000 + latidx; - // cout << "lonidx = " << lonidx << " latidx = " << latidx << " "; - // cout << "Master index = " << master_index << endl; - - // add to the actual bucket - real_add( navmap, master_index, n ); - - // if we are close to the edge, add to adjacent buckets so we only - // have to search one bucket at run time - - // there are 8 cases since there are 8 adjacent tiles - - if ( lonfrac < 0.2 ) { - real_add( navmap, master_index - 1000, n ); - if ( latfrac < 0.2 ) { - real_add( navmap, master_index - 1000 - 1, n ); - } else if ( latfrac > 0.8 ) { - real_add( navmap, master_index - 1000 + 1, n ); - } - } else if ( lonfrac > 0.8 ) { - real_add( navmap, master_index + 1000, n ); - if ( latfrac < 0.2 ) { - real_add( navmap, master_index + 1000 - 1, n ); - } else if ( latfrac > 0.8 ) { - real_add( navmap, master_index + 1000 + 1, n ); - } - } else if ( latfrac < 0.2 ) { - real_add( navmap, master_index - 1, n ); - } else if ( latfrac > 0.8 ) { - real_add( navmap, master_index + 1, n ); - } -} - - // add an entry to the lists bool FGNavList::add( FGNavRecord *n ) { navaids[n->get_freq()].push_back(n); - ident_navaids[n->get_ident()].push_back(n); - tile_add( navaids_by_tile, n ); return true; } -FGNavRecord *FGNavList::findByFreq( double freq, double lon, double lat, double elev ) +FGNavRecord *FGNavList::findByFreq( double freq, const SGGeod& position) { const nav_list_type& stations = navaids[(int)(freq*100.0 + 0.5)]; - - SGGeod geod = SGGeod::fromRadM(lon, lat, elev); - SGVec3d aircraft = SGVec3d::fromGeod(geod); SG_LOG( SG_INSTR, SG_DEBUG, "findbyFreq " << freq << " size " << stations.size() ); - - return findNavFromList( aircraft, stations ); + return findNavFromList( position, stations ); } - -FGNavRecord *FGNavList::findByIdent( const char* ident, - const double lon, const double lat ) +class VORNDBFilter : public FGPositioned::Filter { - const nav_list_type& stations = ident_navaids[ident]; - SGGeod geod = SGGeod::fromRad(lon, lat); - SGVec3d aircraft = SGVec3d::fromGeod(geod); - return findNavFromList( aircraft, stations ); -} - - - +public: + virtual bool pass(FGPositioned* aPos) const + { + return (aPos->type() == FGPositioned::VOR) || (aPos->type() == FGPositioned::NDB); + } +}; // Given an Ident and optional freqency, return the first matching // station. -FGNavRecord *FGNavList::findByIdentAndFreq( const char* ident, const double freq ) +FGNavRecord *FGNavList::findByIdentAndFreq(const string& ident, const double freq ) { - nav_list_type stations = ident_navaids[ident]; - SG_LOG( SG_INSTR, SG_DEBUG, "findByIdent " << ident<< " size " << stations.size() ); - 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); - nav_list_const_iterator it, end = stations.end(); - for ( it = stations.begin(); it != end; ++it ) { - if ( f == (*it)->get_freq() ) { - return (*it); - } - } - } else if (!stations.empty()) { - return stations[0]; + FGPositionedRef cur; + VORNDBFilter filter; + cur = FGPositioned::findNextWithPartialId(cur, ident, &filter); + + if (freq <= 0.0) { + return static_cast(cur.ptr()); // might be null + } + + int f = (int)(freq*100.0 + 0.5); + while (cur) { + FGNavRecord* nav = static_cast(cur.ptr()); + if (nav->get_freq() == f) { + return nav; } + + cur = FGPositioned::findNextWithPartialId(cur, ident, &filter); + } - return NULL; + return NULL; } // LOC, ILS, GS, and DME antenna's could potentially be @@ -203,7 +116,7 @@ FGNavRecord *FGNavList::findByIdentAndFreq( const char* ident, const double freq // directional atennas and only when there is a chance it is // the closest station.) -static bool penaltyForNav(FGNavRecord* aNav, const SGVec3d &aPos) +static bool penaltyForNav(FGNavRecord* aNav, const SGGeod &aGeod) { switch (aNav->type()) { case FGPositioned::ILS: @@ -224,34 +137,31 @@ static bool penaltyForNav(FGNavRecord* aNav, const SGVec3d &aPos) hdg_deg = aNav->get_multiuse(); } - double az1 = 0.0, az2 = 0.0, s = 0.0; - SGGeod geod = SGGeod::fromCart(aPos); - geo_inverse_wgs_84( geod, aNav->geod(), &az1, &az2, &s); + double az1, az2, s; + SGGeodesy::inverse(aGeod, aNav->geod(), az1, az2, s); az1 = az1 - hdg_deg; - - if ( az1 > 180.0) az1 -= 360.0; - if ( az1 < -180.0) az1 += 360.0; - + SG_NORMALIZE_RANGE(az1, -180.0, 180.0); return fabs(az1) > 90.0; } // Given a point and a list of stations, return the closest one to the // specified point. -FGNavRecord *FGNavList::findNavFromList( const SGVec3d &aircraft, +FGNavRecord *FGNavList::findNavFromList( const SGGeod &aircraft, const nav_list_type &stations ) { FGNavRecord *nav = NULL; double d2; // in meters squared double min_dist = FG_NAV_MAX_RANGE*SG_NM_TO_METER*FG_NAV_MAX_RANGE*SG_NM_TO_METER; - + SGVec3d aircraftCart = SGVec3d::fromGeod(aircraft); + nav_list_const_iterator it; nav_list_const_iterator end = stations.end(); // find the closest station within a sensible range (FG_NAV_MAX_RANGE) for ( it = stations.begin(); it != end; ++it ) { FGNavRecord *station = *it; // cout << "testing " << current->get_ident() << endl; - d2 = distSqr(station->get_cart(), aircraft); + d2 = distSqr(station->cart(), aircraftCart); if ( d2 < min_dist && penaltyForNav(station, aircraft)) { double dist = sqrt(d2); @@ -267,69 +177,6 @@ FGNavRecord *FGNavList::findNavFromList( const SGVec3d &aircraft, return nav; } - -// returns the closest entry to the give lon/lat/elev -FGNavRecord *FGNavList::findClosest( double lon_rad, double lat_rad, - double elev_m, fg_nav_types type) -{ - FGNavRecord *result = NULL; - double diff; - - double lon_deg = lon_rad * SG_RADIANS_TO_DEGREES; - double lat_deg = lat_rad * SG_RADIANS_TO_DEGREES; - int lonidx = (int)lon_deg; - diff = lon_deg - (double)lonidx; - if ( (lon_deg < 0.0) && (fabs(diff) > SG_EPSILON) ) { - lonidx -= 1; - } - lonidx += 180; - - int latidx = (int)lat_deg; - diff = lat_deg - (double)latidx; - if ( (lat_deg < 0.0) && (fabs(diff) > SG_EPSILON) ) { - latidx -= 1; - } - latidx += 90; - - int master_index = lonidx * 1000 + latidx; - - const nav_list_type& navs = navaids_by_tile[ master_index ]; - // cout << "Master index = " << master_index << endl; - // cout << "beacon search length = " << beacons.size() << endl; - - nav_list_const_iterator current = navs.begin(); - nav_list_const_iterator last = navs.end(); - - SGGeod geod = SGGeod::fromRadM(lon_rad, lat_rad, elev_m); - SGVec3d aircraft = SGVec3d::fromGeod(geod); - - double min_dist = 999999999.0; - - for ( ; current != last ; ++current ) { - if(isTypeMatch(*current, type)) { - // cout << " testing " << (*current)->get_ident() << endl; - - double d = distSqr((*current)->get_cart(), aircraft); - // 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); - } - } - } - - // cout << "lon = " << lon << " lat = " << lat - // << " closest beacon = " << sqrt( min_dist ) << endl; - - return result; -} - // Given a frequency, return the first matching station. FGNavRecord *FGNavList::findStationByFreq( double freq ) { diff --git a/src/Navaids/navlist.hxx b/src/Navaids/navlist.hxx index 4f2bc5255..f54e5db93 100644 --- a/src/Navaids/navlist.hxx +++ b/src/Navaids/navlist.hxx @@ -26,9 +26,8 @@ #include -#include + #include -#include #include #include @@ -36,37 +35,28 @@ #include "navrecord.hxx" -using std::map; -using std::vector; -using std::string; - - +// forward decls +class SGGeod; // FGNavList ------------------------------------------------------------------ typedef SGSharedPtr nav_rec_ptr; -typedef vector < nav_rec_ptr > nav_list_type; +typedef std::vector < nav_rec_ptr > nav_list_type; typedef nav_list_type::iterator nav_list_iterator; typedef nav_list_type::const_iterator nav_list_const_iterator; -typedef map < int, nav_list_type > nav_map_type; +typedef std::map < int, nav_list_type > nav_map_type; typedef nav_map_type::iterator nav_map_iterator; 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; - - class FGNavList { nav_list_type carrierlist; nav_map_type navaids; - nav_map_type navaids_by_tile; - nav_ident_map_type ident_navaids; // Given a point and a list of stations, return the closest one to // the specified point. - FGNavRecord *findNavFromList( const SGVec3d &aircraft, + FGNavRecord *findNavFromList( const SGGeod &aircraft, const nav_list_type &stations ); public: @@ -82,27 +72,17 @@ public: /** Query the database for the specified station. It is assumed * that there will be multiple stations with matching frequencies - * so a position must be specified. Lon and lat are in radians, - * elev is in meters. + * so a position must be specified. */ - FGNavRecord *findByFreq( double freq, double lon, double lat, double elev ); - - // locate closest item in the DB matching the requested ident - FGNavRecord *findByIdent( const char* ident, const double lon, const double lat ); + FGNavRecord *findByFreq( double freq, const SGGeod& position); // Given an Ident and optional freqency, return the first matching // station. - FGNavRecord *findByIdentAndFreq( const char* ident, + FGNavRecord *findByIdentAndFreq( const std::string& ident, 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, - FGPositioned::Type type = FG_NAV_ANY ); - // given a frequency returns the first matching entry FGNavRecord *findStationByFreq( double frequency ); - - inline const nav_map_type& get_navaids() const { return navaids; } }; @@ -112,10 +92,9 @@ public: typedef SGSharedPtr tacan_rec_ptr; -typedef vector < tacan_rec_ptr > tacan_list_type; -typedef map < int, tacan_list_type > tacan_map_type; -typedef map < string, tacan_list_type > tacan_ident_map_type; - +typedef std::vector < tacan_rec_ptr > tacan_list_type; +typedef std::map < int, tacan_list_type > tacan_map_type; +typedef std::map < std::string, tacan_list_type > tacan_ident_map_type; class FGTACANList { @@ -135,7 +114,7 @@ public: bool add( FGTACANRecord *r ); // Given a TACAN Channel, return the appropriate frequency. - FGTACANRecord *findByChannel( const string& channel ); + FGTACANRecord *findByChannel( const std::string& channel ); }; diff --git a/src/Navaids/navrecord.cxx b/src/Navaids/navrecord.cxx index e85c43c4f..1e3800ae4 100644 --- a/src/Navaids/navrecord.cxx +++ b/src/Navaids/navrecord.cxx @@ -43,7 +43,7 @@ FGNavRecord::FGNavRecord(Type aTy, const std::string& aIdent, freq(aFreq), range(aRange), multiuse(aMultiuse), - name(aName), + _name(aName), serviceable(true), trans_ident(aIdent) { @@ -77,12 +77,6 @@ FGNavRecord::FGNavRecord(Type aTy, const std::string& aIdent, } -SGVec3d FGNavRecord::get_cart() const -{ - return SGVec3d::fromGeod(geod()); -} - - static FGPositioned::Type mapRobinTypeToFGPType(int aTy) { @@ -100,7 +94,7 @@ mapRobinTypeToFGPType(int aTy) case 13: return FGPositioned::DME; case 99: return FGPositioned::INVALID; // end-of-file code default: - throw sg_range_exception("Got a nav.dat type we don't recgonize", "FGNavRecord::createFromStream"); + throw sg_range_exception("Got a nav.dat type we don't recognize", "FGNavRecord::createFromStream"); } } @@ -117,7 +111,7 @@ FGNavRecord* FGNavRecord::createFromStream(std::istream& aStream) double lat, lon, elev_ft, multiuse; int freq, range; - std::string apt_id, name, ident; + std::string name, ident; aStream >> lat >> lon >> elev_ft >> freq >> range >> multiuse >> ident; getline(aStream, name); @@ -127,6 +121,12 @@ FGNavRecord* FGNavRecord::createFromStream(std::istream& aStream) freq *= 100; } + // ensure marker beacons are anonymous, so they don't get added to the + // name index + if ((type >= OM) && (type <= IM)) { + ident.clear(); + } + FGNavRecord* result = new FGNavRecord(type, ident, simgear::strutils::strip(name), SGGeod::fromDegFt(lon, lat, elev_ft), freq, range, multiuse); @@ -136,19 +136,29 @@ FGNavRecord* FGNavRecord::createFromStream(std::istream& aStream) void FGNavRecord::initAirportRelation() { - if (type() < ILS || type() > IM) { + if ((type() < ILS) || (type() > IM)) { return; // not airport-located } - vector parts = simgear::strutils::split(name); - apt_id = parts[0]; - const FGAirport* apt = fgFindAirportID(apt_id); - - if (!apt) { - SG_LOG(SG_GENERAL, SG_WARN, "navaid " << ident() << " associated with bogus airport ID:" << apt_id); + vector parts = simgear::strutils::split(_name); + if (parts.size() < 2) { + SG_LOG(SG_GENERAL, SG_WARN, "navaid has malformed name:" << _name); return; } + const FGAirport* apt = fgFindAirportID(parts[0]); + + if (!apt) { + SG_LOG(SG_GENERAL, SG_WARN, "navaid " << _name << " associated with bogus airport ID:" << parts[0]); + return; + } + + runway = apt->getRunwayByIdent(parts[1]); + if (!runway) { + SG_LOG(SG_GENERAL, SG_WARN, "navaid " << _name << " associated with bogus runway ID:" << parts[1]); + return; + } + // fudge elevation to the field elevation if it's not specified if (fabs(elevation()) < 0.01) { mPosition.setElevationFt(apt->getElevation()); @@ -160,16 +170,8 @@ void FGNavRecord::initAirportRelation() return; } - if (parts.size() < 2) { - SG_LOG(SG_GENERAL, SG_ALERT, "can't parse navaid " << ident() - << " name for airport/runway:" << name); - return; - } - - double threshold - = fgGetDouble( "/sim/navdb/localizers/auto-align-threshold-deg", - 5.0 ); - FGRunway* runway = apt->getRunwayByIdent(parts[1]); + double threshold + = fgGetDouble( "/sim/navdb/localizers/auto-align-threshold-deg", 5.0 ); alignLocaliserWithRunway(runway, threshold); } } diff --git a/src/Navaids/navrecord.hxx b/src/Navaids/navrecord.hxx index 55a02af7e..57c199d6c 100644 --- a/src/Navaids/navrecord.hxx +++ b/src/Navaids/navrecord.hxx @@ -53,9 +53,8 @@ class FGNavRecord : public FGPositioned // (degrees) or localizer heading // (degrees) or dme bias (nm) - std::string name; // verbose name in nav database - std::string apt_id; // corresponding airport id - + std::string _name; // verbose name in nav database + FGRunway* runway; bool serviceable; // for failure modeling std::string trans_ident; // for failure modeling @@ -78,23 +77,18 @@ public: inline double get_lon() const { return longitude(); } // degrees inline double get_lat() const { return latitude(); } // degrees inline double get_elev_ft() const { return elevation(); } - - const SGGeod& get_pos() const { return geod(); } - SGVec3d get_cart() const; - - Type get_fg_type() const { return type(); } - + inline int get_freq() const { return freq; } inline int get_range() const { return range; } inline double get_multiuse() const { return multiuse; } inline void set_multiuse( double m ) { multiuse = m; } inline const char *get_ident() const { return ident().c_str(); } - inline const std::string& get_name() const { return name; } - inline const std::string& get_apt_id() const { return apt_id; } + inline bool get_serviceable() const { return serviceable; } inline const char *get_trans_ident() const { return trans_ident.c_str(); } - + virtual const std::string& name() const + { return _name; } }; class FGTACANRecord : public SGReferenced { diff --git a/src/Navaids/positioned.cxx b/src/Navaids/positioned.cxx index 1f3575c9e..54bc57c4e 100644 --- a/src/Navaids/positioned.cxx +++ b/src/Navaids/positioned.cxx @@ -26,6 +26,8 @@ #include #include +#include + #include #include "positioned.hxx" @@ -199,20 +201,19 @@ class RangePredictate { public: RangePredictate(const SGGeod& aOrigin, double aRange) : - mOrigin(aOrigin), - mRange(aRange) + mOrigin(SGVec3d::fromGeod(aOrigin)), + mRangeSqr(aRange * aRange) { ; } bool operator()(const FGPositionedRef& aPos) { - double d, az1, az2; - SGGeodesy::inverse(aPos->geod(), mOrigin, az1, az2, d); - return (d > mRange); + double dSqr = distSqr(aPos->cart(), mOrigin); + return (dSqr > mRangeSqr); } private: - SGGeod mOrigin; - double mRange; + SGVec3d mOrigin; + double mRangeSqr; }; static void @@ -228,19 +229,18 @@ class DistanceOrdering { public: DistanceOrdering(const SGGeod& aPos) : - mPos(aPos) + mPos(SGVec3d::fromGeod(aPos)) { } bool operator()(const FGPositionedRef& a, const FGPositionedRef& b) const { - double dA, dB, az1, az2; - SGGeodesy::inverse(mPos, a->geod(), az1, az2, dA); - SGGeodesy::inverse(mPos, b->geod(), az1, az2, dB); + double dA = distSqr(a->cart(), mPos), + dB = distSqr(b->cart(), mPos); return dA < dB; } private: - SGGeod mPos; + SGVec3d mPos; }; static void @@ -273,17 +273,17 @@ namedFindClosest(const std::string& aIdent, const SGGeod& aOrigin, FGPositioned: double minDist = HUGE_VAL; FGPositionedRef result; NamedPositionedIndex::const_iterator it = range.first; - + SGVec3d cartOrigin(SGVec3d::fromGeod(aOrigin)); + for (; it != range.second; ++it) { if (aFilter && !aFilter->pass(range.first->second)) { continue; } // find distance - double d, az1, az2; - SGGeodesy::inverse(aOrigin, it->second->geod(), az1, az2, d); - if (d < minDist) { - minDist = d; + double d2 = distSqr(cartOrigin, it->second->cart()); + if (d2 < minDist) { + minDist = d2; result = it->second; } } @@ -328,11 +328,11 @@ spatialGetClosest(const SGGeod& aPos, unsigned int aN, double aCutoffNm, FGPosit result.insert(result.end(), hits.begin(), hits.end()); // append } // of outer loop + sortByDistance(aPos, result); if (result.size() > aN) { result.resize(aN); // truncate at requested number of matches } - sortByDistance(aPos, result); return result; } @@ -353,6 +353,7 @@ FGPositioned::FGPositioned(Type ty, const std::string& aIdent, const SGGeod& aPo FGPositioned::~FGPositioned() { + //std::cout << "destroying:" << mIdent << "/" << nameForType(mType) << std::endl; removeFromIndices(this); } @@ -362,12 +363,24 @@ FGPositioned::bucket() const return SGBucket(mPosition); } +SGVec3d +FGPositioned::cart() const +{ + return SGVec3d::fromGeod(mPosition); +} + const char* FGPositioned::nameForType(Type aTy) { switch (aTy) { + case RUNWAY: return "runway"; + case TAXIWAY: return "taxiway"; + case PARK_STAND: return "parking stand"; case FIX: return "fix"; case VOR: return "VOR"; case NDB: return "NDB"; + case ILS: return "ILS"; + case LOC: return "localiser"; + case GS: return "glideslope"; case OM: return "outer-marker"; case MM: return "middle-marker"; case IM: return "inner-marker"; @@ -375,6 +388,8 @@ const char* FGPositioned::nameForType(Type aTy) case HELIPORT: return "heliport"; case SEAPORT: return "seaport"; case WAYPOINT: return "waypoint"; + case DME: return "dme"; + case TACAN: return "tacan"; default: return "unknown"; } diff --git a/src/Navaids/positioned.hxx b/src/Navaids/positioned.hxx index ff3666290..1c275dcf4 100644 --- a/src/Navaids/positioned.hxx +++ b/src/Navaids/positioned.hxx @@ -82,6 +82,11 @@ public: const SGGeod& geod() const { return mPosition; } + /** + * Compute the cartesian position associated with this object + */ + SGVec3d cart() const; + SGBucket bucket() const; double latitude() const