]> git.mxchange.org Git - flightgear.git/commitdiff
Partial fix for #228: ambiguous navaid-names
authorTorsten Dreyer <Torsten@t3r.de>
Mon, 18 Jul 2011 09:09:43 +0000 (11:09 +0200)
committerTorsten Dreyer <Torsten@t3r.de>
Mon, 18 Jul 2011 09:09:43 +0000 (11:09 +0200)
This fixes at least the startup process.
If an ambigous fix name was presented with --vor=ID or --ndb=ID
present a list of matching records along with frequency and
position in the console to give the user the chance to pick
the correct one by adding the frequency with --vor-frequency=nnn.nn

It does not yes solve the issue when the user relocates using the
GUI dialog. This requires some GUI and Nasal hacking along with a
new Nasal helper function "navaidinfo".

src/Main/fg_init.cxx
src/Main/options.cxx
src/Navaids/navlist.cxx
src/Navaids/navlist.hxx

index 9fd101b65f7319b5296bf97dc727ff9615e0e34e..cc62744cd8c32c3b364d69549aae701a1f93d89d 100644 (file)
@@ -59,6 +59,7 @@
 #include <simgear/misc/sg_path.hxx>
 #include <simgear/misc/sg_dir.hxx>
 #include <simgear/misc/sgstream.hxx>
+#include <simgear/misc/strutils.hxx>
 
 #include <simgear/misc/interpolator.hxx>
 #include <simgear/scene/material/matlib.hxx>
