diff --git a/src/Airports/runways.cxx b/src/Airports/runways.cxx index 5c98af7ff..78c1c6db2 100644 --- a/src/Airports/runways.cxx +++ b/src/Airports/runways.cxx @@ -100,8 +100,8 @@ static string GetReverseRunwayNo(string rwyno) { if (( tmp == "L" || tmp == "R" || tmp == "C" ) || (rwyno.size() == 1)) { tmp = rwyno; rwyno = "0" + tmp; - SG_LOG( SG_GENERAL, SG_INFO, "Standardising rwy number from " << tmp - << " to " << rwyno ); + SG_LOG( SG_GENERAL, SG_INFO, + "Standardising rwy number from " << tmp << " to " << rwyno ); } char buf[4]; @@ -121,6 +121,9 @@ static string GetReverseRunwayNo(string rwyno) { } else if (rwyno.substr(2,1) == "C") { buf[2] = 'C'; buf[3] = '\0'; + } else if (rwyno.substr(2,1) == "T") { + buf[2] = 'T'; + buf[3] = '\0'; } else { SG_LOG(SG_GENERAL, SG_ALERT, "Unknown runway code " << rwyno << " passed to GetReverseRunwayNo(...)"); diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index 4e6988aff..a9c583d7a 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -1062,6 +1062,14 @@ fgInitNav () "Problems loading one or more navigational database" ); } + if ( fgGetBool("/sim/navdb/auto-align-localizers", true) ) { + // align all the localizers with their corresponding runways + // since data sources are good for cockpit navigation + // purposes, but not always to the error tolerances needed to + // exactly place these items. + fgNavDBAlignLOCwithRunway( runways, loclist ); + } + SG_LOG(SG_GENERAL, SG_INFO, " Fixes"); SGPath p_fix( globals->get_fg_root() ); p_fix.append( "Navaids/fix.dat" ); diff --git a/src/Navaids/navdb.cxx b/src/Navaids/navdb.cxx index 5ca43646e..f26791120 100644 --- a/src/Navaids/navdb.cxx +++ b/src/Navaids/navdb.cxx @@ -21,14 +21,20 @@ // $Id$ +#include + +#include STL_STRING + #include +#include #include
#include "navrecord.hxx" - #include "navdb.hxx" +SG_USING_STD( string ); + // load and initialize the navigational databases bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist, @@ -110,3 +116,80 @@ bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist, 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 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; + + loc->set_lat( nloc_lat ); + loc->set_lon( nloc_lon ); + loc->set_multiuse( rwy->heading ); + + // cout << "orig heading = " << loc->get_multiuse() << endl; + // cout << "new heading = " << rwy->heading << endl; +} + + +// 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 ) { + nav_map_type navmap = loclist->get_navaids(); + + nav_map_iterator freq = navmap.begin(); + while ( freq != navmap.end() ) { + nav_list_type locs = freq->second; + nav_list_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 ); + } + ++loc; + } + ++freq; + } +} diff --git a/src/Navaids/navdb.hxx b/src/Navaids/navdb.hxx index 4afc27e11..36f1bdc42 100644 --- a/src/Navaids/navdb.hxx +++ b/src/Navaids/navdb.hxx @@ -45,4 +45,12 @@ bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist, FGNavList *dmelist, FGNavList *mkrbeacons ); +// 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 ); + + #endif // _FG_NAVDB_HXX diff --git a/src/Navaids/navlist.hxx b/src/Navaids/navlist.hxx index aee404196..1298eddb2 100644 --- a/src/Navaids/navlist.hxx +++ b/src/Navaids/navlist.hxx @@ -61,7 +61,7 @@ class FGNavList { // Given a point and a list of stations, return the closest one to // the specified point. FGNavRecord *findNavFromList( const Point3D &aircraft, - const nav_list_type &stations ); + const nav_list_type &stations ); public: @@ -97,6 +97,7 @@ public: // returns the closest entry to the give lon/lat/elev FGNavRecord *findClosest( double lon_rad, double lat_rad, double elev_m ); + inline nav_map_type get_navaids() const { return navaids; } }; diff --git a/src/Navaids/navrecord.hxx b/src/Navaids/navrecord.hxx index 544d2d1aa..ce8fde82d 100644 --- a/src/Navaids/navrecord.hxx +++ b/src/Navaids/navrecord.hxx @@ -74,7 +74,9 @@ public: 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 double get_elev_ft() const { return elev_ft; } inline double get_x() const { return x; } inline double get_y() const { return y; } @@ -82,6 +84,7 @@ public: 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() { return ident.c_str(); } inline string get_name() { return name; } inline bool get_serviceable() { return serviceable; } @@ -127,8 +130,8 @@ operator >> ( istream& in, FGNavRecord& n ) n.freq *= 100; } - // Remove the space before the name - if ( n.name.substr(0,1) == " " ) { + // Remove any leading spaces before the name + while ( n.name.substr(0,1) == " " ) { n.name = n.name.erase(0,1); }