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:
parent
02d1b14c1a
commit
988de9dbca
21 changed files with 196 additions and 353 deletions
|
@ -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:
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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" );
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
||||||
|
|
|
@ -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 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Reference in a new issue