Clean out FGAirportList - not quite obsolete yet, but the spatial queries are
gone. This is good news, since the old query was implemented as a linear search, sorted by Manhattan distance, and with a warning not to use the logic at runtime. Various systems (such as the Mk-VIII) do query such data often, eg every second. Also gets Point3D out of Airports/simple.hxx, as a precursor to removing it completely.
This commit is contained in:
parent
988de9dbca
commit
82bfb6a08d
10 changed files with 157 additions and 227 deletions
|
@ -38,6 +38,9 @@ using std::string;
|
|||
#include "ATCutils.hxx"
|
||||
#include "tower.hxx"
|
||||
|
||||
// extern from Airports/simple.cxx
|
||||
extern Point3D fgGetAirportPos( const std::string& id );
|
||||
|
||||
FGAIGAVFRTraffic::FGAIGAVFRTraffic() {
|
||||
ATC = globals->get_ATC_mgr();
|
||||
_towerContactedIncoming = false;
|
||||
|
|
|
@ -53,6 +53,9 @@ using std::cout;
|
|||
|
||||
using namespace simgear;
|
||||
|
||||
// extern from Airports/simple.cxx
|
||||
extern Point3D fgGetAirportPos( const std::string& id );
|
||||
|
||||
FGAIMgr::FGAIMgr() {
|
||||
ATC = globals->get_ATC_mgr();
|
||||
initDone = false;
|
||||
|
|
|
@ -290,7 +290,7 @@ bool fgAirportDBLoad( FGAirportList *airports,
|
|||
metar_in >> skipeol;
|
||||
} else {
|
||||
const FGAirport* a = airports->search( ident );
|
||||
if ( a ) airports->has_metar( ident );
|
||||
if ( a ) const_cast<FGAirport*>(a)->setMetar(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -325,13 +325,9 @@ FGAirport* FGAirportList::add( const string &id, const SGGeod& location, const S
|
|||
// try and read in an auxilary file
|
||||
|
||||
airports_array.push_back( a );
|
||||
SG_LOG( SG_GENERAL, SG_BULK, "Adding " << id << " pos = " << location.getLongitudeDeg()
|
||||
<< ", " << location.getLatitudeDeg() << " elev = " << location.getElevationFt() );
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
// search for the specified id
|
||||
FGAirport* FGAirportList::search( const string& id)
|
||||
{
|
||||
|
@ -339,41 +335,6 @@ FGAirport* FGAirportList::search( const string& id)
|
|||
return (itr == airports_by_id.end() ? NULL : itr->second);
|
||||
}
|
||||
|
||||
// search for the airport nearest the specified position
|
||||
FGAirport* FGAirportList::search(double lon_deg, double lat_deg, double max_range)
|
||||
{
|
||||
static FGAirportSearchFilter accept_any;
|
||||
return search(lon_deg, lat_deg, max_range, accept_any);
|
||||
}
|
||||
|
||||
|
||||
// search for the airport nearest the specified position and
|
||||
// passing the filter
|
||||
FGAirport* FGAirportList::search(double lon_deg, double lat_deg,
|
||||
double max_range,
|
||||
FGAirportSearchFilter& filter)
|
||||
{
|
||||
double min_dist = max_range;
|
||||
|
||||
airport_list_iterator it = airports_array.begin();
|
||||
airport_list_iterator end = airports_array.end();
|
||||
airport_list_iterator closest = end;
|
||||
for (; it != end; ++it) {
|
||||
if (!filter.pass(*it))
|
||||
continue;
|
||||
|
||||
// crude manhatten distance based on lat/lon difference
|
||||
double d = fabs(lon_deg - (*it)->getLongitude())
|
||||
+ fabs(lat_deg - (*it)->getLatitude());
|
||||
if (d < min_dist) {
|
||||
closest = it;
|
||||
min_dist = d;
|
||||
}
|
||||
}
|
||||
return closest != end ? *closest : 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
FGAirportList::size () const
|
||||
{
|
||||
|
@ -390,29 +351,6 @@ const FGAirport *FGAirportList::getAirport( unsigned int index ) const
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mark the specified airport record as not having metar
|
||||
*/
|
||||
void FGAirportList::no_metar( const string &id )
|
||||
{
|
||||
if(airports_by_id.find(id) != airports_by_id.end()) {
|
||||
airports_by_id[id]->setMetar(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mark the specified airport record as (yes) having metar
|
||||
*/
|
||||
void FGAirportList::has_metar( const string &id )
|
||||
{
|
||||
if(airports_by_id.find(id) != airports_by_id.end()) {
|
||||
airports_by_id[id]->setMetar(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// find basic airport location info from airport database
|
||||
const FGAirport *fgFindAirportID( const string& id)
|
||||
{
|
||||
|
|
|
@ -31,10 +31,8 @@
|
|||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include <simgear/math/point3d.hxx>
|
||||
#include "Navaids/positioned.hxx"
|
||||
|
||||
// forward decls
|
||||
|
@ -139,14 +137,6 @@ private:
|
|||
std::vector<FGRunwayPtr> mTaxiways;
|
||||
};
|
||||
|
||||
|
||||
class FGAirportSearchFilter {
|
||||
public:
|
||||
virtual ~FGAirportSearchFilter() {}
|
||||
// all airports pass the filter by default
|
||||
virtual bool pass(FGAirport*) { return true; }
|
||||
};
|
||||
|
||||
typedef std::map < std::string, FGAirport* > airport_map;
|
||||
typedef airport_map::iterator airport_map_iterator;
|
||||
typedef airport_map::const_iterator const_airport_map_iterator;
|
||||
|
@ -178,14 +168,6 @@ public:
|
|||
// Returns NULL if unsucessfull.
|
||||
FGAirport* search( const std::string& id );
|
||||
|
||||
// search for the airport closest to the specified position
|
||||
// (currently a linear inefficient search so it's probably not
|
||||
// best to use this at runtime.) An FGAirportSearchFilter class
|
||||
// can be used to restrict the possible choices to a subtype.
|
||||
// max_range limits search - specified as an arc distance, in degrees
|
||||
FGAirport* search( double lon_deg, double lat_deg, double max_range );
|
||||
FGAirport* search( double lon_deg, double lat_deg, double max_range, FGAirportSearchFilter& );
|
||||
|
||||
/**
|
||||
* Return the number of airports in the list.
|
||||
*/
|
||||
|
@ -196,16 +178,6 @@ public:
|
|||
*/
|
||||
const FGAirport *getAirport( unsigned int index ) const;
|
||||
|
||||
/**
|
||||
* Mark the specified airport record as not having metar
|
||||
*/
|
||||
void no_metar( const std::string &id );
|
||||
|
||||
/**
|
||||
* Mark the specified airport record as (yes) having metar
|
||||
*/
|
||||
void has_metar( const std::string &id );
|
||||
|
||||
};
|
||||
|
||||
// find basic airport location info from airport database
|
||||
|
@ -214,9 +186,6 @@ const FGAirport *fgFindAirportID( const std::string& id);
|
|||
// get airport elevation
|
||||
double fgGetAirportElev( const std::string& id );
|
||||
|
||||
// get airport position
|
||||
Point3D fgGetAirportPos( const std::string& id );
|
||||
|
||||
#endif // _FG_SIMPLE_HXX
|
||||
|
||||
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
@ -36,15 +34,25 @@
|
|||
#include <Main/fg_props.hxx>
|
||||
#include <Main/util.hxx>
|
||||
|
||||
#include "Environment/fgmetar.hxx"
|
||||
#include "environment_mgr.hxx"
|
||||
#include "environment_ctrl.hxx"
|
||||
|
||||
using std::sort;
|
||||
|
||||
class metar_filter : public FGAirportSearchFilter {
|
||||
virtual bool pass(FGAirport *a) { return a->getMetar(); }
|
||||
} metar_only;
|
||||
|
||||
class AirportWithMetar : public FGPositioned::Filter
|
||||
{
|
||||
public:
|
||||
virtual bool pass(FGPositioned* aPos) const
|
||||
{
|
||||
if ((aPos->type() < FGPositioned::AIRPORT) || (aPos->type() > FGPositioned::SEAPORT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FGAirport* apt = static_cast<FGAirport*>(aPos);
|
||||
return apt->getMetar();
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FGEnvironmentCtrl abstract base class.
|
||||
|
@ -645,10 +653,9 @@ double FGMetarEnvironmentCtrl::interpolate_val(double currentval,
|
|||
void
|
||||
FGMetarEnvironmentCtrl::init ()
|
||||
{
|
||||
const SGPropertyNode *longitude
|
||||
= fgGetNode( "/position/longitude-deg", true );
|
||||
const SGPropertyNode *latitude
|
||||
= fgGetNode( "/position/latitude-deg", true );
|
||||
SGGeod pos = SGGeod::fromDeg(
|
||||
fgGetDouble("/position/longitude-deg", true),
|
||||
fgGetDouble( "/position/latitude-deg", true));
|
||||
|
||||
metar_loaded = false;
|
||||
bool found_metar = false;
|
||||
|
@ -659,33 +666,32 @@ FGMetarEnvironmentCtrl::init ()
|
|||
metar_max_age->setLongValue(0);
|
||||
|
||||
while ( !found_metar && (_error_count < 3) ) {
|
||||
const FGAirport* a = globals->get_airports()
|
||||
->search( longitude->getDoubleValue(),
|
||||
latitude->getDoubleValue(),
|
||||
360.0,
|
||||
metar_only );
|
||||
if ( a ) {
|
||||
FGMetarResult result = fetch_data( a->getId() );
|
||||
if ( result.m != NULL ) {
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = "
|
||||
<< a->getId());
|
||||
last_apt = a;
|
||||
_icao = a->getId();
|
||||
search_elapsed = 0.0;
|
||||
fetch_elapsed = 0.0;
|
||||
update_metar_properties( result.m );
|
||||
update_env_config();
|
||||
env->init();
|
||||
found_metar = true;
|
||||
} else {
|
||||
// mark as no metar so it doesn't show up in subsequent
|
||||
// searches.
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "no metar at metar = "
|
||||
<< a->getId() );
|
||||
globals->get_airports()->no_metar( a->getId() );
|
||||
}
|
||||
AirportWithMetar filter;
|
||||
FGPositionedRef a = FGPositioned::findClosest(pos, 10000.0, &filter);
|
||||
if (!a) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FGMetarResult result = fetch_data(a->ident());
|
||||
if ( result.m != NULL ) {
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = "
|
||||
<< a->ident());
|
||||
last_apt = a;
|
||||
_icao = a->ident();
|
||||
search_elapsed = 0.0;
|
||||
fetch_elapsed = 0.0;
|
||||
update_metar_properties( result.m );
|
||||
update_env_config();
|
||||
env->init();
|
||||
found_metar = true;
|
||||
} else {
|
||||
// mark as no metar so it doesn't show up in subsequent
|
||||
// searches.
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "no metar at metar = " << a->ident() );
|
||||
static_cast<FGAirport*>(a.ptr())->setMetar(false);
|
||||
}
|
||||
} // of airprot-with-metar search iteration
|
||||
|
||||
metar_max_age->setLongValue(max_age);
|
||||
}
|
||||
|
||||
|
@ -702,7 +708,6 @@ FGMetarEnvironmentCtrl::reinit ()
|
|||
void
|
||||
FGMetarEnvironmentCtrl::update(double delta_time_sec)
|
||||
{
|
||||
|
||||
_dt += delta_time_sec;
|
||||
if (_error_count >= 3)
|
||||
return;
|
||||
|
@ -713,6 +718,9 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec)
|
|||
= fgGetNode( "/position/longitude-deg", true );
|
||||
static const SGPropertyNode *latitude
|
||||
= fgGetNode( "/position/latitude-deg", true );
|
||||
SGGeod pos = SGGeod::fromDeg(longitude->getDoubleValue(),
|
||||
latitude->getDoubleValue());
|
||||
|
||||
search_elapsed += delta_time_sec;
|
||||
fetch_elapsed += delta_time_sec;
|
||||
interpolate_elapsed += delta_time_sec;
|
||||
|
@ -720,20 +728,17 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec)
|
|||
// if time for a new search request, push it onto the request
|
||||
// queue
|
||||
if ( search_elapsed > search_interval_sec ) {
|
||||
const FGAirport* a = globals->get_airports()
|
||||
->search( longitude->getDoubleValue(),
|
||||
latitude->getDoubleValue(),
|
||||
360.0,
|
||||
metar_only );
|
||||
if ( a ) {
|
||||
if ( !last_apt || last_apt->getId() != a->getId()
|
||||
AirportWithMetar filter;
|
||||
FGPositionedRef a = FGPositioned::findClosest(pos, 10000.0, &filter);
|
||||
if (a) {
|
||||
if ( !last_apt || last_apt->ident() != a->ident()
|
||||
|| fetch_elapsed > same_station_interval_sec )
|
||||
{
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = "
|
||||
<< a->getId());
|
||||
request_queue.push( a->getId() );
|
||||
<< a->ident());
|
||||
request_queue.push( a->ident() );
|
||||
last_apt = a;
|
||||
_icao = a->getId();
|
||||
_icao = a->ident();
|
||||
search_elapsed = 0.0;
|
||||
fetch_elapsed = 0.0;
|
||||
} else {
|
||||
|
@ -741,8 +746,9 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec)
|
|||
SG_LOG( SG_GENERAL, SG_INFO, "same station, waiting = "
|
||||
<< same_station_interval_sec - fetch_elapsed );
|
||||
}
|
||||
|
||||
} else {
|
||||
SG_LOG( SG_GENERAL, SG_WARN,
|
||||
SG_LOG( SG_GENERAL, SG_WARN,
|
||||
"Unable to find any airports with metar" );
|
||||
}
|
||||
} else if ( interpolate_elapsed > EnvironmentUpdatePeriodSec ) {
|
||||
|
@ -781,7 +787,8 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec)
|
|||
// searches, and signal an immediate re-search.
|
||||
SG_LOG( SG_GENERAL, SG_WARN,
|
||||
"no metar at station = " << result.icao );
|
||||
globals->get_airports()->no_metar( result.icao );
|
||||
const FGAirport* apt = globals->get_airports()->search(result.icao);
|
||||
const_cast<FGAirport*>(apt)->setMetar(false);
|
||||
search_elapsed = 9999.0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,34 +23,25 @@
|
|||
#ifndef _ENVIRONMENT_CTRL_HXX
|
||||
#define _ENVIRONMENT_CTRL_HXX
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/environment/metar.hxx>
|
||||
|
||||
#if defined(ENABLE_THREADS)
|
||||
# include <OpenThreads/Thread>
|
||||
# include <simgear/threads/SGQueue.hxx>
|
||||
#endif
|
||||
|
||||
#include <cmath>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
using std::queue;
|
||||
using std::vector;
|
||||
#include "Navaids/positioned.hxx"
|
||||
#include "Environment/environment.hxx"
|
||||
|
||||
// forward decls
|
||||
class SGPropertyNode;
|
||||
class FGAirport;
|
||||
class FGMetar;
|
||||
|
||||
#include "environment.hxx"
|
||||
#include "fgmetar.hxx"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Interface to control environment information for a specific location.
|
||||
*/
|
||||
|
@ -133,20 +124,20 @@ private:
|
|||
static bool lessThan(bucket *a, bucket *b);
|
||||
};
|
||||
|
||||
void read_table (const SGPropertyNode * node, vector<bucket *> &table);
|
||||
void do_interpolate (vector<bucket *> &table, double altitude_ft,
|
||||
void read_table (const SGPropertyNode * node, std::vector<bucket *> &table);
|
||||
void do_interpolate (std::vector<bucket *> &table, double altitude_ft,
|
||||
FGEnvironment * environment);
|
||||
|
||||
FGEnvironment env1, env2; // temporaries
|
||||
|
||||
vector<bucket *> _boundary_table;
|
||||
vector<bucket *> _aloft_table;
|
||||
std::vector<bucket *> _boundary_table;
|
||||
std::vector<bucket *> _aloft_table;
|
||||
};
|
||||
|
||||
|
||||
// A convenience wrapper around FGMetar
|
||||
struct FGMetarResult {
|
||||
string icao;
|
||||
std::string icao;
|
||||
FGMetar *m;
|
||||
};
|
||||
|
||||
|
@ -169,7 +160,7 @@ public:
|
|||
private:
|
||||
FGInterpolateEnvironmentCtrl *env;
|
||||
|
||||
string _icao;
|
||||
std::string _icao;
|
||||
bool metar_loaded;
|
||||
float station_elevation_ft;
|
||||
float search_interval_sec;
|
||||
|
@ -177,7 +168,7 @@ private:
|
|||
float search_elapsed;
|
||||
float fetch_elapsed;
|
||||
float interpolate_elapsed;
|
||||
const FGAirport *last_apt;
|
||||
FGPositionedRef last_apt;
|
||||
SGPropertyNode_ptr proxy_host;
|
||||
SGPropertyNode_ptr proxy_port;
|
||||
SGPropertyNode_ptr proxy_auth;
|
||||
|
@ -209,7 +200,7 @@ private:
|
|||
/**
|
||||
* FIFO queue which holds a pointer to the fetched metar data.
|
||||
*/
|
||||
SGBlockingQueue < string > request_queue;
|
||||
SGBlockingQueue <std::string > request_queue;
|
||||
|
||||
/**
|
||||
* FIFO queue which holds a pointer to the fetched metar data.
|
||||
|
@ -219,12 +210,12 @@ private:
|
|||
/**
|
||||
* FIFO queue which holds a pointer to the fetched metar data.
|
||||
*/
|
||||
queue < string > request_queue;
|
||||
std::queue <std::string > request_queue;
|
||||
|
||||
/**
|
||||
* FIFO queue which holds a pointer to the fetched metar data.
|
||||
*/
|
||||
queue < FGMetarResult > result_queue;
|
||||
std::queue < FGMetarResult > result_queue;
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_THREADS)
|
||||
|
|
|
@ -4254,9 +4254,14 @@ MK_VIII::Mode6Handler::test_airport (const FGAirport *airport)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool MK_VIII::Mode6Handler::AirportFilter::pass(FGAirport* a)
|
||||
bool MK_VIII::Mode6Handler::AirportFilter::pass(FGPositioned* a) const
|
||||
{
|
||||
return self->test_airport(a);
|
||||
if (a->type() != FGPositioned::AIRPORT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ok = self->test_airport(static_cast<FGAirport*>(a));
|
||||
return ok;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -4269,20 +4274,19 @@ MK_VIII::Mode6Handler::update_runway ()
|
|||
}
|
||||
|
||||
// Search for the closest runway threshold in range 5
|
||||
// nm. Passing 0.5 degrees (approximatively 30 nm) to
|
||||
// nm. Passing 30nm to
|
||||
// get_closest_airport() provides enough margin for large
|
||||
// airports, which may have a runway located far away from the
|
||||
// airport's reference point.
|
||||
AirportFilter filter(this);
|
||||
const FGAirport *airport = globals->get_airports()->search(
|
||||
mk_data(gps_latitude).get(), mk_data(gps_longitude).get(),
|
||||
0.5, filter);
|
||||
|
||||
if (airport) {
|
||||
runway.elevation = airport->getElevation();
|
||||
FGPositionedRef apt = FGPositioned::findClosest(
|
||||
SGGeod::fromDeg(mk_data(gps_longitude).get(), mk_data(gps_latitude).get()),
|
||||
30.0, &filter);
|
||||
if (apt) {
|
||||
runway.elevation = apt->elevation();
|
||||
}
|
||||
|
||||
has_runway.set(airport != NULL);
|
||||
has_runway.set(apt != NULL);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -4493,17 +4497,16 @@ MK_VIII::TCFHandler::select_runway (const FGAirport *airport)
|
|||
return _runway;
|
||||
}
|
||||
|
||||
bool MK_VIII::TCFHandler::AirportFilter::pass(FGAirport *a)
|
||||
bool MK_VIII::TCFHandler::AirportFilter::pass(FGPositioned* aPos) const
|
||||
{
|
||||
for (unsigned int r=0; r<a->numRunways(); ++r) {
|
||||
if (a->getRunwayByIndex(r)->lengthFt() >= mk->conf.runway_database) {
|
||||
return true;
|
||||
}
|
||||
if (aPos->type() != FGPositioned::AIRPORT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
FGAirport* apt = static_cast<FGAirport*>(aPos);
|
||||
return apt->hasHardRunwayOfLengthFt(mk->conf.runway_database);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MK_VIII::TCFHandler::update_runway ()
|
||||
{
|
||||
|
@ -4513,25 +4516,25 @@ MK_VIII::TCFHandler::update_runway ()
|
|||
}
|
||||
|
||||
// Search for the intended destination runway of the closest
|
||||
// airport in range 15 nm. Passing 0.5 degrees (approximatively
|
||||
// 30 nm) to get_closest_airport() provides enough margin for
|
||||
// airport in range 15 nm. Passing 30nm to get_closest_airport()
|
||||
// provides enough margin for
|
||||
// large airports, which may have a runway located far away from
|
||||
// the airport's reference point.
|
||||
AirportFilter filter(mk);
|
||||
const FGAirport *airport = globals->get_airports()->search(
|
||||
mk_data(gps_longitude).get(), mk_data(gps_latitude).get(),
|
||||
0.5, filter);
|
||||
|
||||
if (!airport) return;
|
||||
FGPositionedRef apt = FGPositioned::findClosest(
|
||||
SGGeod::fromDeg(mk_data(gps_longitude).get(), mk_data(gps_latitude).get()),
|
||||
30.0, &filter);
|
||||
|
||||
if (!apt) return;
|
||||
|
||||
has_runway = true;
|
||||
|
||||
FGRunway* _runway = select_runway(airport);
|
||||
|
||||
FGRunway* _runway = select_runway(static_cast<FGAirport*>(apt.ptr()));
|
||||
|
||||
runway.center.latitude = _runway->latitude();
|
||||
runway.center.longitude = _runway->longitude();
|
||||
|
||||
runway.elevation = airport->getElevation();
|
||||
runway.elevation = apt->elevation();
|
||||
|
||||
double half_length_m = _runway->lengthM() * 0.5;
|
||||
runway.half_length = half_length_m * SG_METER_TO_NM;
|
||||
|
|
|
@ -1505,13 +1505,13 @@ private:
|
|||
unsigned int get_bank_angle_alerts ();
|
||||
void update_bank_angle ();
|
||||
|
||||
class AirportFilter : public FGAirportSearchFilter
|
||||
class AirportFilter : public FGPositioned::Filter
|
||||
{
|
||||
public:
|
||||
AirportFilter(Mode6Handler *s)
|
||||
: self(s) {}
|
||||
|
||||
virtual bool pass(FGAirport *a);
|
||||
virtual bool pass(FGPositioned *a) const;
|
||||
|
||||
private:
|
||||
Mode6Handler* self;
|
||||
|
@ -1578,13 +1578,13 @@ private:
|
|||
bool is_tcf ();
|
||||
bool is_rfcf ();
|
||||
|
||||
class AirportFilter : public FGAirportSearchFilter
|
||||
class AirportFilter : public FGPositioned::Filter
|
||||
{
|
||||
public:
|
||||
AirportFilter(MK_VIII *device)
|
||||
: mk(device) {}
|
||||
|
||||
virtual bool pass(FGAirport *a);
|
||||
virtual bool pass(FGPositioned *a) const;
|
||||
|
||||
private:
|
||||
MK_VIII* mk;
|
||||
|
|
|
@ -497,19 +497,23 @@ static naRef f_geodinfo(naContext c, naRef me, int argc, naRef* args)
|
|||
#undef HASHSET
|
||||
}
|
||||
|
||||
|
||||
class airport_filter : public FGAirportSearchFilter {
|
||||
virtual bool pass(FGAirport *a) { return a->isAirport(); }
|
||||
} airport;
|
||||
class seaport_filter : public FGAirportSearchFilter {
|
||||
virtual bool pass(FGAirport *a) { return a->isSeaport(); }
|
||||
} seaport;
|
||||
class heliport_filter : public FGAirportSearchFilter {
|
||||
virtual bool pass(FGAirport *a) { return a->isHeliport(); }
|
||||
} heliport;
|
||||
class AirportInfoFilter : public FGPositioned::Filter
|
||||
{
|
||||
public:
|
||||
AirportInfoFilter() :
|
||||
type(FGPositioned::AIRPORT)
|
||||
{ }
|
||||
|
||||
virtual bool pass(FGPositioned* aPos) const
|
||||
{
|
||||
return (aPos->type() == type);
|
||||
}
|
||||
|
||||
FGPositioned::Type type;
|
||||
};
|
||||
|
||||
// Returns data hash for particular or nearest airport of a <type>, or nil
|
||||
// on error. Only one side of each runway is contained.
|
||||
// on error.
|
||||
//
|
||||
// airportinfo(<id>); e.g. "KSFO"
|
||||
// airportinfo(<type>); type := ("airport"|"seaport"|"heliport")
|
||||
|
@ -519,38 +523,50 @@ static naRef f_airportinfo(naContext c, naRef me, int argc, naRef* args)
|
|||
{
|
||||
static SGConstPropertyNode_ptr latn = fgGetNode("/position/latitude-deg", true);
|
||||
static SGConstPropertyNode_ptr lonn = fgGetNode("/position/longitude-deg", true);
|
||||
double lat, lon;
|
||||
|
||||
FGAirportList *aptlst = globals->get_airports();
|
||||
FGAirport *apt;
|
||||
SGGeod pos;
|
||||
FGPositionedRef ref;
|
||||
|
||||
if(argc >= 2 && naIsNum(args[0]) && naIsNum(args[1])) {
|
||||
lat = args[0].num;
|
||||
lon = args[1].num;
|
||||
pos = SGGeod::fromDeg(args[1].num, args[0].num);
|
||||
args += 2;
|
||||
argc -= 2;
|
||||
} else {
|
||||
lat = latn->getDoubleValue();
|
||||
lon = lonn->getDoubleValue();
|
||||
pos = SGGeod::fromDeg(lonn->getDoubleValue(), latn->getDoubleValue());
|
||||
}
|
||||
|
||||
double maxRange = 360.0; // expose this? or pick a smaller value?
|
||||
double maxRange = 10000.0; // expose this? or pick a smaller value?
|
||||
|
||||
AirportInfoFilter filter; // defaults to airports only
|
||||
|
||||
if(argc == 0) {
|
||||
apt = aptlst->search(lon, lat, maxRange, airport);
|
||||
// fine, just fall through and use AIRPORT
|
||||
} else if(argc == 1 && naIsString(args[0])) {
|
||||
const char *s = naStr_data(args[0]);
|
||||
if(!strcmp(s, "airport")) apt = aptlst->search(lon, lat, maxRange, airport);
|
||||
else if(!strcmp(s, "seaport")) apt = aptlst->search(lon, lat, maxRange, seaport);
|
||||
else if(!strcmp(s, "heliport")) apt = aptlst->search(lon, lat, maxRange, heliport);
|
||||
else apt = aptlst->search(s);
|
||||
if (!strcmp(s, "airport")) filter.type = FGPositioned::AIRPORT;
|
||||
else if(!strcmp(s, "seaport")) filter.type = FGPositioned::SEAPORT;
|
||||
else if(!strcmp(s, "heliport")) filter.type = FGPositioned::HELIPORT;
|
||||
else {
|
||||
// user provided an <id>, hopefully
|
||||
ref = globals->get_airports()->search(s);
|
||||
if (!ref) {
|
||||
naRuntimeError(c, "airportinfo() couldn't find airport:%s", s);
|
||||
return naNil();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
naRuntimeError(c, "airportinfo() with invalid function arguments");
|
||||
return naNil();
|
||||
}
|
||||
if(!apt) return naNil();
|
||||
|
||||
string id = apt->getId();
|
||||
string name = apt->getName();
|
||||
|
||||
if (!ref) {
|
||||
ref = FGPositioned::findClosest(pos, maxRange, &filter);
|
||||
}
|
||||
|
||||
if(!ref) return naNil();
|
||||
FGAirport *apt = static_cast<FGAirport*>(ref.ptr());
|
||||
|
||||
string id = apt->ident();
|
||||
string name = apt->name();
|
||||
|
||||
// set runway hash
|
||||
naRef rwys = naNewHash(c);
|
||||
|
|
Loading…
Add table
Reference in a new issue