From e2bf85e67ebe9d53a6d9b3664988d263b3cc412a Mon Sep 17 00:00:00 2001 From: fredb Date: Tue, 9 Dec 2008 07:58:46 +0000 Subject: [PATCH] James Turner : this patch - updates how filtering is done on the various FGPositioned query functions - both spatial and ident-based. - updates the KLN-89b / DCLGPS code to use FGPositioned for all Navaid/Airport queries. me: Add few include directives in globals.cxx to avoid such MSVC warning messages : deletion of pointer to incomplete type 'FGAirportList'; no destructor called deletion of pointer to incomplete type 'FGNavList'; no destructor called deletion of pointer to incomplete type 'FGTACANList'; no destructor called deletion of pointer to incomplete type 'FGFixList'; no destructor called --- src/Instrumentation/KLN89/kln89.cxx | 1 + src/Instrumentation/KLN89/kln89_page_apt.cxx | 8 +- src/Instrumentation/KLN89/kln89_page_int.cxx | 1 + src/Instrumentation/KLN89/kln89_page_ndb.cxx | 1 + src/Instrumentation/KLN89/kln89_page_vor.cxx | 1 + src/Instrumentation/dclgps.cxx | 232 ++++++++----------- src/Instrumentation/dclgps.hxx | 20 +- src/Main/globals.cxx | 3 + src/Navaids/positioned.cxx | 89 ++++--- src/Navaids/positioned.hxx | 65 +++++- 10 files changed, 236 insertions(+), 185 deletions(-) diff --git a/src/Instrumentation/KLN89/kln89.cxx b/src/Instrumentation/KLN89/kln89.cxx index 81a9b0aeb..70c948fd9 100644 --- a/src/Instrumentation/KLN89/kln89.cxx +++ b/src/Instrumentation/KLN89/kln89.cxx @@ -46,6 +46,7 @@ #include #include
#include +#include "Airports/simple.hxx" using std::cout; diff --git a/src/Instrumentation/KLN89/kln89_page_apt.cxx b/src/Instrumentation/KLN89/kln89_page_apt.cxx index b370d54ad..e42121519 100644 --- a/src/Instrumentation/KLN89/kln89_page_apt.cxx +++ b/src/Instrumentation/KLN89/kln89_page_apt.cxx @@ -26,10 +26,10 @@ #endif #include "kln89_page_apt.hxx" -#include -#include
-#include - +#include "ATCDCL/commlist.hxx" +#include "Main/globals.hxx" +#include "Airports/runways.hxx" +#include "Airports/simple.hxx" // This function is copied from Airports/runways.cxx // TODO - Make the original properly available and remove this instance!!!! diff --git a/src/Instrumentation/KLN89/kln89_page_int.cxx b/src/Instrumentation/KLN89/kln89_page_int.cxx index 581580f2a..de5803416 100644 --- a/src/Instrumentation/KLN89/kln89_page_int.cxx +++ b/src/Instrumentation/KLN89/kln89_page_int.cxx @@ -27,6 +27,7 @@ #include "kln89_page_int.hxx" #include "Navaids/fix.hxx" +#include "Navaids/navrecord.hxx" KLN89IntPage::KLN89IntPage(KLN89* parent) : KLN89Page(parent) { diff --git a/src/Instrumentation/KLN89/kln89_page_ndb.cxx b/src/Instrumentation/KLN89/kln89_page_ndb.cxx index 07e4a8385..7bc6f2848 100644 --- a/src/Instrumentation/KLN89/kln89_page_ndb.cxx +++ b/src/Instrumentation/KLN89/kln89_page_ndb.cxx @@ -26,6 +26,7 @@ #endif #include "kln89_page_ndb.hxx" +#include "Navaids/navrecord.hxx" KLN89NDBPage::KLN89NDBPage(KLN89* parent) : KLN89Page(parent) { diff --git a/src/Instrumentation/KLN89/kln89_page_vor.cxx b/src/Instrumentation/KLN89/kln89_page_vor.cxx index daaf8ae03..1b9fb0ace 100644 --- a/src/Instrumentation/KLN89/kln89_page_vor.cxx +++ b/src/Instrumentation/KLN89/kln89_page_vor.cxx @@ -26,6 +26,7 @@ #endif #include "kln89_page_vor.hxx" +#include "Navaids/navrecord.hxx" KLN89VorPage::KLN89VorPage(KLN89* parent) : KLN89Page(parent) { diff --git a/src/Instrumentation/dclgps.cxx b/src/Instrumentation/dclgps.cxx index d1ab7ef02..35141c9dc 100644 --- a/src/Instrumentation/dclgps.cxx +++ b/src/Instrumentation/dclgps.cxx @@ -32,11 +32,12 @@ #include
#include +#include +#include #include -using std::cout; -//using namespace std; +using namespace std; // Command callbacks for FlightGear @@ -140,31 +141,43 @@ string GPSWaypoint::GetAprId() { else return(id); } -GPSWaypoint* GPSWaypoint::createFromFix(const FGFix* aFix) +static GPSWpType +GPSWpTypeFromFGPosType(FGPositioned::Type aType) { - assert(aFix); - return new GPSWaypoint(aFix->get_ident(), - aFix->get_lat() * SG_DEGREES_TO_RADIANS, - aFix->get_lon() * SG_DEGREES_TO_RADIANS, - GPS_WP_INT); + switch (aType) { + case FGPositioned::AIRPORT: + case FGPositioned::SEAPORT: + case FGPositioned::HELIPORT: + return GPS_WP_APT; + + case FGPositioned::VOR: + return GPS_WP_VOR; + + case FGPositioned::NDB: + return GPS_WP_NDB; + + case FGPositioned::WAYPOINT: + return GPS_WP_USR; + + case FGPositioned::FIX: + return GPS_WP_INT; + + default: + return GPS_WP_USR; + } } -GPSWaypoint* GPSWaypoint::createFromNav(const FGNavRecord* aNav) +GPSWaypoint* GPSWaypoint::createFromPositioned(const FGPositioned* aPos) { - assert(aNav); - return new GPSWaypoint(aNav->get_ident(), - aNav->get_lat() * SG_DEGREES_TO_RADIANS, - aNav->get_lon() * SG_DEGREES_TO_RADIANS, - (aNav->get_fg_type() == FG_NAV_VOR ? GPS_WP_VOR : GPS_WP_NDB)); -} - -GPSWaypoint* GPSWaypoint::createFromAirport(const FGAirport* aApt) -{ - assert(aApt); - return new GPSWaypoint(aApt->getId(), - aApt->getLatitude() * SG_DEGREES_TO_RADIANS, - aApt->getLongitude() * SG_DEGREES_TO_RADIANS, - GPS_WP_APT); + if (!aPos) { + return NULL; // happens if find returns no match + } + + return new GPSWaypoint(aPos->ident(), + aPos->latitude() * SG_DEGREES_TO_RADIANS, + aPos->longitude() * SG_DEGREES_TO_RADIANS, + GPSWpTypeFromFGPosType(aPos->type()) + ); } ostream& operator << (ostream& os, GPSAppWpType type) { @@ -1071,132 +1084,83 @@ public: } }; +class DCLGPSFilter : public FGPositioned::Filter +{ +public: + virtual bool pass(const FGPositioned* aPos) const { + switch (aPos->type()) { + case FGPositioned::AIRPORT: + // how about heliports and seaports? + case FGPositioned::NDB: + case FGPositioned::VOR: + case FGPositioned::WAYPOINT: + case FGPositioned::FIX: + break; + default: return false; // reject all other types + } + return true; + } +}; + GPSWaypoint* DCLGPS::FindFirstById(const string& id) const { - stringOrderKLN89 ordering; - nav_list_type vors = globals->get_navlist()->findFirstByIdent(id, FG_NAV_VOR, false); - nav_list_type ndbs = globals->get_navlist()->findFirstByIdent(id, FG_NAV_NDB, false); - const FGFix* fix = globals->get_fixlist()->findFirstByIdent(id, &ordering); - const FGAirport* apt = globals->get_airports()->findFirstById(id, &ordering); - // search local gps waypoints (USR) - -// pick the best - ugly logic, sorry. This is a temporary fix to getting rid -// of the huge local waypoint table, it'll die when there's a way to query -// this stuff centrally. -// what we're doing is using map inserts to order the result, then using -// the first entry (begin()) as the lowest, hence best, match - map sorter; - if (fix) sorter[fix->get_ident()] = GPS_WP_INT; - if (apt) sorter[apt->getId()] = GPS_WP_APT; - if (!vors.empty()) sorter[vors.front()->get_ident()] = GPS_WP_VOR; - if (!ndbs.empty()) sorter[ndbs.front()->get_ident()] = GPS_WP_NDB; - - if (sorter.empty()) return NULL; // no results at all - GPSWpType ty = sorter.begin()->second; - - switch (ty) { - case GPS_WP_INT: - return GPSWaypoint::createFromFix(fix); - - case GPS_WP_APT: - return GPSWaypoint::createFromAirport(apt); - - case GPS_WP_VOR: - return GPSWaypoint::createFromNav(vors.front()); - - case GPS_WP_NDB: - return GPSWaypoint::createFromNav(ndbs.front()); - default: - return NULL; // can't happen - } + DCLGPSFilter filter; + FGPositionedRef result = FGPositioned::findNextWithPartialId(NULL, id, &filter); + return GPSWaypoint::createFromPositioned(result); } GPSWaypoint* DCLGPS::FindFirstByExactId(const string& id) const { - if (const FGAirport* apt = globals->get_airports()->search(id)) { - return GPSWaypoint::createFromAirport(apt); - } - - if (const FGFix* fix = globals->get_fixlist()->search(id)) { - return GPSWaypoint::createFromFix(fix); - } - - nav_list_type vors = globals->get_navlist()->findFirstByIdent(id, FG_NAV_VOR, true); - if (!vors.empty()) { - return GPSWaypoint::createFromNav(vors.front()); - } - - nav_list_type ndbs = globals->get_navlist()->findFirstByIdent(id, FG_NAV_NDB, true); - if (!ndbs.empty()) { - return GPSWaypoint::createFromNav(ndbs.front()); - } - - return NULL; -} - -// Host specific lookup functions -// TODO - add the ASCII / alphabetical stuff from the Atlas version -FGNavRecord* DCLGPS::FindFirstVorById(const string& id, bool &multi, bool exact) { - // NOTE - at the moment multi is never set. - multi = false; - //if(exact) return(_overlays->FindFirstVorById(id, exact)); - - nav_list_type nav = globals->get_navlist()->findFirstByIdent(id, FG_NAV_VOR, exact); - - if(nav.size() > 1) multi = true; - //return(nav.empty() ? NULL : *(nav.begin())); - - // The above is sort of what we want - unfortunately we can't guarantee no NDB/ILS at the moment - if(nav.empty()) return(NULL); - - for(nav_list_iterator it = nav.begin(); it != nav.end(); ++it) { - if((*it)->type() == FGPositioned::VOR) return(*it); - } - return(NULL); // Shouldn't get here! + SGGeod pos(SGGeod::fromRad(_lon, _lat)); + FGPositionedRef result = FGPositioned::findClosestWithIdent(id, pos); + return GPSWaypoint::createFromPositioned(result); } // TODO - add the ASCII / alphabetical stuff from the Atlas version -FGNavRecord* DCLGPS::FindFirstNDBById(const string& id, bool &multi, bool exact) { - // NOTE - at the moment multi is never set. - multi = false; - //if(exact) return(_overlays->FindFirstVorById(id, exact)); - - nav_list_type nav = globals->get_navlist()->findFirstByIdent(id, FG_NAV_NDB, exact); - - if(nav.size() > 1) multi = true; - //return(nav.empty() ? NULL : *(nav.begin())); - - // The above is sort of what we want - unfortunately we can't guarantee no NDB/ILS at the moment - if(nav.empty()) return(NULL); - - for(nav_list_iterator it = nav.begin(); it != nav.end(); ++it) { - if((*it)->type() == FGPositioned::NDB) return(*it); - } - return(NULL); // Shouldn't get here! +FGPositioned* DCLGPS::FindTypedFirstById(const string& id, FGPositioned::Type ty, bool &multi, bool exact) +{ + multi = false; + FGPositioned::TypeFilter filter(ty); + + if (exact) { + FGPositioned::List matches = + FGPositioned::findAllWithIdentSortedByRange(id, SGGeod::fromRad(_lon, _lat), &filter); + multi = (matches.size() > 1); + return matches.empty() ? NULL : matches.front().ptr(); + } + + return FGPositioned::findNextWithPartialId(NULL, id, &filter); } -const FGFix* DCLGPS::FindFirstIntById(const string& id, bool &multi, bool exact) { - // NOTE - at the moment multi is never set, and indeed can't be - // since FG can only map one Fix per ID at the moment. - multi = false; - if (exact) return globals->get_fixlist()->search(id); - - stringOrderKLN89 ordering; - return globals->get_fixlist()->findFirstByIdent(id, &ordering); +FGNavRecord* DCLGPS::FindFirstVorById(const string& id, bool &multi, bool exact) +{ + return dynamic_cast(FindTypedFirstById(id, FGPositioned::VOR, multi, exact)); } -const FGAirport* DCLGPS::FindFirstAptById(const string& id, bool &multi, bool exact) { - // NOTE - at the moment multi is never set. - //cout << "FindFirstAptById, id = " << id << '\n'; - multi = false; - if(exact) return(globals->get_airports()->search(id)); - - stringOrderKLN89 ordering; - return globals->get_airports()->findFirstById(id, &ordering); +FGNavRecord* DCLGPS::FindFirstNDBById(const string& id, bool &multi, bool exact) +{ + return dynamic_cast(FindTypedFirstById(id, FGPositioned::NDB, multi, exact)); } -FGNavRecord* DCLGPS::FindClosestVor(double lat_rad, double lon_rad) { - return(globals->get_navlist()->findClosest(lon_rad, lat_rad, 0.0, FG_NAV_VOR)); +const FGFix* DCLGPS::FindFirstIntById(const string& id, bool &multi, bool exact) +{ + return dynamic_cast(FindTypedFirstById(id, FGPositioned::FIX, multi, exact)); +} + +const FGAirport* DCLGPS::FindFirstAptById(const string& id, bool &multi, bool exact) +{ + return dynamic_cast(FindTypedFirstById(id, FGPositioned::AIRPORT, multi, exact)); +} + +FGNavRecord* DCLGPS::FindClosestVor(double lat_rad, double lon_rad) { + FGPositioned::TypeFilter filter(FGPositioned::VOR); + double cutoff = 1000; // nautical miles + FGPositionedRef v = FGPositioned::findClosest(SGGeod::fromRad(lon_rad, lat_rad), cutoff, &filter); + if (!v) { + return NULL; + } + + return dynamic_cast(v.ptr()); } //---------------------------------------------------------------------------------------------------------- diff --git a/src/Instrumentation/dclgps.hxx b/src/Instrumentation/dclgps.hxx index 3766e6932..435f7899a 100644 --- a/src/Instrumentation/dclgps.hxx +++ b/src/Instrumentation/dclgps.hxx @@ -32,15 +32,16 @@ #include #include -#include -#include -#include -#include #include - -using namespace std; +#include class SGTime; +class FGPositioned; + +// XXX fix me +class FGNavRecord; +class FGAirport; +class FGFix; enum GPSDistanceUnits { GPS_DIST_UNITS_NM = 0, @@ -94,9 +95,7 @@ struct GPSWaypoint { GPSWaypoint(const std::string& aIdent, float lat, float lon, GPSWpType aType); - static GPSWaypoint* createFromFix(const FGFix* aFix); - static GPSWaypoint* createFromNav(const FGNavRecord* aNav); - static GPSWaypoint* createFromAirport(const FGAirport* aApt); + static GPSWaypoint* createFromPositioned(const FGPositioned* aFix); ~GPSWaypoint(); string GetAprId(); // Returns the id with i, f, m or h added if appropriate. (Initial approach fix, final approach fix, etc) @@ -428,6 +427,9 @@ protected: // Find the closest VOR to a position in RADIANS. FGNavRecord* FindClosestVor(double lat_rad, double lon_rad); + // helper to implement the above FindFirstXXX methods + FGPositioned* FindTypedFirstById(const std::string& id, FGPositioned::Type ty, bool &multi, bool exact); + // Position, orientation and velocity. // These should be read from FG's built-in GPS logic if possible. // Use the property node pointers below to do this. diff --git a/src/Main/globals.cxx b/src/Main/globals.cxx index 7ab82e16e..7241af030 100644 --- a/src/Main/globals.cxx +++ b/src/Main/globals.cxx @@ -47,6 +47,9 @@ #include #include #include +#include +#include +#include #include "globals.hxx" #include "renderer.hxx" diff --git a/src/Navaids/positioned.cxx b/src/Navaids/positioned.cxx index e09f0da2c..07af55b1c 100644 --- a/src/Navaids/positioned.cxx +++ b/src/Navaids/positioned.cxx @@ -98,7 +98,7 @@ removeFromIndices(FGPositioned* aPos) } static void -spatialFilterInBucket(const SGBucket& aBucket, const FGPositioned::Filter& aFilter, FGPositioned::List& aResult) +spatialFilterInBucket(const SGBucket& aBucket, FGPositioned::Filter* aFilter, FGPositioned::List& aResult) { SpatialPositionedIndex::const_iterator it; it = global_spatialIndex.find(aBucket.gen_index()); @@ -109,8 +109,13 @@ spatialFilterInBucket(const SGBucket& aBucket, const FGPositioned::Filter& aFilt BucketEntry::const_iterator l = it->second.begin(); BucketEntry::const_iterator u = it->second.end(); + if (!aFilter) { // pass everything + aResult.insert(aResult.end(), l, u); + return; + } + for ( ; l != u; ++l) { - if (aFilter(*l)) { + if ((*aFilter)(*l)) { aResult.push_back(*l); } } @@ -118,7 +123,7 @@ spatialFilterInBucket(const SGBucket& aBucket, const FGPositioned::Filter& aFilt static void spatialFind(const SGGeod& aPos, double aRange, - const FGPositioned::Filter& aFilter, FGPositioned::List& aResult) + FGPositioned::Filter* aFilter, FGPositioned::List& aResult) { SGBucket buck(aPos); double lat = aPos.getLatitudeDeg(), @@ -135,6 +140,7 @@ spatialFind(const SGGeod& aPos, double aRange, } // of i-iteration } +/* class LowerLimitOfType { public: @@ -149,6 +155,7 @@ public: } }; + static void spatialFindTyped(const SGGeod& aPos, double aRange, FGPositioned::Type aLower, FGPositioned::Type aUpper, FGPositioned::List& aResult) { @@ -180,6 +187,7 @@ spatialFindTyped(const SGGeod& aPos, double aRange, FGPositioned::Type aLower, F } // of j-iteration } // of i-iteration } +*/ /** */ @@ -238,8 +246,7 @@ sortByDistance(const SGGeod& aPos, FGPositioned::List& aResult) } static FGPositionedRef -namedFindClosestTyped(const std::string& aIdent, const SGGeod& aOrigin, - FGPositioned::Type aLower, FGPositioned::Type aUpper) +namedFindClosest(const std::string& aIdent, const SGGeod& aOrigin, FGPositioned::Filter* aFilter) { NamedIndexRange range = global_namedIndex.equal_range(aIdent); if (range.first == range.second) { @@ -251,8 +258,7 @@ namedFindClosestTyped(const std::string& aIdent, const SGGeod& aOrigin, NamedPositionedIndex::const_iterator check = range.first; if (++check == range.second) { // excellent, only one match in the range - all we care about is the type - FGPositioned::Type ty = range.first->second->type(); - if ((ty < aLower) || (ty > aUpper)) { + if (aFilter && !aFilter->pass(range.first->second)) { return NULL; // type check failed } @@ -267,7 +273,7 @@ namedFindClosestTyped(const std::string& aIdent, const SGGeod& aOrigin, for (; it != range.second; ++it) { // filter by type FGPositioned::Type ty = it->second->type(); - if ((ty < aLower) || (ty > aUpper)) { + if (aFilter && !aFilter->pass(range.first->second)) { continue; } @@ -284,7 +290,7 @@ namedFindClosestTyped(const std::string& aIdent, const SGGeod& aOrigin, } static FGPositioned::List -spatialGetClosest(const SGGeod& aPos, unsigned int aN, double aCutoffNm, const FGPositioned::Filter& aFilter) +spatialGetClosest(const SGGeod& aPos, unsigned int aN, double aCutoffNm, FGPositioned::Filter* aFilter) { FGPositioned::List result; int radius = 1; // start at 1, radius 0 is handled explicitly @@ -381,28 +387,13 @@ const char* FGPositioned::nameForType(Type aTy) // search / query functions FGPositionedRef -FGPositioned::findClosestWithIdent(const std::string& aIdent, double aLat, double aLon) +FGPositioned::findClosestWithIdent(const std::string& aIdent, const SGGeod& aPos, Filter* aFilter) { - return findClosestWithIdent(aIdent, SGGeod::fromDeg(aLon, aLat)); -} - -FGPositionedRef -FGPositioned::findClosestWithIdent(const std::string& aIdent, const SGGeod& aPos) -{ - return namedFindClosestTyped(aIdent, aPos, INVALID, LAST_TYPE); + return namedFindClosest(aIdent, aPos, aFilter); } FGPositioned::List -FGPositioned::findWithinRangeByType(const SGGeod& aPos, double aRangeNm, Type aTy) -{ - List result; - spatialFindTyped(aPos, aRangeNm, aTy, aTy, result); - filterListByRange(aPos, aRangeNm, result); - return result; -} - -FGPositioned::List -FGPositioned::findWithinRange(const SGGeod& aPos, double aRangeNm, const Filter& aFilter) +FGPositioned::findWithinRange(const SGGeod& aPos, double aRangeNm, Filter* aFilter) { List result; spatialFind(aPos, aRangeNm, aFilter, result); @@ -411,20 +402,60 @@ FGPositioned::findWithinRange(const SGGeod& aPos, double aRangeNm, const Filter& } FGPositioned::List -FGPositioned::findAllWithIdent(const std::string& aIdent) +FGPositioned::findAllWithIdentSortedByRange(const std::string& aIdent, const SGGeod& aPos, Filter* aFilter) { List result; NamedIndexRange range = global_namedIndex.equal_range(aIdent); for (; range.first != range.second; ++range.first) { + if (aFilter && !aFilter->pass(range.first->second)) { + continue; + } + result.push_back(range.first->second); } + sortByDistance(aPos, result); return result; } +FGPositionedRef +FGPositioned::findClosest(const SGGeod& aPos, double aCutoffNm, Filter* aFilter) +{ + FGPositioned::List l(spatialGetClosest(aPos, 1, aCutoffNm, aFilter)); + if (l.empty()) { + return NULL; + } + + assert(l.size() == 1); + return l.front(); +} + FGPositioned::List -FGPositioned::findClosestN(const SGGeod& aPos, unsigned int aN, double aCutoffNm, const Filter& aFilter) +FGPositioned::findClosestN(const SGGeod& aPos, unsigned int aN, double aCutoffNm, Filter* aFilter) { return spatialGetClosest(aPos, aN, aCutoffNm, aFilter); } +FGPositionedRef +FGPositioned::findNextWithPartialId(FGPositionedRef aCur, const std::string& aId, Filter* aFilter) +{ + NamedIndexRange range = global_namedIndex.equal_range(aId); + for (; range.first != range.second; ++range.first) { + FGPositionedRef candidate = range.first->second; + if (aCur == candidate) { + aCur = NULL; // found our start point, next match will pass + continue; + } + + if (aFilter && !aFilter->pass(candidate)) { + continue; + } + + if (!aCur) { + return candidate; + } + } + + return NULL; // fell out, no match in range +} + diff --git a/src/Navaids/positioned.hxx b/src/Navaids/positioned.hxx index 3c2683506..4a0bd4c20 100644 --- a/src/Navaids/positioned.hxx +++ b/src/Navaids/positioned.hxx @@ -71,6 +71,14 @@ public: const std::string& ident() const { return mIdent; } + /** + * Return the name of this positioned. By default this is the same as the + * ident, but for many derived classes it's more meaningful - the aiport or + * navaid name, for example. + */ + virtual const std::string& name() const + { return mIdent; } + const SGGeod& geod() const { return mPosition; } @@ -87,27 +95,64 @@ public: /** * Predicate class to support custom filtering of FGPositioned queries + * Default implementation of this passes any FGPositioned instance. */ class Filter { public: virtual ~Filter() { ; } - virtual bool pass(FGPositioned* aPos) const = 0; + /** + * Over-rideable filter method. Default implementation returns true. + */ + virtual bool pass(FGPositioned* aPos) const + { return true; } bool operator()(FGPositioned* aPos) const { return pass(aPos); } }; - static List findWithinRange(const SGGeod& aPos, double aRangeNm, const Filter& aFilter); - - static List findWithinRangeByType(const SGGeod& aPos, double aRangeNm, Type aTy); - - static FGPositionedRef findClosestWithIdent(const std::string& aIdent, double aLat, double aLon); + class TypeFilter : public Filter + { + public: + TypeFilter(Type aTy) : mType(aTy) { ; } + virtual bool pass(FGPositioned* aPos) const + { return (mType == aPos->type()); } + private: + const Type mType; + }; - static FGPositionedRef findClosestWithIdent(const std::string& aIdent, const SGGeod& aPos); + static List findWithinRange(const SGGeod& aPos, double aRangeNm, Filter* aFilter = NULL); + + static FGPositionedRef findClosestWithIdent(const std::string& aIdent, const SGGeod& aPos, Filter* aFilter = NULL); - static List findAllWithIdent(const std::string& aIdent); + /** + * Find the next item with the specified partial ID, after the 'current' item + * Note this function is not hyper-efficient, particular where the partial id + * spans a large number of candidates. + * + * @param aCur - Current item, or NULL to retrieve the first item with partial id + * @param aId - the (partial) id to lookup + */ + static FGPositionedRef findNextWithPartialId(FGPositionedRef aCur, const std::string& aId, Filter* aFilter = NULL); + + /** + * Find all items with the specified ident, and return then sorted by + * distance from a position + * + * @param aFilter - optional filter on items + */ + static List findAllWithIdentSortedByRange(const std::string& aIdent, const SGGeod& aPos, Filter* aFilter = NULL); + + /** + * Find the closest item to a position, which pass the specified filter + * A cutoff range in NM must be specified, to constrain the search acceptably. + * Very large cutoff values will make this slow. + * + * @result The closest item passing the filter, or NULL + * @param aCutoffNm - maximum distance to search within, in nautical miles + */ + static FGPositionedRef findClosest(const SGGeod& aPos, double aCutoffNm, Filter* aFilter = NULL); /** * Find the closest N items to a position, which pass the specified filter @@ -119,7 +164,9 @@ public: * @param aN - number of matches to find * @param aCutoffNm - maximum distance to search within, in nautical miles */ - static List findClosestN(const SGGeod& aPos, unsigned int aN, double aCutoffNm, const Filter& aFilter); + static List findClosestN(const SGGeod& aPos, unsigned int aN, double aCutoffNm, Filter* aFilter = NULL); + + /** * Debug helper, map a type to a human-readable string