]> git.mxchange.org Git - flightgear.git/blobdiff - src/Navaids/navdb.cxx
Merge branch 'maint' into next
[flightgear.git] / src / Navaids / navdb.cxx
index 5ca43646e73af8039657b438c6f043aa73043f74..95f7f77eef15f1b72d1e4f32cefc360fa9331230 100644 (file)
@@ -2,7 +2,7 @@
 //
 // Written by Curtis Olson, started May 2004.
 //
-// Copyright (C) 2004  Curtis L. Olson - curt@flightgear.org
+// Copyright (C) 2004  Curtis L. Olson - http://www.flightgear.org/~curt
 //
 // This program is free software; you can redistribute it and/or
 // modify it under the terms of the GNU General Public License as
 //
 // 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/debug/logstream.hxx>
+#include <simgear/compiler.h>
 
-#include <Main/globals.hxx>
+#include <string>
 
-#include "navrecord.hxx"
+#include <simgear/debug/logstream.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"
 
+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::LOC;
+  case 5: return FGPositioned::ILS;
+  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( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist,
-                  FGNavList *dmelist, FGNavList *mkrlist )
+                  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" );
@@ -60,53 +121,130 @@ bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist,
     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 = " << n.get_ident() << endl;
-       cout << " type = " << n.get_type() << endl;
-       cout << " lon = " << n.get_lon() << endl;
-       cout << " lat = " << n.get_lat() << endl;
-       cout << " elev = " << n.get_elev() << endl;
-       cout << " freq = " << n.get_freq() << endl;
-       cout << " range = " << n.get_range() << endl << 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
-            dmelist->add( r );
-        }
-               
-        in >> skipcomment;
+        break;
+      }
+      
+      default:
+        throw sg_range_exception("got unsupported NavRecord type", "fgNavDBInit");
+      }
+
+      in >> skipcomment;
+    } // of stream data loop
+
+// load the carrier navaids file
+    
+    string file, name;
+    path = globals->get_fg_root() ;
+    path.append( "Navaids/carrier_nav.dat" );
+    
+    file = path.str();
+    SG_LOG( SG_GENERAL, SG_INFO, "opening file: " << path.str() );
+    
+    sg_gzifstream incarrier( path.str() );
+    
+    if ( !incarrier.is_open() ) {
+        SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << path.str() );
+        exit(-1);
     }
+    
+    // skip first two lines
+    //incarrier >> skipeol;
+    //incarrier >> skipeol;
+    
+    while ( ! incarrier.eof() ) {
+      FGNavRecord *r = createNavFromStream(incarrier);
+      if (!r) {
+        continue;
+      }
+      
+      carrierlist->add (r);
+    } // end while
+
+// end loading the carrier navaids file
+
+// load the channel/freqency file
+    string channel, freq;
+    path="";
+    path = globals->get_fg_root();
+    path.append( "Navaids/TACAN_freq.dat" );
+    
+    SG_LOG( SG_GENERAL, SG_INFO, "opening file: " << path.str() );
+        
+    sg_gzifstream inchannel( path.str() );
+    
+    if ( !inchannel.is_open() ) {
+        SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << path.str() );
+        exit(-1);
+    }
+    
+    // skip first line
+    inchannel >> skipeol;
+    while ( ! inchannel.eof() ) {
+        FGTACANRecord *r = new FGTACANRecord;
+        inchannel >> (*r);
+        channellist->add ( r );
+               //cout << "channel = " << r->get_channel() ;
+               //cout << " freq = " << r->get_freq() << endl;
+       
+    } // end while
+
+ // end ReadChanFile
 
-    // cout << "min freq = " << min << endl;
-    // cout << "max freq = " << max << endl;
 
     return true;
 }
+
+FGRunway* getRunwayFromName(const std::string& aName)
+{
+  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;
+  }
+  
+  FGRunway* runway = apt->getRunwayByIdent(parts[1]);
+  if (!runway) {
+    SG_LOG(SG_GENERAL, SG_WARN, "navaid " << aName << " associated with bogus runway ID:" << parts[1]);
+    return NULL;
+  }
+
+  return runway;
+}