X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FNavaids%2Fnavdb.cxx;h=4f7c10e7f8e89241e3d67d532ee6d7cfac6e0856;hb=2e6d7e111aa3681e764ba57dc5c03e595dea8422;hp=1c2d40a65c4d8cec9ef4682dd79e6f4fccc9870c;hpb=e35911e45a654b6bea455aac64f02bd6d4967a6a;p=flightgear.git diff --git a/src/Navaids/navdb.cxx b/src/Navaids/navdb.cxx index 1c2d40a65..4f7c10e7f 100644 --- a/src/Navaids/navdb.cxx +++ b/src/Navaids/navdb.cxx @@ -16,46 +16,97 @@ // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include -#include STL_STRING +#include #include - -#include -#include -#include
+#include +#include +#include +#include +#include #include "navrecord.hxx" +#include "navlist.hxx" #include "navdb.hxx" +#include
+#include +#include -SG_USING_STD( string ); +using std::string; +static FGPositioned::Type +mapRobinTypeToFGPType(int aTy) +{ + switch (aTy) { + // case 1: + case 2: return FGPositioned::NDB; + case 3: return FGPositioned::VOR; + case 4: return FGPositioned::ILS; + case 5: return FGPositioned::LOC; + case 6: return FGPositioned::GS; + case 12: + 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 recognize", "FGNavRecord::createFromStream"); + } +} + +static FGNavRecord* createNavFromStream(std::istream& aStream) +{ + int rawType; + aStream >> rawType; + if (aStream.eof() || (rawType == 99)) { + return NULL; // happens with, eg, carrier_nav.dat + } + + double lat, lon, elev_ft, multiuse; + int freq, range; + std::string name, ident; + aStream >> lat >> lon >> elev_ft >> freq >> range >> multiuse >> ident; + getline(aStream, name); + + SGGeod pos(SGGeod::fromDegFt(lon, lat, elev_ft)); + name = simgear::strutils::strip(name); + + if ((rawType >= 7) && (rawType <= 9)) { + // marker beacons use a different run-time class now + FGMarkerBeaconRecord::create(rawType, name, pos); + return NULL; // not a nav-record, but that's okay + } + + FGPositioned::Type type = mapRobinTypeToFGPType(rawType); + if (type == FGPositioned::INVALID) { + return NULL; + } + + // silently multiply adf frequencies by 100 so that adf + // vs. nav/loc frequency lookups can use the same code. + if (type == FGPositioned::NDB) { + freq *= 100; + } + + return new FGNavRecord(type, ident, name, pos, + freq, range, multiuse); +} // load and initialize the navigational databases -bool fgNavDBInit( FGAirportList *airports, - FGNavList *navlist, FGNavList *loclist, FGNavList *gslist, - FGNavList *dmelist, FGNavList *mkrlist, +bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist, + FGNavList *dmelist, FGNavList *tacanlist, FGNavList *carrierlist, FGTACANList *channellist) { SG_LOG(SG_GENERAL, SG_INFO, "Loading Navaid Databases"); - // SG_LOG(SG_GENERAL, SG_INFO, " VOR/NDB"); - // SGPath p_nav( globals->get_fg_root() ); - // p_nav.append( "Navaids/default.nav" ); - // navlist->init( p_nav ); - - // SG_LOG(SG_GENERAL, SG_INFO, " ILS and Marker Beacons"); - // beacons->init(); - // SGPath p_ils( globals->get_fg_root() ); - // p_ils.append( "Navaids/default.ils" ); - // ilslist->init( p_ils ); - SGPath path( globals->get_fg_root() ); path.append( "Navaids/nav.dat" ); @@ -70,78 +121,50 @@ bool fgNavDBInit( FGAirportList *airports, in >> skipeol; in >> skipeol; - -#ifdef __MWERKS__ - char c = 0; - while ( in.get(c) && c != '\0' ) { - in.putback(c); -#else - while ( ! in.eof() ) { -#endif - - FGNavRecord *r = new FGNavRecord; - in >> (*r); - if ( r->get_type() > 95 ) { - break; + while (!in.eof()) { + FGNavRecord *r = createNavFromStream(in); + if (!r) { + continue; + } + + switch (r->type()) { + case FGPositioned::NDB: + case FGPositioned::VOR: + navlist->add(r); + break; + + case FGPositioned::ILS: + case FGPositioned::LOC: + loclist->add(r); + break; + + case FGPositioned::GS: + gslist->add(r); + break; + + case FGPositioned::DME: + { + dmelist->add(r); + 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); } - /*cout << "id = " << r->get_ident() << endl; - cout << " type = " << r->get_type() << endl; - cout << " lon = " << r->get_lon() << endl; - cout << " lat = " << r->get_lat() << endl; - cout << " elev = " <get_elev_ft() << endl; - cout << " freq = " << r->get_freq() << endl; - cout << " range = " << r->get_range() << endl; - cout << " name = " << r->get_name() << endl << endl; */ + break; + } + + default: + throw sg_range_exception("got unsupported NavRecord type", "fgNavDBInit"); + } - // fudge elevation to the field elevation if it's not specified - if ( fabs(r->get_elev_ft()) < 0.01 && r->get_apt_id().length() ) { - // cout << r->get_type() << " " << r->get_apt_id() << " zero elev" - // << endl; - const FGAirport* a = airports->search( r->get_apt_id() ); - if ( a ) { - r->set_elev_ft( a->getElevation() ); - // cout << " setting to " << a.elevation << endl; - } - } - - if ( r->get_type() == 2 || r->get_type() == 3 ) { - // NDB=2, VOR=3 - navlist->add( r ); - } else if ( r->get_type() == 4 || r->get_type() == 5 ) { - // ILS=4, LOC(only)=5 - loclist->add( r ); - } else if ( r->get_type() == 6 ) { - // GS=6 - gslist->add( r ); - } else if ( r->get_type() == 7 || r->get_type() == 8 - || r->get_type() == 9 ) - { - // Marker Beacon = 7,8,9 - mkrlist->add( r ); - } else if ( r->get_type() == 12 ) { - // DME=12 - string str1( r->get_name() ); - unsigned int loc1= str1.find( "TACAN", 0 ); - unsigned int loc2 = str1.find( "VORTAC", 0 ); - - if( loc1 != string::npos || loc2 != string::npos ){ - //cout << " name = " << r->get_name() ; - //cout << " freq = " << r->get_freq() ; - tacanlist->add( r ); - } - - dmelist->add( r ); - - } - - in >> skipcomment; - } + in >> skipcomment; + } // of stream data loop // load the carrier navaids file string file, name; - path = ""; path = globals->get_fg_root() ; path.append( "Navaids/carrier_nav.dat" ); @@ -159,24 +182,13 @@ bool fgNavDBInit( FGAirportList *airports, //incarrier >> skipeol; //incarrier >> skipeol; -#ifdef __MWERKS__ - char c = 0; - while ( incarrier.get(c) && c != '\0' ) { - incarrier.putback(c); -#else while ( ! incarrier.eof() ) { -#endif - - FGNavRecord *r = new FGNavRecord; - incarrier >> (*r); - carrierlist->add ( r ); - /*cout << " carrier lon: "<< r->get_lon() ; - cout << " carrier lat: "<< r->get_lat() ; - cout << " freq: " << r->get_freq() ; - cout << " carrier name: "<< r->get_name() << endl;*/ - - //if ( r->get_type() > 95 ) { - // break;} + FGNavRecord *r = createNavFromStream(incarrier); + if (!r) { + continue; + } + + carrierlist->add (r); } // end while // end loading the carrier navaids file @@ -198,15 +210,7 @@ bool fgNavDBInit( FGAirportList *airports, // skip first line inchannel >> skipeol; - -#ifdef __MWERKS__ - char c = 0; - while ( inchannel.get(c) && c != '\0' ) { - in.putback(c); -#else while ( ! inchannel.eof() ) { -#endif - FGTACANRecord *r = new FGTACANRecord; inchannel >> (*r); channellist->add ( r ); @@ -222,93 +226,24 @@ bool fgNavDBInit( FGAirportList *airports, return true; } - -// Given a localizer record and it's corresponding runway record, -// adjust the localizer position so it is in perfect alignment with -// the runway. -static void update_loc_position( FGNavRecord *loc, FGRunway *rwy, - double threshold ) +FGRunway* getRunwayFromName(const std::string& aName) { - double hdg = rwy->_heading; - hdg += 180.0; - if ( hdg > 360.0 ) { - hdg -= 360.0; - } - - // calculate runway threshold point - double thresh_lat, thresh_lon, return_az; - geo_direct_wgs_84 ( 0.0, rwy->_lat, rwy->_lon, hdg, - rwy->_length/2.0 * SG_FEET_TO_METER, - &thresh_lat, &thresh_lon, &return_az ); - // cout << "Threshold = " << thresh_lat << "," << thresh_lon << endl; - - // calculate distance from threshold to localizer - double az1, az2, dist_m; - geo_inverse_wgs_84( 0.0, loc->get_lat(), loc->get_lon(), - thresh_lat, thresh_lon, - &az1, &az2, &dist_m ); - // cout << "Distance = " << dist_m << endl; - - // back project that distance along the runway center line - double nloc_lat, nloc_lon; - geo_direct_wgs_84 ( 0.0, thresh_lat, thresh_lon, hdg + 180.0, - dist_m, &nloc_lat, &nloc_lon, &return_az ); - // printf("New localizer = %.6f %.6f\n", nloc_lat, nloc_lon ); - - // sanity check, how far have we moved the localizer? - geo_inverse_wgs_84( 0.0, loc->get_lat(), loc->get_lon(), - nloc_lat, nloc_lon, - &az1, &az2, &dist_m ); - // cout << "Distance moved = " << dist_m << endl; - - // cout << "orig heading = " << loc->get_multiuse() << endl; - // cout << "new heading = " << rwy->_heading << endl; - - double hdg_diff = loc->get_multiuse() - rwy->_heading; - - // clamp to [-180.0 ... 180.0] - if ( hdg_diff < -180.0 ) { - hdg_diff += 360.0; - } else if ( hdg_diff > 180.0 ) { - hdg_diff -= 360.0; - } - - if ( fabs(hdg_diff) <= threshold ) { - loc->set_lat( nloc_lat ); - loc->set_lon( nloc_lon ); - loc->set_multiuse( rwy->_heading ); - } -} - - -// This routines traverses the localizer list and attempts to match -// each entry with it's corresponding runway. When it is successful, -// it then "moves" the localizer and updates it's heading so it -// *perfectly* aligns with the runway, but is still the same distance -// from the runway threshold. -void fgNavDBAlignLOCwithRunway( FGRunwayList *runways, FGNavList *loclist, - double threshold ) { - nav_map_type navmap = loclist->get_navaids(); - - nav_map_const_iterator freq = navmap.begin(); - while ( freq != navmap.end() ) { - nav_list_type locs = freq->second; - nav_list_const_iterator loc = locs.begin(); - while ( loc != locs.end() ) { - string name = (*loc)->get_name(); - string::size_type pos1 = name.find(" "); - string id = name.substr(0, pos1); - name = name.substr(pos1+1); - string::size_type pos2 = name.find(" "); - string rwy = name.substr(0, pos2); - - FGRunway r; - if ( runways->search(id, rwy, &r) ) { - update_loc_position( (*loc), &r, threshold ); - } - ++loc; - } - ++freq; - } + vector parts = simgear::strutils::split(aName); + if (parts.size() < 2) { + SG_LOG(SG_GENERAL, SG_WARN, "getRunwayFromName: malformed name:" << aName); + return NULL; + } + + const FGAirport* apt = fgFindAirportID(parts[0]); + if (!apt) { + SG_LOG(SG_GENERAL, SG_WARN, "navaid " << aName << " associated with bogus airport ID:" << parts[0]); + return NULL; + } + + if (!apt->hasRunwayWithIdent(parts[1])) { + SG_LOG(SG_GENERAL, SG_WARN, "navaid " << aName << " associated with bogus runway ID:" << parts[1]); + return NULL; + } + + return apt->getRunwayByIdent(parts[1]); } -