]> git.mxchange.org Git - flightgear.git/blobdiff - src/Navaids/navdb.cxx
gcc warning fixes
[flightgear.git] / src / Navaids / navdb.cxx
index 1c2d40a65c4d8cec9ef4682dd79e6f4fccc9870c..4f7c10e7f8e89241e3d67d532ee6d7cfac6e0856 100644 (file)
 //
 // 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 <simgear/compiler.h>
 
-#include STL_STRING
+#include <string>
 
 #include <simgear/debug/logstream.hxx>
-
-#include <Airports/runways.hxx>
-#include <Airports/simple.hxx>
-#include <Main/globals.hxx>
+#include <simgear/math/sg_geodesy.hxx>
+#include <simgear/misc/strutils.hxx>
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/structure/exception.hxx>
+#include <simgear/misc/sgstream.hxx>
 
 #include "navrecord.hxx"
+#include "navlist.hxx"
 #include "navdb.hxx"
+#include <Main/globals.hxx>
+#include <Navaids/markerbeacon.hxx>
+#include <Airports/simple.hxx>
 
-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 = " <<r->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<string> 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]);
 }
-