1
0
Fork 0

Remove all name and spatial queries from FGNavList. All remaining queries are

by frequency (which makes sense), and use the FGPositioned spatial data if
required. As a result, the marker beacon list is gone (since beacons are only
searched spatially). In the process, clean up various minor things - most
notably, all the 'airport-related' navaids (ILS, GS, LOC, and the beacons) now
store a FGRunway* instead of an airport id string. This is more precise, and
saves string allocations.
This commit is contained in:
jmt 2008-12-25 23:11:43 +00:00
parent 02d1b14c1a
commit 988de9dbca
21 changed files with 196 additions and 353 deletions

View file

@ -44,6 +44,10 @@ class FGRunway : public FGPositioned
double _width; double _width;
double _displ_thresh; double _displ_thresh;
double _stopway; double _stopway;
/** surface, as defined by:
* http://www.x-plane.org/home/robinp/Apt810.htm#RwySfcCodes
*/
int _surface_code; int _surface_code;
public: public:

View file

@ -71,6 +71,9 @@ public:
bool isSeaport() const; bool isSeaport() const;
bool isHeliport() const; bool isHeliport() const;
virtual const std::string& name() const
{ return _name; }
const SGGeod& getTowerLocation() const { return _tower_location; } const SGGeod& getTowerLocation() const { return _tower_location; }
void setMetar(bool value) { _has_metar = value; } void setMetar(bool value) { _has_metar = value; }

View file

