]> git.mxchange.org Git - flightgear.git/commitdiff
James Turner : this patch
authorfredb <fredb>
Tue, 9 Dec 2008 07:58:46 +0000 (07:58 +0000)
committerfredb <fredb>
Tue, 9 Dec 2008 07:58:46 +0000 (07:58 +0000)
- 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
src/Instrumentation/KLN89/kln89_page_apt.cxx
src/Instrumentation/KLN89/kln89_page_int.cxx
src/Instrumentation/KLN89/kln89_page_ndb.cxx
src/Instrumentation/KLN89/kln89_page_vor.cxx
src/Instrumentation/dclgps.cxx
src/Instrumentation/dclgps.hxx
src/Main/globals.cxx
src/Navaids/positioned.cxx
src/Navaids/positioned.hxx

index 81a9b0aeb8b02eecdfeb1fe0f3d10cbbaf8a5ea0..70c948fd957e862d74a7b8aedab03c49c52bf3b2 100644 (file)
@@ -46,6 +46,7 @@
 #include <ATCDCL/ATCProjection.hxx>
 #include <Main/fg_props.hxx>
 #include <simgear/math/point3d.hxx>
+#include "Airports/simple.hxx"
 
 using std::cout;
 
index b370d54ad2b5a2afb910a178a4f879010af8039b..e4212151940376169d77a3cd299fbf610c405f90 100644 (file)
 #endif
 
 #include "kln89_page_apt.hxx"
-#include <ATCDCL/commlist.hxx>
-#include <Main/globals.hxx>
-#include <Airports/runways.hxx>
-
+#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!!!!
index 581580f2a5433584fbaa6bda81dc7c42c9d112b1..de5803416b3b640e39cadc77c9dce7dd7a3d4791 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "kln89_page_int.hxx"
 #include "Navaids/fix.hxx"
+#include "Navaids/navrecord.hxx"
 
 KLN89IntPage::KLN89IntPage(KLN89* parent) 
 : KLN89Page(parent) {
index 07e4a838555579303a66b74a13a22431d5fb8c50..7bc6f2848a931a784599e85a99709dd27792f82f 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 
 #include "kln89_page_ndb.hxx"
+#include "Navaids/navrecord.hxx"
 
 KLN89NDBPage::KLN89NDBPage(KLN89* parent) 
 : KLN89Page(parent) {
index daaf8ae0311287f77765f9790026ea5477b103ab..1b9fb0ace4ac329faff6106460b39694221fc19c 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 
 #include "kln89_page_vor.hxx"
+#include "Navaids/navrecord.hxx"
 
 KLN89VorPage::KLN89VorPage(KLN89* parent) 
 : KLN89Page(parent) {
index d1ab7ef0279cd1a5857bc08a2082705d15140216..35141c9dc4e683d72bca7e92f58ad2cf3229766f 100644 (file)
 
 #include <Main/fg_props.hxx>
 #include <Navaids/fix.hxx>
+#include <Navaids/navrecord.hxx>
+#include <Airports/simple.hxx>
 
 #include <iostream>
-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);
-}
-
-GPSWaypoint* GPSWaypoint::createFromNav(const FGNavRecord* aNav)
-{
-  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));
+  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::createFromAirport(const FGAirport* aApt)
+GPSWaypoint* GPSWaypoint::createFromPositioned(const FGPositioned* aPos)
 {
-  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:
   }
 };
 
-GPSWaypoint* DCLGPS::FindFirstById(const string& id) const
+class DCLGPSFilter : public FGPositioned::Filter
 {
-  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<string, GPSWpType, stringOrderKLN89> 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
+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
+{
+  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());
-  }
+  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
+FGPositioned* DCLGPS::FindTypedFirstById(const string& id, FGPositioned::Type ty, bool &multi, bool exact)
+{
+  multi = false;
+  FGPositioned::TypeFilter filter(ty);
   
-  nav_list_type ndbs = globals->get_navlist()->findFirstByIdent(id, FG_NAV_NDB, true);
-  if (!ndbs.empty()) {
-    return GPSWaypoint::createFromNav(ndbs.front());
+  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 NULL;
+  return FGPositioned::findNextWithPartialId(NULL, id, &filter);
 }
 
-// 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!
+FGNavRecord* DCLGPS::FindFirstVorById(const string& id, bool &multi, bool exact)
+{
+  return dynamic_cast<FGNavRecord*>(FindTypedFirstById(id, FGPositioned::VOR, multi, exact));
 }
 
-// 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!
+FGNavRecord* DCLGPS::FindFirstNDBById(const string& id, bool &multi, bool exact)
+{
+  return dynamic_cast<FGNavRecord*>(FindTypedFirstById(id, FGPositioned::NDB, multi, exact));
 }
 
-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);
+const FGFix* DCLGPS::FindFirstIntById(const string& id, bool &multi, bool exact)
+{
+  return dynamic_cast<FGFix*>(FindTypedFirstById(id, FGPositioned::FIX, 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);
+const FGAirport* DCLGPS::FindFirstAptById(const string& id, bool &multi, bool exact)
+{
+  return dynamic_cast<FGAirport*>(FindTypedFirstById(id, FGPositioned::AIRPORT, 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));
+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<FGNavRecord*>(v.ptr());
 }
 
 //----------------------------------------------------------------------------------------------------------
index 3766e6932d831c35d651538b45420662327b3783..435f7899a25e51f53e5ca4ed2a229a8eee3bcfac 100644 (file)
 #include <vector>
 #include <map>
 
-#include <Navaids/navrecord.hxx>
-#include <Navaids/navlist.hxx>
-#include <Navaids/fixlist.hxx>
-#include <Airports/simple.hxx>
 #include <simgear/structure/subsystem_mgr.hxx>
-
-using namespace std;
+#include <Navaids/positioned.hxx>
 
 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.
index 7ab82e16e1b287697fdcfc82cb243fdac2ab5598..7241af030731b6eac4f8a240d8db671b61bb9fcc 100644 (file)
@@ -47,6 +47,9 @@
 #include <Navaids/awynet.hxx>
 #include <Scenery/scenery.hxx>
 #include <Scenery/tilemgr.hxx>
+#include <Airports\simple.hxx>
+#include <Navaids\navlist.hxx>
+#include <Navaids\fixlist.hxx>
 
 #include "globals.hxx"
 #include "renderer.hxx"
index e09f0da2c5c63800769885d415b2ccd65308a27d..07af55b1cfb5e141f3fd09b28bb74311c9cc306f 100644 (file)
@@ -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)
-{
-  return findClosestWithIdent(aIdent, SGGeod::fromDeg(aLon, aLat));
-}
-
-FGPositionedRef
-FGPositioned::findClosestWithIdent(const std::string& aIdent, const SGGeod& aPos)
+FGPositioned::findClosestWithIdent(const std::string& aIdent, const SGGeod& aPos, Filter* aFilter)
 {
-  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
+}
+
index 3c26835061ef1cc38d19ffa749cd8c59f10881e4..4a0bd4c204e73977f554b7e3dc056ad049a125e0 100644 (file)
@@ -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 List findWithinRange(const SGGeod& aPos, double aRangeNm, Filter* aFilter = NULL);
+        
+  static FGPositionedRef findClosestWithIdent(const std::string& aIdent, const SGGeod& aPos, Filter* aFilter = NULL);
+  
+  /**
+   * 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);
   
-  static FGPositionedRef findClosestWithIdent(const std::string& aIdent, const SGGeod& aPos);
+  /**
+   * 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);
   
-  static List findAllWithIdent(const std::string& aIdent);
+  /**
+   * 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