@@ -996,18 +997,37 @@ static void fgSetDistOrAltFromGlideSlope() {
 
 
 // Set current_options lon/lat given an airport id and heading (degrees)
-static bool fgSetPosFromNAV( const string& id, const double& freq ) {
-    FGNavRecord *nav
-        = globals->get_navlist()->findByIdentAndFreq( id.c_str(), freq );
+static bool fgSetPosFromNAV( const string& id, const double& freq, FGPositioned::Type type ) {
 
-  if (!nav) {
-    SG_LOG( SG_GENERAL, SG_ALERT, "Failed to locate NAV = "
-                << id << ":" << freq );
-    return false;
-  }
-  
-  fgApplyStartOffset(nav->geod(), fgGetDouble("/sim/presets/heading-deg"));
-  return true;
+    const nav_list_type navlist
+        = globals->get_navlist()->findByIdentAndFreq( id.c_str(), freq, type );
+
+    if (navlist.size() == 0 ) {
+        SG_LOG( SG_GENERAL, SG_ALERT, "Failed to locate NAV = "
+            << id << ":" << freq );
+        return false;
+    }
+
+    if( navlist.size() > 1 ) {
+        ostringstream buf;
+        buf << "Ambigous NAV-ID: '" << id << "'. Specify id and frequency. Available stations:" << endl;
+        for( nav_list_type::const_iterator it = navlist.begin(); it != navlist.end(); ++it ) {
+            // NDB stored in kHz, VOR stored in MHz * 100 :-P
+            double factor = (*it)->type() == FGPositioned::NDB ? 1.0 : 1/100.0;
+            string unit = (*it)->type() == FGPositioned::NDB ? "kHz" : "MHz";
+            buf << (*it)->ident() << " "
+                << setprecision(5) << (double)((*it)->get_freq() * factor) << " "
+                << (*it)->get_lat() << "/" << (*it)->get_lon()
+                << endl;
+        }
+
+        SG_LOG( SG_GENERAL, SG_ALERT, buf.str() );
+        return false;
+    }
+
+    FGNavRecord *nav = navlist[0];
+    fgApplyStartOffset(nav->geod(), fgGetDouble("/sim/presets/heading-deg"));
+    return true;
 }
 
 // Set current_options lon/lat given an aircraft carrier id
@@ -1219,14 +1239,14 @@ bool fgInitPosition() {
 
     if ( !set_pos && !vor.empty() ) {
         // a VOR is requested
-        if ( fgSetPosFromNAV( vor, vor_freq ) ) {
+        if ( fgSetPosFromNAV( vor, vor_freq, FGPositioned::VOR ) ) {
             set_pos = true;
         }
     }
 
     if ( !set_pos && !ndb.empty() ) {
         // an NDB is requested
-        if ( fgSetPosFromNAV( ndb, ndb_freq ) ) {
+        if ( fgSetPosFromNAV( ndb, ndb_freq, FGPositioned::NDB ) ) {
             set_pos = true;
         }
     }
index 9e1b5c55b4aa85e73f67f9e6fb4183cc82becf62..00ace6e4ba7510cf9e8522a391fe02d7ed81c77d 100644 (file)
@@ -59,7 +59,6 @@
 #include <Main/viewer.hxx>
 #include <Environment/presets.hxx>
 
-#include <simgear/version.h>
 #include <osg/Version>
 
 using std::string;
@@ -70,6 +69,7 @@ using std::endl;
 
 #if defined( HAVE_VERSION_H ) && HAVE_VERSION_H
 #  include <Include/version.h>
+#  include <simgear/version.h>
 #else
 #  include <Include/no_version.h>
 #endif
@@ -1341,7 +1341,9 @@ struct OptionDesc {
     {"airport",                      true,  OPTION_STRING, "/sim/presets/airport-id", false, "", 0 },
     {"runway",                       true,  OPTION_FUNC,   "", false, "", fgOptRunway },
     {"vor",                          true,  OPTION_FUNC,   "", false, "", fgOptVOR },
+    {"vor-frequency",                true,  OPTION_DOUBLE, "/sim/presets/vor-freq", false, "", fgOptVOR },
     {"ndb",                          true,  OPTION_FUNC,   "", false, "", fgOptNDB },
+    {"ndb-frequency",                true,  OPTION_DOUBLE, "/sim/presets/ndb-freq", false, "", fgOptVOR },
     {"carrier",                      true,  OPTION_FUNC,   "", false, "", fgOptCarrier },
     {"parkpos",                      true,  OPTION_FUNC,   "", false, "", fgOptParkpos },
     {"fix",                          true,  OPTION_FUNC,   "", false, "", fgOptFIX },
index bbe3eb424d85c1971616132c17ed42858c5d31e5..6bbf59fa3c7f1475543d875b49391246f5a16b7b 100644 (file)
@@ -33,6 +33,8 @@
 
 #include <Airports/runways.hxx>
 
+#include <algorithm>
+
 using std::string;
 
 // FGNavList ------------------------------------------------------------------
@@ -73,41 +75,74 @@ FGNavRecord *FGNavList::findByFreq( double freq, const SGGeod& position)
     return findNavFromList( position, stations );
 }
 
-class VORNDBFilter : public FGPositioned::Filter
+class TypeFilter : public FGPositioned::Filter
 {
 public:
+    TypeFilter( const FGPositioned::Type mintype, const FGPositioned::Type maxtype ) : _mintype(mintype), _maxtype(maxtype) {}
+
   virtual FGPositioned::Type minType() const {
-    return FGPositioned::VOR;
+    return _mintype;
   }
 
   virtual FGPositioned::Type maxType()  const {
-    return FGPositioned::NDB;
+    return _maxtype;
   }
+private:
+    FGPositioned::Type _mintype;
+    FGPositioned::Type _maxtype;
 };
 
 // Given an Ident and optional freqency, return the first matching
 // station.
-FGNavRecord *FGNavList::findByIdentAndFreq(const string& ident, const double freq )
+const nav_list_type FGNavList::findByIdentAndFreq(const string& ident, const double freq, const FGPositioned::Type type )
 {
   FGPositionedRef cur;
-  VORNDBFilter filter;
+  TypeFilter filter( 
+      type == FGPositioned::INVALID ? FGPositioned::VOR : type,
+      type == FGPositioned::INVALID ? FGPositioned::NDB : type );
+  nav_list_type reply;
+
   cur = FGPositioned::findNextWithPartialId(cur, ident, &filter);
   
-  if (freq <= 0.0) {
-    return static_cast<FGNavRecord*>(cur.ptr()); // might be null
-  }
-  
   int f = (int)(freq*100.0 + 0.5);
   while (cur) {
     FGNavRecord* nav = static_cast<FGNavRecord*>(cur.ptr());
-    if (nav->get_freq() == f) {
-      return nav;
+    if ( f <= 0.0 || nav->get_freq() == f) {
+        reply.push_back( nav );
     }
     
     cur = FGPositioned::findNextWithPartialId(cur, ident, &filter);
   }
 
-  return NULL;
+  return reply;
+}
+
+class NavRecordDistanceSortPredicate
+{
+public:
+    NavRecordDistanceSortPredicate( const SGGeod & position ) :
+    _position(SGVec3d::fromGeod(position)) {}
+
+    bool operator()( const nav_rec_ptr & n1, const nav_rec_ptr & n2 )
+    {
+        if( n1 == NULL || n2 == NULL ) return false;
+        return distSqr(n1->cart(), _position) < distSqr(n2->cart(), _position);
+    }
+private:
+    SGVec3d _position;
+
+};
+
+// Given an Ident and optional freqency and type , 
+// return a list of matching stations sorted by distance to the given position
+const nav_list_type FGNavList::findByIdentAndFreq( const SGGeod & position,
+        const std::string& ident, const double freq, const FGPositioned::Type type )
+{
+    nav_list_type reply = findByIdentAndFreq( ident, freq, type );
+    NavRecordDistanceSortPredicate sortPredicate( position );
+    std::sort( reply.begin(), reply.end(), sortPredicate );
+
+    return reply;
 }
 
 // discount navids if they conflict with another on the same frequency
index f54e5db9320433dff00b90f96d33bb0c93959af9..6b4b6365c1342659530617ba7d56af36b04cc20b 100644 (file)
@@ -76,10 +76,16 @@ public:
       */
     FGNavRecord *findByFreq( double freq, const SGGeod& position);
 
-    // Given an Ident and optional freqency, return the first matching
-    // station.
-    FGNavRecord *findByIdentAndFreq( const std::string& ident,
-                                     const double freq = 0.0 );
+    // Given an Ident and optional freqency and type , 
+    // return a list of matching stations.
+    const nav_list_type findByIdentAndFreq( const std::string& ident,
+        const double freq = 0.0, const FGPositioned::Type = FGPositioned::INVALID );
+
+    // Given an Ident and optional freqency and type , 
+    // return a list of matching stations sorted by distance to the given position
+    const nav_list_type findByIdentAndFreq( const SGGeod & position,
+        const std::string& ident, const double freq = 0.0, 
+        const FGPositioned::Type = FGPositioned::INVALID );
 
     // given a frequency returns the first matching entry
     FGNavRecord *findStationByFreq( double frequency );