From 82bfb6a08de380a445b7a7b2f27409731d30bd8b Mon Sep 17 00:00:00 2001 From: jmt Date: Fri, 26 Dec 2008 11:15:00 +0000 Subject: [PATCH] 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. --- src/ATCDCL/AIGAVFRTraffic.cxx | 3 + src/ATCDCL/AIMgr.cxx | 3 + src/Airports/apt_loader.cxx | 2 +- src/Airports/simple.cxx | 62 ---------------- src/Airports/simple.hxx | 31 -------- src/Environment/environment_ctrl.cxx | 105 ++++++++++++++------------- src/Environment/environment_ctrl.hxx | 37 ++++------ src/Instrumentation/mk_viii.cxx | 59 ++++++++------- src/Instrumentation/mk_viii.hxx | 8 +- src/Scripting/NasalSys.cxx | 74 +++++++++++-------- 10 files changed, 157 insertions(+), 227 deletions(-) diff --git a/src/ATCDCL/AIGAVFRTraffic.cxx b/src/ATCDCL/AIGAVFRTraffic.cxx index 811002f23..faaf41e64 100644 --- a/src/ATCDCL/AIGAVFRTraffic.cxx +++ b/src/ATCDCL/AIGAVFRTraffic.cxx @@ -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; diff --git a/src/ATCDCL/AIMgr.cxx b/src/ATCDCL/AIMgr.cxx index 5d4da1d86..36a97783e 100644 --- a/src/ATCDCL/AIMgr.cxx +++ b/src/ATCDCL/AIMgr.cxx @@ -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; diff --git a/src/Airports/apt_loader.cxx b/src/Airports/apt_loader.cxx index 646aedc5c..92495181a 100644 --- a/src/Airports/apt_loader.cxx +++ b/src/Airports/apt_loader.cxx @@ -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(a)->setMetar(true); } } diff --git a/src/Airports/simple.cxx b/src/Airports/simple.cxx index 944dfbb80..e7b9a48d8 100644 --- a/src/Airports/simple.cxx +++ b/src/Airports/simple.cxx @@ -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) { diff --git a/src/Airports/simple.hxx b/src/Airports/simple.hxx index 9a295b251..8b2aaf10f 100644 --- a/src/Airports/simple.hxx +++ b/src/Airports/simple.hxx @@ -31,10 +31,8 @@ #include #include -#include #include -#include #include "Navaids/positioned.hxx" // forward decls @@ -139,14 +137,6 @@ private: std::vector 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 diff --git a/src/Environment/environment_ctrl.cxx b/src/Environment/environment_ctrl.cxx index 677969e70..e0844d81d 100644 --- a/src/Environment/environment_ctrl.cxx +++ b/src/Environment/environment_ctrl.cxx @@ -24,8 +24,6 @@ # include "config.h" #endif -#include -#include #include #include @@ -36,15 +34,25 @@ #include
#include
+#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(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(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(apt)->setMetar(false); search_elapsed = 9999.0; } } diff --git a/src/Environment/environment_ctrl.hxx b/src/Environment/environment_ctrl.hxx index cc2449cae..9538548ec 100644 --- a/src/Environment/environment_ctrl.hxx +++ b/src/Environment/environment_ctrl.hxx @@ -23,34 +23,25 @@ #ifndef _ENVIRONMENT_CTRL_HXX #define _ENVIRONMENT_CTRL_HXX -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - #include #include -#include #if defined(ENABLE_THREADS) # include # include #endif -#include #include #include -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 &table); - void do_interpolate (vector &table, double altitude_ft, + void read_table (const SGPropertyNode * node, std::vector &table); + void do_interpolate (std::vector &table, double altitude_ft, FGEnvironment * environment); FGEnvironment env1, env2; // temporaries - vector _boundary_table; - vector _aloft_table; + std::vector _boundary_table; + std::vector _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 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 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) diff --git a/src/Instrumentation/mk_viii.cxx b/src/Instrumentation/mk_viii.cxx index a310297d6..8908078c9 100755 --- a/src/Instrumentation/mk_viii.cxx +++ b/src/Instrumentation/mk_viii.cxx @@ -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(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; rnumRunways(); ++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(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(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; diff --git a/src/Instrumentation/mk_viii.hxx b/src/Instrumentation/mk_viii.hxx index f13408440..249bdf023 100755 --- a/src/Instrumentation/mk_viii.hxx +++ b/src/Instrumentation/mk_viii.hxx @@ -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; diff --git a/src/Scripting/NasalSys.cxx b/src/Scripting/NasalSys.cxx index 0a10317f9..61055ce4e 100644 --- a/src/Scripting/NasalSys.cxx +++ b/src/Scripting/NasalSys.cxx @@ -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 , or nil -// on error. Only one side of each runway is contained. +// on error. // // airportinfo(); e.g. "KSFO" // airportinfo(); 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 , 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(ref.ptr()); + + string id = apt->ident(); + string name = apt->name(); // set runway hash naRef rwys = naNewHash(c); -- 2.39.5