Partial fix for #228: ambiguous navaid-names
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".
This commit is contained in:
parent
24383e5194
commit
c6d5b6ebdb
4 changed files with 93 additions and 30 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in a new issue