1
0
Fork 0

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:
jmt 2008-12-26 11:15:00 +00:00
parent 988de9dbca
commit 82bfb6a08d
10 changed files with 157 additions and 227 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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)
{

View file

@ -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

View file

@ -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;
}
}

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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);