@ -90,7 +90,7 @@ void KLN89NDBPage::Update(double dt) {
} }
if(_subPage == 0) { if(_subPage == 0) {
// TODO - trim VOR-DME from the name, convert to uppercase, abbreviate, etc // TODO - trim VOR-DME from the name, convert to uppercase, abbreviate, etc
_kln89->DrawText(np->get_name(), 2, 0, 2); _kln89->DrawText(np->name(), 2, 0, 2);
_kln89->DrawLatitude(np->get_lat(), 2, 3, 1); _kln89->DrawLatitude(np->get_lat(), 2, 3, 1);
_kln89->DrawLongitude(np->get_lon(), 2, 3, 0); _kln89->DrawLongitude(np->get_lon(), 2, 3, 0);
} else { } else {

View file

@ -92,7 +92,7 @@ void KLN89VorPage::Update(double dt) {
//// TODO - will almost certainly have to process freq below for FG //// TODO - will almost certainly have to process freq below for FG
_kln89->DrawFreq(np->get_freq(), 2, 9, 3); _kln89->DrawFreq(np->get_freq(), 2, 9, 3);
// TODO - trim VOR-DME from the name, convert to uppercase, abbreviate, etc // TODO - trim VOR-DME from the name, convert to uppercase, abbreviate, etc
_kln89->DrawText(np->get_name(), 2, 0, 2); _kln89->DrawText(np->name(), 2, 0, 2);
//cout << np->lat << "... "; //cout << np->lat << "... ";
_kln89->DrawLatitude(np->get_lat(), 2, 3, 1); _kln89->DrawLatitude(np->get_lat(), 2, 3, 1);
_kln89->DrawLongitude(np->get_lon(), 2, 3, 0); _kln89->DrawLongitude(np->get_lon(), 2, 3, 0);

View file

@ -217,16 +217,15 @@ ADF::search (double frequency_khz, double longitude_rad,
_time_before_search_sec = 1.0; _time_before_search_sec = 1.0;
// try the ILS list first // try the ILS list first
FGNavRecord *nav = FGNavRecord *nav = globals->get_navlist()->findByFreq(frequency_khz,
globals->get_navlist()->findByFreq(frequency_khz, longitude_rad, SGGeod::fromRadM(longitude_rad, latitude_rad, altitude_m));
latitude_rad, altitude_m);
_transmitter_valid = (nav != NULL); _transmitter_valid = (nav != NULL);
if ( _transmitter_valid ) { if ( _transmitter_valid ) {
ident = nav->get_trans_ident(); ident = nav->get_trans_ident();
if ( ident != _last_ident ) { if ( ident != _last_ident ) {
_transmitter_pos = nav->get_pos(); _transmitter_pos = nav->geod();
_transmitter_cart = nav->get_cart(); _transmitter_cart = nav->cart();
_transmitter_range_nm = nav->get_range(); _transmitter_range_nm = nav->get_range();
} }
} }

View file

@ -165,14 +165,14 @@ DME::search (double frequency_mhz, double longitude_rad,
_time_before_search_sec = 1.0; _time_before_search_sec = 1.0;
// try the ILS list first // try the ILS list first
FGNavRecord *dme
= globals->get_dmelist()->findByFreq( frequency_mhz, longitude_rad, FGNavRecord *dme = globals->get_dmelist()->findByFreq( frequency_mhz,
latitude_rad, altitude_m); SGGeod::fromRadM(longitude_rad, latitude_rad, altitude_m));
_transmitter_valid = (dme != NULL); _transmitter_valid = (dme != NULL);
if ( _transmitter_valid ) { if ( _transmitter_valid ) {
_transmitter = dme->get_cart(); _transmitter = dme->cart();
_transmitter_elevation_ft = dme->get_elev_ft(); _transmitter_elevation_ft = dme->get_elev_ft();
_transmitter_range_nm = dme->get_range(); _transmitter_range_nm = dme->get_range();
_transmitter_bias = dme->get_multiuse(); _transmitter_bias = dme->get_multiuse();

View file

@ -494,10 +494,9 @@ void FGKR_87::update( double dt_sec ) {
// Update current nav/adf radio stations based on current postition // Update current nav/adf radio stations based on current postition
void FGKR_87::search() { void FGKR_87::search() {
double acft_lon = lon_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS; SGGeod pos = SGGeod::fromDegFt(lon_node->getDoubleValue(),
double acft_lat = lat_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS; lat_node->getDoubleValue(), alt_node->getDoubleValue());
double acft_elev = alt_node->getDoubleValue() * SG_FEET_TO_METER;
// FIXME: the panel should handle this // FIXME: the panel should handle this
static string last_ident = ""; static string last_ident = "";
@ -508,9 +507,8 @@ void FGKR_87::search() {
// ADF. // ADF.
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
FGNavRecord *adf
= globals->get_navlist()->findByFreq( freq, acft_lon, acft_lat, FGNavRecord *adf = globals->get_navlist()->findByFreq( freq, pos);
acft_elev );
if ( adf != NULL ) { if ( adf != NULL ) {
char sfreq[128]; char sfreq[128];
snprintf( sfreq, 10, "%d", freq ); snprintf( sfreq, 10, "%d", freq );
@ -526,8 +524,8 @@ void FGKR_87::search() {
stn_lat = adf->get_lat(); stn_lat = adf->get_lat();
stn_elev = adf->get_elev_ft(); stn_elev = adf->get_elev_ft();
range = adf->get_range(); range = adf->get_range();
effective_range = kludgeRange(stn_elev, acft_elev, range); effective_range = kludgeRange(stn_elev, pos.getElevationM(), range);
xyz = adf->get_cart(); xyz = adf->cart();
if ( globals->get_soundmgr()->exists( "adf-ident" ) ) { if ( globals->get_soundmgr()->exists( "adf-ident" ) ) {
globals->get_soundmgr()->remove( "adf-ident" ); globals->get_soundmgr()->remove( "adf-ident" );

View file

@ -29,6 +29,7 @@
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <simgear/math/sg_random.h> #include <simgear/math/sg_random.h>
#include <simgear/misc/sg_path.hxx>
#include <Aircraft/aircraft.hxx> #include <Aircraft/aircraft.hxx>
#include <Navaids/navlist.hxx> #include <Navaids/navlist.hxx>
@ -210,20 +211,20 @@ FGMarkerBeacon::update(double dt)
static bool check_beacon_range( const SGGeod& pos, static bool check_beacon_range( const SGGeod& pos,
FGNavRecord *b ) FGPositioned *b )
{ {
double d = distSqr(b->get_cart(), SGVec3d::fromGeod(pos)); double d = distSqr(b->cart(), SGVec3d::fromGeod(pos));
// cout << " distance = " << d << " (" // cout << " distance = " << d << " ("
// << FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER // << FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER
// * FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER // * FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER
// << ")" << endl; // << ")" << endl;
// cout << " range = " << sqrt(d) << endl; //std::cout << " range = " << sqrt(d) << std::endl;
// cout << "elev = " << elev * SG_METER_TO_FEET // cout << "elev = " << elev * SG_METER_TO_FEET
// << " current->get_elev() = " << current->get_elev() << endl; // << " current->get_elev() = " << current->get_elev() << endl;
double elev_ft = pos.getElevationFt(); double elev_ft = pos.getElevationFt();
double delev = elev_ft - b->get_elev_ft(); double delev = elev_ft - b->elevation();
// max range is the area under r = 2.4 * alt or r^2 = 4000^2 - alt^2 // max range is the area under r = 2.4 * alt or r^2 = 4000^2 - alt^2
// whichever is smaller. The intersection point is 1538 ... // whichever is smaller. The intersection point is 1538 ...
@ -236,7 +237,7 @@ static bool check_beacon_range( const SGGeod& pos,
maxrange2 = 0.0; maxrange2 = 0.0;
} }
maxrange2 *= SG_FEET_TO_METER * SG_FEET_TO_METER; // convert to meter^2 maxrange2 *= SG_FEET_TO_METER * SG_FEET_TO_METER; // convert to meter^2
// cout << "delev = " << delev << " maxrange = " << maxrange << endl; //std::cout << "delev = " << delev << " maxrange = " << sqrt(maxrange2) << std::endl;
// match up to twice the published range so we can model // match up to twice the published range so we can model
// reduced signal strength // reduced signal strength
@ -247,10 +248,18 @@ static bool check_beacon_range( const SGGeod& pos,
} }
} }
class BeaconFilter : public FGPositioned::Filter
{
public:
virtual bool pass(FGPositioned* aPos) const
{
return (aPos->type() >= FGPositioned::OM) && (aPos->type() <= FGPositioned::IM);
}
};
// Update current nav/adf radio stations based on current postition // Update current nav/adf radio stations based on current postition
void FGMarkerBeacon::search() void FGMarkerBeacon::search()
{ {
// reset search time // reset search time
_time_before_search_sec = 1.0; _time_before_search_sec = 1.0;
@ -264,14 +273,10 @@ void FGMarkerBeacon::search()
// Beacons. // Beacons.
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// get closest marker beacon // get closest marker beacon - within a 1nm cutoff
FGNavRecord *b BeaconFilter filter;
= globals->get_mkrlist()->findClosest( pos.getLongitudeRad(), FGPositionedRef b = FGPositioned::findClosest(pos, 1.0, &filter);
pos.getLatitudeRad(),
pos.getElevationM() );
// cout << "marker beacon = " << b << " (" << b->get_type() << ")" << endl;
fgMkrBeacType beacon_type = NOBEACON; fgMkrBeacType beacon_type = NOBEACON;
bool inrange = false; bool inrange = false;
if ( b != NULL ) { if ( b != NULL ) {
@ -282,8 +287,7 @@ void FGMarkerBeacon::search()
} else if ( b->type() == FGPositioned::IM ) { } else if ( b->type() == FGPositioned::IM ) {
beacon_type = INNER; beacon_type = INNER;
} }
inrange = check_beacon_range( pos, b ); inrange = check_beacon_range( pos, b.ptr() );
// cout << " inrange = " << inrange << endl;
} }
outer_marker = middle_marker = inner_marker = false; outer_marker = middle_marker = inner_marker = false;

View file

@ -31,6 +31,7 @@
#include <simgear/timing/sg_time.hxx> #include <simgear/timing/sg_time.hxx>
#include <simgear/math/vector.hxx> #include <simgear/math/vector.hxx>
#include <simgear/math/sg_random.h> #include <simgear/math/sg_random.h>
#include <simgear/misc/sg_path.hxx>
#include <simgear/math/sg_geodesy.hxx> #include <simgear/math/sg_geodesy.hxx>
#include <simgear/structure/exception.hxx> #include <simgear/structure/exception.hxx>
@ -764,10 +765,8 @@ void FGNavRadio::search()
_time_before_search_sec = 1.0; _time_before_search_sec = 1.0;
// cache values locally for speed // cache values locally for speed
double lon = lon_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS; SGGeod pos = SGGeod::fromDegFt(lon_node->getDoubleValue(),
double lat = lat_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS; lat_node->getDoubleValue(), alt_node->getDoubleValue());
double elev = alt_node->getDoubleValue() * SG_FEET_TO_METER;
FGNavRecord *nav = NULL; FGNavRecord *nav = NULL;
FGNavRecord *loc = NULL; FGNavRecord *loc = NULL;
FGNavRecord *dme = NULL; FGNavRecord *dme = NULL;
@ -778,11 +777,11 @@ void FGNavRadio::search()
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
double freq = freq_node->getDoubleValue(); double freq = freq_node->getDoubleValue();
nav = globals->get_navlist()->findByFreq(freq, lon, lat, elev); nav = globals->get_navlist()->findByFreq(freq, pos);
dme = globals->get_dmelist()->findByFreq(freq, lon, lat, elev); dme = globals->get_dmelist()->findByFreq(freq, pos);
if ( nav == NULL ) { if ( nav == NULL ) {
loc = globals->get_loclist()->findByFreq(freq, lon, lat, elev); loc = globals->get_loclist()->findByFreq(freq, pos);
gs = globals->get_gslist()->findByFreq(freq, lon, lat, elev); gs = globals->get_gslist()->findByFreq(freq, pos);
} }
string nav_id = ""; string nav_id = "";
@ -799,7 +798,7 @@ void FGNavRadio::search()
while ( target_radial > 360.0 ) { target_radial -= 360.0; } while ( target_radial > 360.0 ) { target_radial -= 360.0; }
loc_lon = loc->get_lon(); loc_lon = loc->get_lon();
loc_lat = loc->get_lat(); loc_lat = loc->get_lat();
nav_xyz = loc->get_cart(); nav_xyz = loc->cart();
last_nav_id = nav_id; last_nav_id = nav_id;
last_nav_vor = false; last_nav_vor = false;
loc_node->setBoolValue( true ); loc_node->setBoolValue( true );
@ -811,7 +810,7 @@ void FGNavRadio::search()
nav_elev = gs->get_elev_ft(); nav_elev = gs->get_elev_ft();
int tmp = (int)(gs->get_multiuse() / 1000.0); int tmp = (int)(gs->get_multiuse() / 1000.0);
target_gs = (double)tmp / 100.0; target_gs = (double)tmp / 100.0;
gs_xyz = gs->get_cart(); gs_xyz = gs->cart();
// derive GS baseline (perpendicular to the runay // derive GS baseline (perpendicular to the runay
// along the ground) // along the ground)
@ -884,10 +883,10 @@ void FGNavRadio::search()
nav_elev = nav->get_elev_ft(); nav_elev = nav->get_elev_ft();
twist = nav->get_multiuse(); twist = nav->get_multiuse();
range = nav->get_range(); range = nav->get_range();
effective_range = adjustNavRange(nav_elev, elev, range); effective_range = adjustNavRange(nav_elev, pos.getElevationM(), range);
target_gs = 0.0; target_gs = 0.0;
target_radial = sel_radial_node->getDoubleValue(); target_radial = sel_radial_node->getDoubleValue();
nav_xyz = nav->get_cart(); nav_xyz = nav->cart();
if ( globals->get_soundmgr()->exists( nav_fx_name ) ) { if ( globals->get_soundmgr()->exists( nav_fx_name ) ) {
globals->get_soundmgr()->remove( nav_fx_name ); globals->get_soundmgr()->remove( nav_fx_name );

View file

@ -293,7 +293,7 @@ TACAN::search (double frequency_mhz, double longitude_rad,
if ( freq_valid ) { if ( freq_valid ) {
string str1( mobile_tacan->get_name() ); string str1( mobile_tacan->name() );
SGPropertyNode * branch = fgGetNode("ai/models", true); SGPropertyNode * branch = fgGetNode("ai/models", true);
vector<SGPropertyNode_ptr> carrier = branch->getChildren("carrier"); vector<SGPropertyNode_ptr> carrier = branch->getChildren("carrier");
@ -315,7 +315,7 @@ TACAN::search (double frequency_mhz, double longitude_rad,
_mobile_elevation_ft = mobile_tacan->get_elev_ft(); _mobile_elevation_ft = mobile_tacan->get_elev_ft();
_mobile_range_nm = mobile_tacan->get_range(); _mobile_range_nm = mobile_tacan->get_range();
_mobile_bias = mobile_tacan->get_multiuse(); _mobile_bias = mobile_tacan->get_multiuse();
_mobile_name = mobile_tacan->get_name(); _mobile_name = mobile_tacan->name();
_mobile_ident = mobile_tacan->get_trans_ident(); _mobile_ident = mobile_tacan->get_trans_ident();
_mobile_valid = true; _mobile_valid = true;
SG_LOG( SG_INSTR, SG_DEBUG, " carrier transmitter valid " << _mobile_valid ); SG_LOG( SG_INSTR, SG_DEBUG, " carrier transmitter valid " << _mobile_valid );
@ -353,7 +353,7 @@ TACAN::search (double frequency_mhz, double longitude_rad,
_mobile_elevation_ft = tanker[i]->getDoubleValue("position/altitude-ft"); _mobile_elevation_ft = tanker[i]->getDoubleValue("position/altitude-ft");
_mobile_range_nm = mobile_tacan->get_range(); _mobile_range_nm = mobile_tacan->get_range();
_mobile_bias = mobile_tacan->get_multiuse(); _mobile_bias = mobile_tacan->get_multiuse();
_mobile_name = mobile_tacan->get_name(); _mobile_name = mobile_tacan->name();
_mobile_ident = mobile_tacan->get_trans_ident(); _mobile_ident = mobile_tacan->get_trans_ident();
_mobile_valid = true; _mobile_valid = true;
SG_LOG( SG_INSTR, SG_DEBUG, " tanker transmitter valid " << _mobile_valid ); SG_LOG( SG_INSTR, SG_DEBUG, " tanker transmitter valid " << _mobile_valid );
@ -392,7 +392,7 @@ TACAN::search (double frequency_mhz, double longitude_rad,
_mobile_elevation_ft = mp_tanker[i]->getDoubleValue("position/altitude-ft"); _mobile_elevation_ft = mp_tanker[i]->getDoubleValue("position/altitude-ft");
_mobile_range_nm = mobile_tacan->get_range(); _mobile_range_nm = mobile_tacan->get_range();
_mobile_bias = mobile_tacan->get_multiuse(); _mobile_bias = mobile_tacan->get_multiuse();
_mobile_name = mobile_tacan->get_name(); _mobile_name = mobile_tacan->name();
_mobile_ident = mobile_tacan->get_trans_ident(); _mobile_ident = mobile_tacan->get_trans_ident();
_mobile_valid = true; _mobile_valid = true;
@ -415,19 +415,18 @@ TACAN::search (double frequency_mhz, double longitude_rad,
} }
// try the TACAN/VORTAC list next // try the TACAN/VORTAC list next
FGNavRecord *tacan FGNavRecord *tacan = globals->get_tacanlist()->findByFreq( frequency_mhz,
= globals->get_tacanlist()->findByFreq( frequency_mhz, longitude_rad, SGGeod::fromRadM(longitude_rad, latitude_rad, altitude_m));
latitude_rad, altitude_m);
_transmitter_valid = (tacan != NULL); _transmitter_valid = (tacan != NULL);
if ( _transmitter_valid ) { if ( _transmitter_valid ) {
SG_LOG( SG_INSTR, SG_DEBUG, "transmitter valid " << _transmitter_valid ); SG_LOG( SG_INSTR, SG_DEBUG, "transmitter valid " << _transmitter_valid );
_transmitter_pos = tacan->get_pos(); _transmitter_pos = tacan->geod();
_transmitter_range_nm = tacan->get_range(); _transmitter_range_nm = tacan->get_range();
_transmitter_bias = tacan->get_multiuse(); _transmitter_bias = tacan->get_multiuse();
_transmitter_name = tacan->get_name(); _transmitter_name = tacan->name();
_name_node->setStringValue(_transmitter_name.c_str()); _name_node->setStringValue(_transmitter_name.c_str());
_transmitter_ident = tacan->get_trans_ident(); _transmitter_ident = tacan->get_trans_ident();
_ident_node->setStringValue(_transmitter_ident.c_str()); _ident_node->setStringValue(_transmitter_ident.c_str());

View file

@ -102,6 +102,7 @@
#include <Navaids/navdb.hxx> #include <Navaids/navdb.hxx>
#include <Navaids/navlist.hxx> #include <Navaids/navlist.hxx>
#include <Navaids/fix.hxx> #include <Navaids/fix.hxx>
#include <Navaids/fixlist.hxx>
#include <Scenery/scenery.hxx> #include <Scenery/scenery.hxx>
#include <Scenery/tilemgr.hxx> #include <Scenery/tilemgr.hxx>
#include <Scripting/NasalSys.hxx> #include <Scripting/NasalSys.hxx>
@ -974,7 +975,6 @@ fgInitNav ()
FGNavList *loclist = new FGNavList; FGNavList *loclist = new FGNavList;
FGNavList *gslist = new FGNavList; FGNavList *gslist = new FGNavList;
FGNavList *dmelist = new FGNavList; FGNavList *dmelist = new FGNavList;
FGNavList *mkrlist = new FGNavList;
FGNavList *tacanlist = new FGNavList; FGNavList *tacanlist = new FGNavList;
FGNavList *carrierlist = new FGNavList; FGNavList *carrierlist = new FGNavList;
FGTACANList *channellist = new FGTACANList; FGTACANList *channellist = new FGTACANList;
@ -983,12 +983,11 @@ fgInitNav ()
globals->set_loclist( loclist ); globals->set_loclist( loclist );
globals->set_gslist( gslist ); globals->set_gslist( gslist );
globals->set_dmelist( dmelist ); globals->set_dmelist( dmelist );
globals->set_mkrlist( mkrlist );
globals->set_tacanlist( tacanlist ); globals->set_tacanlist( tacanlist );
globals->set_carrierlist( carrierlist ); globals->set_carrierlist( carrierlist );
globals->set_channellist( channellist ); globals->set_channellist( channellist );
if ( !fgNavDBInit(navlist, loclist, gslist, dmelist, mkrlist, tacanlist, carrierlist, channellist) ) { if ( !fgNavDBInit(navlist, loclist, gslist, dmelist, tacanlist, carrierlist, channellist) ) {
SG_LOG( SG_GENERAL, SG_ALERT, SG_LOG( SG_GENERAL, SG_ALERT,
"Problems loading one or more navigational database" ); "Problems loading one or more navigational database" );
} }

View file

@ -104,7 +104,6 @@ FGGlobals::FGGlobals() :
loclist( NULL ), loclist( NULL ),
gslist( NULL ), gslist( NULL ),
dmelist( NULL ), dmelist( NULL ),
mkrlist( NULL ),
tacanlist( NULL ), tacanlist( NULL ),
carrierlist( NULL ), carrierlist( NULL ),
channellist( NULL ), channellist( NULL ),
@ -155,7 +154,6 @@ FGGlobals::~FGGlobals()
delete loclist; delete loclist;
delete gslist; delete gslist;
delete dmelist; delete dmelist;
delete mkrlist;
delete tacanlist; delete tacanlist;
delete carrierlist; delete carrierlist;
delete channellist; delete channellist;

View file

@ -183,7 +183,6 @@ private:
FGNavList *loclist; FGNavList *loclist;
FGNavList *gslist; FGNavList *gslist;
FGNavList *dmelist; FGNavList *dmelist;
FGNavList *mkrlist;
FGNavList *tacanlist; FGNavList *tacanlist;
FGNavList *carrierlist; FGNavList *carrierlist;
FGTACANList *channellist; FGTACANList *channellist;
@ -331,8 +330,6 @@ public:
inline void set_tacanlist( FGNavList *n ) { tacanlist = n; } inline void set_tacanlist( FGNavList *n ) { tacanlist = n; }
inline FGNavList *get_carrierlist() const { return carrierlist; } inline FGNavList *get_carrierlist() const { return carrierlist; }
inline void set_carrierlist( FGNavList *n ) { carrierlist = n; } inline void set_carrierlist( FGNavList *n ) { carrierlist = n; }
inline FGNavList *get_mkrlist() const { return mkrlist; }
inline void set_mkrlist( FGNavList *n ) { mkrlist = n; }
inline FGTACANList *get_channellist() const { return channellist; } inline FGTACANList *get_channellist() const { return channellist; }
inline void set_channellist( FGTACANList *c ) { channellist = c; } inline void set_channellist( FGTACANList *c ) { channellist = c; }

View file

@ -31,10 +31,12 @@
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_geodesy.hxx> #include <simgear/math/sg_geodesy.hxx>
#include <simgear/misc/strutils.hxx> #include <simgear/misc/strutils.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/structure/exception.hxx> #include <simgear/structure/exception.hxx>
#include <simgear/misc/sgstream.hxx> #include <simgear/misc/sgstream.hxx>
#include "navrecord.hxx" #include "navrecord.hxx"
#include "navlist.hxx"
#include "navdb.hxx" #include "navdb.hxx"
#include "Main/globals.hxx" #include "Main/globals.hxx"
@ -43,7 +45,7 @@ using std::string;
// load and initialize the navigational databases // load and initialize the navigational databases
bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist, bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist,
FGNavList *dmelist, FGNavList *mkrlist, FGNavList *dmelist,
FGNavList *tacanlist, FGNavList *carrierlist, FGNavList *tacanlist, FGNavList *carrierlist,
FGTACANList *channellist) FGTACANList *channellist)
{ {
@ -97,14 +99,14 @@ bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist,
case FGPositioned::OM: case FGPositioned::OM:
case FGPositioned::MM: case FGPositioned::MM:
case FGPositioned::IM: case FGPositioned::IM:
mkrlist->add(r); // no need to add this to a list, never searched by frequency
break; break;
case FGPositioned::DME: case FGPositioned::DME:
{ {
dmelist->add(r); dmelist->add(r);
string::size_type loc1= r->get_name().find( "TACAN", 0 ); string::size_type loc1= r->name().find( "TACAN", 0 );
string::size_type loc2 = r->get_name().find( "VORTAC", 0 ); string::size_type loc2 = r->name().find( "VORTAC", 0 );
if( loc1 != string::npos || loc2 != string::npos) { if( loc1 != string::npos || loc2 != string::npos) {
tacanlist->add(r); tacanlist->add(r);

View file

@ -26,14 +26,13 @@
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <simgear/misc/sg_path.hxx>
#include "navlist.hxx" class FGNavList;
#include "fixlist.hxx" class FGTACANList;
// load and initialize the navigational databases // load and initialize the navigational databases
bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist, bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist,
FGNavList *dmelist, FGNavList *mkrbeacons, FGNavList *dmelist,
FGNavList *tacanlist, FGNavList *carrierlist, FGNavList *tacanlist, FGNavList *carrierlist,
FGTACANList *channellist ); FGTACANList *channellist );

View file

@ -26,20 +26,12 @@
#endif #endif
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/misc/sgstream.hxx>
#include <simgear/math/sg_geodesy.hxx> #include <simgear/math/sg_geodesy.hxx>
#include <simgear/sg_inlines.h>
#include "navlist.hxx" #include "navlist.hxx"
using std::string;
// Return true if the nav record matches the type
static bool isTypeMatch(const FGNavRecord* n, fg_nav_types type)
{
if (type == FG_NAV_ANY) return true;
return type == n->type();
}
// FGNavList ------------------------------------------------------------------ // FGNavList ------------------------------------------------------------------
@ -50,7 +42,6 @@ FGNavList::FGNavList( void )
FGNavList::~FGNavList( void ) FGNavList::~FGNavList( void )
{ {
navaids_by_tile.erase( navaids_by_tile.begin(), navaids_by_tile.end() );
nav_list_type navlist = navaids.begin()->second; nav_list_type navlist = navaids.begin()->second;
navaids.erase( navaids.begin(), navaids.end() ); navaids.erase( navaids.begin(), navaids.end() );
} }
@ -63,133 +54,55 @@ bool FGNavList::init()
// since we're using an SGSharedPointer // since we're using an SGSharedPointer
nav_list_type navlist = navaids.begin()->second; nav_list_type navlist = navaids.begin()->second;
navaids.erase( navaids.begin(), navaids.end() ); navaids.erase( navaids.begin(), navaids.end() );
navaids_by_tile.erase( navaids_by_tile.begin(), navaids_by_tile.end() );
ident_navaids.erase( ident_navaids.begin(), ident_navaids.end() );
return true; return true;
} }
// real add a marker beacon
static void real_add( nav_map_type &navmap, const int master_index,
FGNavRecord *n )
{
navmap[master_index].push_back( n );
}
// front end for add a marker beacon
static void tile_add( nav_map_type &navmap, FGNavRecord *n )
{
double diff = 0;
double lon = n->get_lon();
double lat = n->get_lat();
int lonidx = (int)lon;
diff = lon - (double)lonidx;
if ( (lon < 0.0) && (fabs(diff) > SG_EPSILON) ) {
lonidx -= 1;
}
double lonfrac = lon - (double)lonidx;
lonidx += 180;
int latidx = (int)lat;
diff = lat - (double)latidx;
if ( (lat < 0.0) && (fabs(diff) > SG_EPSILON) ) {
latidx -= 1;
}
double latfrac = lat - (double)latidx;
latidx += 90;
int master_index = lonidx * 1000 + latidx;
// cout << "lonidx = " << lonidx << " latidx = " << latidx << " ";
// cout << "Master index = " << master_index << endl;
// add to the actual bucket
real_add( navmap, master_index, n );
// if we are close to the edge, add to adjacent buckets so we only
// have to search one bucket at run time
// there are 8 cases since there are 8 adjacent tiles
if ( lonfrac < 0.2 ) {
real_add( navmap, master_index - 1000, n );
if ( latfrac < 0.2 ) {
real_add( navmap, master_index - 1000 - 1, n );
} else if ( latfrac > 0.8 ) {
real_add( navmap, master_index - 1000 + 1, n );
}
} else if ( lonfrac > 0.8 ) {
real_add( navmap, master_index + 1000, n );
if ( latfrac < 0.2 ) {
real_add( navmap, master_index + 1000 - 1, n );
} else if ( latfrac > 0.8 ) {
real_add( navmap, master_index + 1000 + 1, n );
}
} else if ( latfrac < 0.2 ) {
real_add( navmap, master_index - 1, n );
} else if ( latfrac > 0.8 ) {
real_add( navmap, master_index + 1, n );
}
}
// add an entry to the lists // add an entry to the lists
bool FGNavList::add( FGNavRecord *n ) bool FGNavList::add( FGNavRecord *n )
{ {
navaids[n->get_freq()].push_back(n); navaids[n->get_freq()].push_back(n);
ident_navaids[n->get_ident()].push_back(n);
tile_add( navaids_by_tile, n );
return true; return true;
} }
FGNavRecord *FGNavList::findByFreq( double freq, double lon, double lat, double elev ) FGNavRecord *FGNavList::findByFreq( double freq, const SGGeod& position)
{ {
const nav_list_type& stations = navaids[(int)(freq*100.0 + 0.5)]; const nav_list_type& stations = navaids[(int)(freq*100.0 + 0.5)];
SGGeod geod = SGGeod::fromRadM(lon, lat, elev);
SGVec3d aircraft = SGVec3d::fromGeod(geod);
SG_LOG( SG_INSTR, SG_DEBUG, "findbyFreq " << freq << " size " << stations.size() ); SG_LOG( SG_INSTR, SG_DEBUG, "findbyFreq " << freq << " size " << stations.size() );
return findNavFromList( position, stations );
return findNavFromList( aircraft, stations );
} }
class VORNDBFilter : public FGPositioned::Filter
FGNavRecord *FGNavList::findByIdent( const char* ident,
const double lon, const double lat )
{ {
const nav_list_type& stations = ident_navaids[ident]; public:
SGGeod geod = SGGeod::fromRad(lon, lat); virtual bool pass(FGPositioned* aPos) const
SGVec3d aircraft = SGVec3d::fromGeod(geod); {
return findNavFromList( aircraft, stations ); return (aPos->type() == FGPositioned::VOR) || (aPos->type() == FGPositioned::NDB);
} }
};
// Given an Ident and optional freqency, return the first matching // Given an Ident and optional freqency, return the first matching
// station. // station.
FGNavRecord *FGNavList::findByIdentAndFreq( const char* ident, const double freq ) FGNavRecord *FGNavList::findByIdentAndFreq(const string& ident, const double freq )
{ {
nav_list_type stations = ident_navaids[ident]; FGPositionedRef cur;
SG_LOG( SG_INSTR, SG_DEBUG, "findByIdent " << ident<< " size " << stations.size() ); VORNDBFilter filter;
if ( freq > 0.0 ) { cur = FGPositioned::findNextWithPartialId(cur, ident, &filter);
// sometimes there can be duplicated idents. If a freq is
// specified, use it to refine the search. if (freq <= 0.0) {
int f = (int)(freq*100.0 + 0.5); return static_cast<FGNavRecord*>(cur.ptr()); // might be null
nav_list_const_iterator it, end = stations.end(); }
for ( it = stations.begin(); it != end; ++it ) {
if ( f == (*it)->get_freq() ) { int f = (int)(freq*100.0 + 0.5);
return (*it); while (cur) {
} FGNavRecord* nav = static_cast<FGNavRecord*>(cur.ptr());
} if (nav->get_freq() == f) {
} else if (!stations.empty()) { return nav;
return stations[0];
} }
cur = FGPositioned::findNextWithPartialId(cur, ident, &filter);
}
return NULL; return NULL;
} }
// LOC, ILS, GS, and DME antenna's could potentially be // LOC, ILS, GS, and DME antenna's could potentially be
@ -203,7 +116,7 @@ FGNavRecord *FGNavList::findByIdentAndFreq( const char* ident, const double freq
// directional atennas and only when there is a chance it is // directional atennas and only when there is a chance it is
// the closest station.) // the closest station.)
static bool penaltyForNav(FGNavRecord* aNav, const SGVec3d &aPos) static bool penaltyForNav(FGNavRecord* aNav, const SGGeod &aGeod)
{ {
switch (aNav->type()) { switch (aNav->type()) {
case FGPositioned::ILS: case FGPositioned::ILS:
@ -224,34 +137,31 @@ static bool penaltyForNav(FGNavRecord* aNav, const SGVec3d &aPos)
hdg_deg = aNav->get_multiuse(); hdg_deg = aNav->get_multiuse();
} }
double az1 = 0.0, az2 = 0.0, s = 0.0; double az1, az2, s;
SGGeod geod = SGGeod::fromCart(aPos); SGGeodesy::inverse(aGeod, aNav->geod(), az1, az2, s);
geo_inverse_wgs_84( geod, aNav->geod(), &az1, &az2, &s);
az1 = az1 - hdg_deg; az1 = az1 - hdg_deg;
SG_NORMALIZE_RANGE(az1, -180.0, 180.0);
if ( az1 > 180.0) az1 -= 360.0;
if ( az1 < -180.0) az1 += 360.0;
return fabs(az1) > 90.0; return fabs(az1) > 90.0;
} }
// Given a point and a list of stations, return the closest one to the // Given a point and a list of stations, return the closest one to the
// specified point. // specified point.
FGNavRecord *FGNavList::findNavFromList( const SGVec3d &aircraft, FGNavRecord *FGNavList::findNavFromList( const SGGeod &aircraft,
const nav_list_type &stations ) const nav_list_type &stations )
{ {
FGNavRecord *nav = NULL; FGNavRecord *nav = NULL;
double d2; // in meters squared double d2; // in meters squared
double min_dist double min_dist
= FG_NAV_MAX_RANGE*SG_NM_TO_METER*FG_NAV_MAX_RANGE*SG_NM_TO_METER; = FG_NAV_MAX_RANGE*SG_NM_TO_METER*FG_NAV_MAX_RANGE*SG_NM_TO_METER;
SGVec3d aircraftCart = SGVec3d::fromGeod(aircraft);
nav_list_const_iterator it; nav_list_const_iterator it;
nav_list_const_iterator end = stations.end(); nav_list_const_iterator end = stations.end();
// find the closest station within a sensible range (FG_NAV_MAX_RANGE) // find the closest station within a sensible range (FG_NAV_MAX_RANGE)
for ( it = stations.begin(); it != end; ++it ) { for ( it = stations.begin(); it != end; ++it ) {
FGNavRecord *station = *it; FGNavRecord *station = *it;
// cout << "testing " << current->get_ident() << endl; // cout << "testing " << current->get_ident() << endl;
d2 = distSqr(station->get_cart(), aircraft); d2 = distSqr(station->cart(), aircraftCart);
if ( d2 < min_dist && penaltyForNav(station, aircraft)) if ( d2 < min_dist && penaltyForNav(station, aircraft))
{ {
double dist = sqrt(d2); double dist = sqrt(d2);
@ -267,69 +177,6 @@ FGNavRecord *FGNavList::findNavFromList( const SGVec3d &aircraft,
return nav; return nav;
} }
// returns the closest entry to the give lon/lat/elev
FGNavRecord *FGNavList::findClosest( double lon_rad, double lat_rad,
double elev_m, fg_nav_types type)
{
FGNavRecord *result = NULL;
double diff;
double lon_deg = lon_rad * SG_RADIANS_TO_DEGREES;
double lat_deg = lat_rad * SG_RADIANS_TO_DEGREES;
int lonidx = (int)lon_deg;
diff = lon_deg - (double)lonidx;
if ( (lon_deg < 0.0) && (fabs(diff) > SG_EPSILON) ) {
lonidx -= 1;
}
lonidx += 180;
int latidx = (int)lat_deg;
diff = lat_deg - (double)latidx;
if ( (lat_deg < 0.0) && (fabs(diff) > SG_EPSILON) ) {
latidx -= 1;
}
latidx += 90;
int master_index = lonidx * 1000 + latidx;
const nav_list_type& navs = navaids_by_tile[ master_index ];
// cout << "Master index = " << master_index << endl;
// cout << "beacon search length = " << beacons.size() << endl;
nav_list_const_iterator current = navs.begin();
nav_list_const_iterator last = navs.end();
SGGeod geod = SGGeod::fromRadM(lon_rad, lat_rad, elev_m);
SGVec3d aircraft = SGVec3d::fromGeod(geod);
double min_dist = 999999999.0;
for ( ; current != last ; ++current ) {
if(isTypeMatch(*current, type)) {
// cout << " testing " << (*current)->get_ident() << endl;
double d = distSqr((*current)->get_cart(), aircraft);
// cout << " distance = " << d << " ("
// << FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER
// * FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER
// << ")" << endl;
// cout << " range = " << sqrt(d) << endl;
if ( d < min_dist ) {
min_dist = d;
result = (*current);
}
}
}
// cout << "lon = " << lon << " lat = " << lat
// << " closest beacon = " << sqrt( min_dist ) << endl;
return result;
}
// Given a frequency, return the first matching station. // Given a frequency, return the first matching station.
FGNavRecord *FGNavList::findStationByFreq( double freq ) FGNavRecord *FGNavList::findStationByFreq( double freq )
{ {

View file

@ -26,9 +26,8 @@
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <simgear/misc/sg_path.hxx>
#include <simgear/structure/SGSharedPtr.hxx> #include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/structure/SGReferenced.hxx>
#include <map> #include <map>
#include <vector> #include <vector>
@ -36,37 +35,28 @@
#include "navrecord.hxx" #include "navrecord.hxx"
using std::map; // forward decls
using std::vector; class SGGeod;
using std::string;
// FGNavList ------------------------------------------------------------------ // FGNavList ------------------------------------------------------------------
typedef SGSharedPtr<FGNavRecord> nav_rec_ptr; typedef SGSharedPtr<FGNavRecord> nav_rec_ptr;
typedef vector < nav_rec_ptr > nav_list_type; typedef std::vector < nav_rec_ptr > nav_list_type;
typedef nav_list_type::iterator nav_list_iterator; typedef nav_list_type::iterator nav_list_iterator;
typedef nav_list_type::const_iterator nav_list_const_iterator; typedef nav_list_type::const_iterator nav_list_const_iterator;
typedef map < int, nav_list_type > nav_map_type; typedef std::map < int, nav_list_type > nav_map_type;
typedef nav_map_type::iterator nav_map_iterator; typedef nav_map_type::iterator nav_map_iterator;
typedef nav_map_type::const_iterator nav_map_const_iterator; typedef nav_map_type::const_iterator nav_map_const_iterator;
typedef map < string, nav_list_type > nav_ident_map_type;
typedef nav_ident_map_type::iterator nav_ident_map_iterator;
class FGNavList { class FGNavList {
nav_list_type carrierlist; nav_list_type carrierlist;
nav_map_type navaids; nav_map_type navaids;
nav_map_type navaids_by_tile;
nav_ident_map_type ident_navaids;
// Given a point and a list of stations, return the closest one to // Given a point and a list of stations, return the closest one to
// the specified point. // the specified point.
FGNavRecord *findNavFromList( const SGVec3d &aircraft, FGNavRecord *findNavFromList( const SGGeod &aircraft,
const nav_list_type &stations ); const nav_list_type &stations );
public: public:
@ -82,27 +72,17 @@ public:
/** Query the database for the specified station. It is assumed /** Query the database for the specified station. It is assumed
* that there will be multiple stations with matching frequencies * that there will be multiple stations with matching frequencies
* so a position must be specified. Lon and lat are in radians, * so a position must be specified.
* elev is in meters.
*/ */
FGNavRecord *findByFreq( double freq, double lon, double lat, double elev ); FGNavRecord *findByFreq( double freq, const SGGeod& position);
// locate closest item in the DB matching the requested ident
FGNavRecord *findByIdent( const char* ident, const double lon, const double lat );
// Given an Ident and optional freqency, return the first matching // Given an Ident and optional freqency, return the first matching
// station. // station.
FGNavRecord *findByIdentAndFreq( const char* ident, FGNavRecord *findByIdentAndFreq( const std::string& ident,
const double freq = 0.0 ); const double freq = 0.0 );
// returns the closest entry to the give lon/lat/elev
FGNavRecord *findClosest( double lon_rad, double lat_rad, double elev_m,
FGPositioned::Type type = FG_NAV_ANY );
// given a frequency returns the first matching entry // given a frequency returns the first matching entry
FGNavRecord *findStationByFreq( double frequency ); FGNavRecord *findStationByFreq( double frequency );
inline const nav_map_type& get_navaids() const { return navaids; }
}; };
@ -112,10 +92,9 @@ public:
typedef SGSharedPtr<FGTACANRecord> tacan_rec_ptr; typedef SGSharedPtr<FGTACANRecord> tacan_rec_ptr;
typedef vector < tacan_rec_ptr > tacan_list_type; typedef std::vector < tacan_rec_ptr > tacan_list_type;
typedef map < int, tacan_list_type > tacan_map_type; typedef std::map < int, tacan_list_type > tacan_map_type;
typedef map < string, tacan_list_type > tacan_ident_map_type; typedef std::map < std::string, tacan_list_type > tacan_ident_map_type;
class FGTACANList { class FGTACANList {
@ -135,7 +114,7 @@ public:
bool add( FGTACANRecord *r ); bool add( FGTACANRecord *r );
// Given a TACAN Channel, return the appropriate frequency. // Given a TACAN Channel, return the appropriate frequency.
FGTACANRecord *findByChannel( const string& channel ); FGTACANRecord *findByChannel( const std::string& channel );
}; };

View file

@ -43,7 +43,7 @@ FGNavRecord::FGNavRecord(Type aTy, const std::string& aIdent,
freq(aFreq), freq(aFreq),
range(aRange), range(aRange),
multiuse(aMultiuse), multiuse(aMultiuse),
name(aName), _name(aName),
serviceable(true), serviceable(true),
trans_ident(aIdent) trans_ident(aIdent)
{ {
@ -77,12 +77,6 @@ FGNavRecord::FGNavRecord(Type aTy, const std::string& aIdent,
} }
SGVec3d FGNavRecord::get_cart() const
{
return SGVec3d::fromGeod(geod());
}
static FGPositioned::Type static FGPositioned::Type
mapRobinTypeToFGPType(int aTy) mapRobinTypeToFGPType(int aTy)
{ {
@ -100,7 +94,7 @@ mapRobinTypeToFGPType(int aTy)
case 13: return FGPositioned::DME; case 13: return FGPositioned::DME;
case 99: return FGPositioned::INVALID; // end-of-file code case 99: return FGPositioned::INVALID; // end-of-file code
default: default:
throw sg_range_exception("Got a nav.dat type we don't recgonize", "FGNavRecord::createFromStream"); throw sg_range_exception("Got a nav.dat type we don't recognize", "FGNavRecord::createFromStream");
} }
} }
@ -117,7 +111,7 @@ FGNavRecord* FGNavRecord::createFromStream(std::istream& aStream)
double lat, lon, elev_ft, multiuse; double lat, lon, elev_ft, multiuse;
int freq, range; int freq, range;
std::string apt_id, name, ident; std::string name, ident;
aStream >> lat >> lon >> elev_ft >> freq >> range >> multiuse >> ident; aStream >> lat >> lon >> elev_ft >> freq >> range >> multiuse >> ident;
getline(aStream, name); getline(aStream, name);
@ -127,6 +121,12 @@ FGNavRecord* FGNavRecord::createFromStream(std::istream& aStream)
freq *= 100; freq *= 100;
} }
// ensure marker beacons are anonymous, so they don't get added to the
// name index
if ((type >= OM) && (type <= IM)) {
ident.clear();
}
FGNavRecord* result = new FGNavRecord(type, ident, FGNavRecord* result = new FGNavRecord(type, ident,
simgear::strutils::strip(name), SGGeod::fromDegFt(lon, lat, elev_ft), simgear::strutils::strip(name), SGGeod::fromDegFt(lon, lat, elev_ft),
freq, range, multiuse); freq, range, multiuse);
@ -136,19 +136,29 @@ FGNavRecord* FGNavRecord::createFromStream(std::istream& aStream)
void FGNavRecord::initAirportRelation() void FGNavRecord::initAirportRelation()
{ {
if (type() < ILS || type() > IM) { if ((type() < ILS) || (type() > IM)) {
return; // not airport-located return; // not airport-located
} }
vector<string> parts = simgear::strutils::split(name); vector<string> parts = simgear::strutils::split(_name);
apt_id = parts[0]; if (parts.size() < 2) {
const FGAirport* apt = fgFindAirportID(apt_id); SG_LOG(SG_GENERAL, SG_WARN, "navaid has malformed name:" << _name);
if (!apt) {
SG_LOG(SG_GENERAL, SG_WARN, "navaid " << ident() << " associated with bogus airport ID:" << apt_id);
return; return;
} }
const FGAirport* apt = fgFindAirportID(parts[0]);
if (!apt) {
SG_LOG(SG_GENERAL, SG_WARN, "navaid " << _name << " associated with bogus airport ID:" << parts[0]);
return;
}
runway = apt->getRunwayByIdent(parts[1]);
if (!runway) {
SG_LOG(SG_GENERAL, SG_WARN, "navaid " << _name << " associated with bogus runway ID:" << parts[1]);
return;
}
// fudge elevation to the field elevation if it's not specified // fudge elevation to the field elevation if it's not specified
if (fabs(elevation()) < 0.01) { if (fabs(elevation()) < 0.01) {
mPosition.setElevationFt(apt->getElevation()); mPosition.setElevationFt(apt->getElevation());
@ -160,16 +170,8 @@ void FGNavRecord::initAirportRelation()
return; return;
} }
if (parts.size() < 2) { double threshold
SG_LOG(SG_GENERAL, SG_ALERT, "can't parse navaid " << ident() = fgGetDouble( "/sim/navdb/localizers/auto-align-threshold-deg", 5.0 );
<< " name for airport/runway:" << name);
return;
}
double threshold
= fgGetDouble( "/sim/navdb/localizers/auto-align-threshold-deg",
5.0 );
FGRunway* runway = apt->getRunwayByIdent(parts[1]);
alignLocaliserWithRunway(runway, threshold); alignLocaliserWithRunway(runway, threshold);
} }
} }

View file

@ -53,9 +53,8 @@ class FGNavRecord : public FGPositioned
// (degrees) or localizer heading // (degrees) or localizer heading
// (degrees) or dme bias (nm) // (degrees) or dme bias (nm)
std::string name; // verbose name in nav database std::string _name; // verbose name in nav database
std::string apt_id; // corresponding airport id FGRunway* runway;
bool serviceable; // for failure modeling bool serviceable; // for failure modeling
std::string trans_ident; // for failure modeling std::string trans_ident; // for failure modeling
@ -78,23 +77,18 @@ public:
inline double get_lon() const { return longitude(); } // degrees inline double get_lon() const { return longitude(); } // degrees
inline double get_lat() const { return latitude(); } // degrees inline double get_lat() const { return latitude(); } // degrees
inline double get_elev_ft() const { return elevation(); } inline double get_elev_ft() const { return elevation(); }
const SGGeod& get_pos() const { return geod(); }
SGVec3d get_cart() const;
Type get_fg_type() const { return type(); }
inline int get_freq() const { return freq; } inline int get_freq() const { return freq; }
inline int get_range() const { return range; } inline int get_range() const { return range; }
inline double get_multiuse() const { return multiuse; } inline double get_multiuse() const { return multiuse; }
inline void set_multiuse( double m ) { multiuse = m; } inline void set_multiuse( double m ) { multiuse = m; }
inline const char *get_ident() const { return ident().c_str(); } inline const char *get_ident() const { return ident().c_str(); }
inline const std::string& get_name() const { return name; }
inline const std::string& get_apt_id() const { return apt_id; }
inline bool get_serviceable() const { return serviceable; } inline bool get_serviceable() const { return serviceable; }
inline const char *get_trans_ident() const { return trans_ident.c_str(); } inline const char *get_trans_ident() const { return trans_ident.c_str(); }
virtual const std::string& name() const
{ return _name; }
}; };
class FGTACANRecord : public SGReferenced { class FGTACANRecord : public SGReferenced {

View file

@ -26,6 +26,8 @@
#include <set> #include <set>
#include <algorithm> #include <algorithm>
#include <iostream>
#include <simgear/math/sg_geodesy.hxx> #include <simgear/math/sg_geodesy.hxx>
#include "positioned.hxx" #include "positioned.hxx"
@ -199,20 +201,19 @@ class RangePredictate
{ {
public: public:
RangePredictate(const SGGeod& aOrigin, double aRange) : RangePredictate(const SGGeod& aOrigin, double aRange) :
mOrigin(aOrigin), mOrigin(SGVec3d::fromGeod(aOrigin)),
mRange(aRange) mRangeSqr(aRange * aRange)
{ ; } { ; }
bool operator()(const FGPositionedRef& aPos) bool operator()(const FGPositionedRef& aPos)
{ {
double d, az1, az2; double dSqr = distSqr(aPos->cart(), mOrigin);
SGGeodesy::inverse(aPos->geod(), mOrigin, az1, az2, d); return (dSqr > mRangeSqr);
return (d > mRange);
} }
private: private:
SGGeod mOrigin; SGVec3d mOrigin;
double mRange; double mRangeSqr;
}; };
static void static void
@ -228,19 +229,18 @@ class DistanceOrdering
{ {
public: public:
DistanceOrdering(const SGGeod& aPos) : DistanceOrdering(const SGGeod& aPos) :
mPos(aPos) mPos(SGVec3d::fromGeod(aPos))
{ } { }
bool operator()(const FGPositionedRef& a, const FGPositionedRef& b) const bool operator()(const FGPositionedRef& a, const FGPositionedRef& b) const
{ {
double dA, dB, az1, az2; double dA = distSqr(a->cart(), mPos),
SGGeodesy::inverse(mPos, a->geod(), az1, az2, dA); dB = distSqr(b->cart(), mPos);
SGGeodesy::inverse(mPos, b->geod(), az1, az2, dB);
return dA < dB; return dA < dB;
} }
private: private:
SGGeod mPos; SGVec3d mPos;
}; };
static void static void
@ -273,17 +273,17 @@ namedFindClosest(const std::string& aIdent, const SGGeod& aOrigin, FGPositioned:
double minDist = HUGE_VAL; double minDist = HUGE_VAL;
FGPositionedRef result; FGPositionedRef result;
NamedPositionedIndex::const_iterator it = range.first; NamedPositionedIndex::const_iterator it = range.first;
SGVec3d cartOrigin(SGVec3d::fromGeod(aOrigin));
for (; it != range.second; ++it) { for (; it != range.second; ++it) {
if (aFilter && !aFilter->pass(range.first->second)) { if (aFilter && !aFilter->pass(range.first->second)) {
continue; continue;
} }
// find distance // find distance
double d, az1, az2; double d2 = distSqr(cartOrigin, it->second->cart());
SGGeodesy::inverse(aOrigin, it->second->geod(), az1, az2, d); if (d2 < minDist) {
if (d < minDist) { minDist = d2;
minDist = d;
result = it->second; result = it->second;
} }
} }
@ -328,11 +328,11 @@ spatialGetClosest(const SGGeod& aPos, unsigned int aN, double aCutoffNm, FGPosit
result.insert(result.end(), hits.begin(), hits.end()); // append result.insert(result.end(), hits.begin(), hits.end()); // append
} // of outer loop } // of outer loop
sortByDistance(aPos, result);
if (result.size() > aN) { if (result.size() > aN) {
result.resize(aN); // truncate at requested number of matches result.resize(aN); // truncate at requested number of matches
} }
sortByDistance(aPos, result);
return result; return result;
} }
@ -353,6 +353,7 @@ FGPositioned::FGPositioned(Type ty, const std::string& aIdent, const SGGeod& aPo
FGPositioned::~FGPositioned() FGPositioned::~FGPositioned()
{ {
//std::cout << "destroying:" << mIdent << "/" << nameForType(mType) << std::endl;
removeFromIndices(this); removeFromIndices(this);
} }
@ -362,12 +363,24 @@ FGPositioned::bucket() const
return SGBucket(mPosition); return SGBucket(mPosition);
} }
SGVec3d
FGPositioned::cart() const
{
return SGVec3d::fromGeod(mPosition);
}
const char* FGPositioned::nameForType(Type aTy) const char* FGPositioned::nameForType(Type aTy)
{ {
switch (aTy) { switch (aTy) {
case RUNWAY: return "runway";
case TAXIWAY: return "taxiway";
case PARK_STAND: return "parking stand";
case FIX: return "fix"; case FIX: return "fix";
case VOR: return "VOR"; case VOR: return "VOR";
case NDB: return "NDB"; case NDB: return "NDB";
case ILS: return "ILS";
case LOC: return "localiser";
case GS: return "glideslope";
case OM: return "outer-marker"; case OM: return "outer-marker";
case MM: return "middle-marker"; case MM: return "middle-marker";
case IM: return "inner-marker"; case IM: return "inner-marker";
@ -375,6 +388,8 @@ const char* FGPositioned::nameForType(Type aTy)
case HELIPORT: return "heliport"; case HELIPORT: return "heliport";
case SEAPORT: return "seaport"; case SEAPORT: return "seaport";
case WAYPOINT: return "waypoint"; case WAYPOINT: return "waypoint";
case DME: return "dme";
case TACAN: return "tacan";
default: default:
return "unknown"; return "unknown";
} }

View file

@ -82,6 +82,11 @@ public:
const SGGeod& geod() const const SGGeod& geod() const
{ return mPosition; } { return mPosition; }
/**
* Compute the cartesian position associated with this object
*/
SGVec3d cart() const;
SGBucket bucket() const; SGBucket bucket() const;
double latitude() const double latitude() const