]> git.mxchange.org Git - flightgear.git/commitdiff
Fix bug 150 (airports not found in GPS search)
authorJames Turner <zakalawe@mac.com>
Sat, 14 Aug 2010 18:16:28 +0000 (19:16 +0100)
committerJames Turner <zakalawe@mac.com>
Sat, 14 Aug 2010 18:16:28 +0000 (19:16 +0100)
Overhaul and simplify the GPS search logic based
on experience and testing with the API. Also fix
search-by-name, which was broken.

src/Airports/pavement.cxx
src/Airports/runwaybase.cxx
src/Airports/simple.cxx
src/Instrumentation/dclgps.cxx
src/Instrumentation/gps.cxx
src/Instrumentation/gps.hxx
src/Navaids/fixlist.cxx
src/Navaids/markerbeacon.cxx
src/Navaids/navrecord.cxx
src/Navaids/positioned.cxx
src/Navaids/positioned.hxx

index 7e5f607636e4bfbfa0a2cae52a08a03f4231e777..4f06a9a1dc7a5db89cda431b3715888137e4fb8e 100755 (executable)
@@ -25,8 +25,9 @@
 #include "pavement.hxx"
 
 FGPavement::FGPavement(const std::string& aIdent, const SGGeod& aPos) :
-  FGPositioned(PAVEMENT, aIdent, aPos, false)
+  FGPositioned(PAVEMENT, aIdent, aPos)
 {
+  init(false); // FGPositioned::init
 }
 
 void FGPavement::addNode(const SGGeod &aPos, bool aClose)
index fd82406ad9a0696258a5a034d9551b9d2db783a9..1131e22a0c932db85168a7f43415ff7da76271b8 100644 (file)
@@ -51,12 +51,14 @@ FGRunwayBase::FGRunwayBase(Type aTy, const string& aIdent,
                         const double width,
                         const int surface_code,
                         bool index) :
-  FGPositioned(aTy, aIdent, aGeod, index)
+  FGPositioned(aTy, aIdent, aGeod)
 {
   _heading = heading;
   _length = length;
   _width = width;
   _surface_code = surface_code;
+  
+  init(index);
 }
 
 SGGeod FGRunwayBase::pointOnCenterline(double aOffset) const
index 249e5a72b40a8fa51cfaafd365e780524b32cfd6..a418bd4144f1a81472f67e3d005953693949c4ae 100644 (file)
@@ -63,6 +63,7 @@ FGAirport::FGAirport(const string &id, const SGGeod& location, const SGGeod& tow
     mRunwaysLoaded(false),
     mTaxiwaysLoaded(true)
 {
+  init(true); // init FGPositioned
 }
 
 
index d3da8e828e5902107f6400b70898a05bd31ad366..018e943c4cd62b4618360f664b5bf03dbbf9b9ae 100644 (file)
@@ -1102,7 +1102,8 @@ FGPositioned* DCLGPS::FindTypedFirstById(const string& id, FGPositioned::Type ty
   
   if (exact) {
     FGPositioned::List matches = 
-      FGPositioned::findAllWithIdentSortedByRange(id, SGGeod::fromRad(_lon, _lat), &filter);
+      FGPositioned::findAllWithIdent(id, &filter);
+    FGPositioned::sortByRange(matches, SGGeod::fromRad(_lon, _lat));
     multi = (matches.size() > 1);
     return matches.empty() ? NULL : matches.front().ptr();
   }
index 06647d4ad20596645b24717d72093a0f3b5a7655..9ebe8d6ea4ea456c9d8e9d7bae049b905731d53b 100644 (file)
@@ -220,7 +220,6 @@ GPS::GPS ( SGPropertyNode *node) :
   _mode("init"),
   _name(node->getStringValue("name", "gps")),
   _num(node->getIntValue("number", 0)),
-  _searchResultsCached(false),
   _computeTurnData(false),
   _anticipateTurn(false),
   _inTurn(false)
@@ -1384,9 +1383,6 @@ void GPS::setScratchFromRouteWaypoint(int aIndex)
   _scratchValid = true;
   _scratchNode->setDoubleValue("course", wp.get_track());
   _scratchNode->setIntValue("index", aIndex);
-  
-  int lastResult = _routeMgr->size() - 1;
-  _searchHasNext = (_searchResultIndex < lastResult);
 }
 
 void GPS::loadNearest()
@@ -1411,17 +1407,14 @@ void GPS::loadNearest()
     
   _searchResults = 
     FGPositioned::findClosestN(searchPos, limitCount, cutoffDistance, f.get());
-  _searchResultsCached = true;
   _searchResultIndex = 0;
   _searchIsRoute = false;
-  _searchHasNext = false;
   
   if (_searchResults.empty()) {
     SG_LOG(SG_INSTR, SG_INFO, "GPS:loadNearest: no matches at all");
     return;
   }
   
-  _searchHasNext = (_searchResults.size() > 1);
   setScratchFromCachedSearchResult();
 }
 
@@ -1478,66 +1471,47 @@ void GPS::search()
   }
   
   _searchExact = _scratchNode->getBoolValue("exact", true);
-  _searchOrderByRange = _scratchNode->getBoolValue("order-by-distance", true);
   _searchResultIndex = 0;
   _searchIsRoute = false;
-  _searchHasNext = false;
-  
-  if (_searchExact && _searchOrderByRange) {
-    // immediate mode search, get all the results now and cache them
-    auto_ptr<FGPositioned::Filter> f(createFilter(_searchType));
-    if (_searchNames) {
-      _searchResults = FGPositioned::findAllWithNameSortedByRange(_searchQuery, _indicated_pos, f.get());
-    } else {
-      _searchResults = FGPositioned::findAllWithIdentSortedByRange(_searchQuery, _indicated_pos, f.get());
-    }
-    
-    _searchResultsCached = true;
-    
-    if (_searchResults.empty()) {
-      clearScratch();
-      return;
-    }
-    
-    _searchHasNext = (_searchResults.size() > 1);
-    setScratchFromCachedSearchResult();
-  } else {
-    // iterative search, look up result zero
-    _searchResultsCached = false;
-    performSearch();
-  }
-}
 
-void GPS::performSearch()
-{
   auto_ptr<FGPositioned::Filter> f(createFilter(_searchType));
-  clearScratch();
-  
-  FGPositionedRef r;
   if (_searchNames) {
-    if (_searchOrderByRange) {
-      r = FGPositioned::findClosestWithPartialName(_indicated_pos, _searchQuery, f.get(), _searchResultIndex, _searchHasNext);
-    } else {
-      r = FGPositioned::findWithPartialName(_searchQuery, f.get(), _searchResultIndex, _searchHasNext);
-    }
+    _searchResults = FGPositioned::findAllWithName(_searchQuery, f.get());
   } else {
-    if (_searchOrderByRange) {
-      r = FGPositioned::findClosestWithPartialId(_indicated_pos, _searchQuery, f.get(), _searchResultIndex, _searchHasNext);
-    } else {
-      r = FGPositioned::findWithPartialId(_searchQuery, f.get(), _searchResultIndex, _searchHasNext);
-    }
+    _searchResults = FGPositioned::findAllWithIdent(_searchQuery, f.get());
+  }
+  
+  bool orderByRange = _scratchNode->getBoolValue("order-by-distance", true);
+  if (orderByRange) {
+    FGPositioned::sortByRange(_searchResults, _indicated_pos);
   }
   
-  if (!r) {
+  if (_searchResults.empty()) {
+    clearScratch();
     return;
   }
   
-  setScratchFromPositioned(r.get(), _searchResultIndex);
+  setScratchFromCachedSearchResult();
+}
+
+bool GPS::getScratchHasNext() const
+{
+  int lastResult;
+  if (_searchIsRoute) {
+    lastResult = _routeMgr->size() - 1;
+  } else {
+    lastResult = (int) _searchResults.size() - 1;
+  }
+
+  if (lastResult < 0) { // search array might be empty
+    return false;
+  }
+  
+  return (_searchResultIndex < lastResult);
 }
 
 void GPS::setScratchFromCachedSearchResult()
 {
-  assert(_searchResultsCached);
   int index = _searchResultIndex;
   
   if ((index < 0) || (index >= (int) _searchResults.size())) {
@@ -1546,9 +1520,6 @@ void GPS::setScratchFromCachedSearchResult()
   }
   
   setScratchFromPositioned(_searchResults[index], index);
-  
-  int lastResult = (int) _searchResults.size() - 1;
-  _searchHasNext = (_searchResultIndex < lastResult);
 }
 
 void GPS::setScratchFromPositioned(FGPositioned* aPos, int aIndex)
@@ -1566,9 +1537,7 @@ void GPS::setScratchFromPositioned(FGPositioned* aPos, int aIndex)
   }
   
   _scratchValid = true;
-  if (_searchResultsCached) {
-    _scratchNode->setIntValue("result-count", _searchResults.size());
-  }
+  _scratchNode->setIntValue("result-count", _searchResults.size());
   
   switch (aPos->type()) {
   case FGPositioned::VOR:
@@ -1652,20 +1621,17 @@ void GPS::selectLegMode()
 
 void GPS::nextResult()
 {
-  if (!_searchHasNext) {
+  if (!getScratchHasNext()) {
     return;
   }
   
   clearScratch();
   if (_searchIsRoute) {
     setScratchFromRouteWaypoint(++_searchResultIndex);
-  } else if (_searchResultsCached) {
-    ++_searchResultIndex;
-    setScratchFromCachedSearchResult();
   } else {
     ++_searchResultIndex;
-    performSearch();
-  } // of iterative search case
+    setScratchFromCachedSearchResult();
+  }
 }
 
 void GPS::previousResult()
@@ -1679,10 +1645,8 @@ void GPS::previousResult()
   
   if (_searchIsRoute) {
     setScratchFromRouteWaypoint(_searchResultIndex);
-  } else if (_searchResultsCached) {
-    setScratchFromCachedSearchResult();
   } else {
-    performSearch();
+    setScratchFromCachedSearchResult();
   }
 }
 
@@ -1701,14 +1665,15 @@ void GPS::defineWaypoint()
     
 // check for duplicate idents
   FGPositioned::TypeFilter f(FGPositioned::WAYPOINT);
-  FGPositioned::List dups = FGPositioned::findAllWithIdentSortedByRange(ident, _indicated_pos, &f);
+  FGPositioned::List dups = FGPositioned::findAllWithIdent(ident, &f);
   if (!dups.empty()) {
     SG_LOG(SG_INSTR, SG_WARN, "GPS:defineWaypoint: non-unique waypoint identifier, ho-hum");
   }
   
   SG_LOG(SG_INSTR, SG_INFO, "GPS:defineWaypoint: creating waypoint:" << ident);
   FGPositionedRef wpt = FGPositioned::createUserWaypoint(ident, _scratchPos);
-  _searchResultsCached = false;
+  _searchResults.clear();
+  _searchResults.push_back(wpt);
   setScratchFromPositioned(wpt.get(), -1);
 }
 
index cbdca3bc49b76bd08b0140136afb8277316eea9c..d6c3a7069bfe96d2f3d32d1ed71cab60bec6b1d3 100644 (file)
@@ -264,7 +264,7 @@ private:
   double getScratchDistance() const;
   double getScratchMagBearing() const;
   double getScratchTrueBearing() const;
-  bool getScratchHasNext() const { return _searchHasNext; }
+  bool getScratchHasNext() const;
   
   double getSelectedCourse() const { return _selectedCourse; }
   void setSelectedCourse(double crs);
@@ -394,8 +394,6 @@ private:
   std::string _searchQuery;
   FGPositioned::Type _searchType;
   bool _searchExact;
-  bool _searchOrderByRange;
-  bool _searchResultsCached;
   FGPositioned::List _searchResults;
   bool _searchIsRoute; ///< set if 'search' is actually the current route
   bool _searchHasNext; ///< is there a result after this one?
index 835a2b1b595320c9c1c0b9264e27da30997bf30d..50c06ac563c804bb99eda19862fc2921386b20ac 100644 (file)
@@ -39,6 +39,7 @@
 FGFix::FGFix(const std::string& aIdent, const SGGeod& aPos) :
   FGPositioned(FIX, aIdent, aPos)
 {
+  init(true); // init FGPositioned
 }
 
 // Constructor
index 3a49e328056fb4f0cedad3b82c10f3ffee051d17..6518799613505579ae2d84770b8366fc43567597 100644 (file)
@@ -65,4 +65,5 @@ FGMarkerBeaconRecord::FGMarkerBeaconRecord(Type aTy, FGRunway* aRunway, const SG
   FGPositioned(aTy, string(), aPos),
   _runway(aRunway)
 {
+  init(true); // init FGPositioned
 }
index 041c12f1a663fc84aef85f6b021682eedb01c089..a22bebb69b431f7f6dec13701adb0a6318531488 100644 (file)
@@ -82,6 +82,7 @@ FGNavRecord::FGNavRecord(Type aTy, const std::string& aIdent,
     }
   }
   
+  init(true); // init FGPositioned (now position is adjusted)
 }
 
 void FGNavRecord::initAirportRelation()
index 48f284648a7678a7c0ef1203d318ecf592827d23..591f52e45f0bf48344e4ef698df67a1217e50ad5 100644 (file)
@@ -22,6 +22,8 @@
 #  include "config.h"
 #endif
 
+#include "positioned.hxx"
+
 #include <map>
 #include <set>
 #include <algorithm> // for sort
@@ -35,7 +37,7 @@
 #include <simgear/structure/exception.hxx>
 #include <simgear/math/SGGeometry.hxx>
 
-#include "positioned.hxx"
+
 
 typedef std::multimap<std::string, FGPositioned*> NamedPositionedIndex;
 typedef std::pair<NamedPositionedIndex::const_iterator, NamedPositionedIndex::const_iterator> NamedIndexRange;
@@ -402,91 +404,6 @@ removeFromIndices(FGPositioned* aPos)
   }
 }
 
-class DistanceOrdering
-{
-public:
-  DistanceOrdering(const SGGeod& aPos) :
-    mPos(SGVec3d::fromGeod(aPos))
-  { }
-  
-  bool operator()(const FGPositionedRef& a, const FGPositionedRef& b) const
-  {
-    if (!a || !b) {
-      throw sg_exception("empty reference passed to DistanceOrdering");
-    }
-  
-    double dA = distSqr(a->cart(), mPos),
-      dB = distSqr(b->cart(), mPos);
-    return dA < dB;
-  }
-
-private:
-  SGVec3d mPos;
-};
-
-static void
-sortByDistance(const SGGeod& aPos, FGPositioned::List& aResult)
-{
-  std::sort(aResult.begin(), aResult.end(), DistanceOrdering(aPos));
-}
-
-static FGPositionedRef
-namedFindClosest(const NamedPositionedIndex& aIndex, const std::string& aName, 
-                 const SGGeod& aOrigin, FGPositioned::Filter* aFilter)
-{
-  NamedIndexRange range = aIndex.equal_range(aName);
-  if (range.first == range.second) {
-    return NULL;
-  }
-  
-// common case, only one result. looks a bit ugly because these are
-// sequential iterators, not random-access ones
-  NamedPositionedIndex::const_iterator check = range.first;
-  if (++check == range.second) {
-    // excellent, only one match in the range
-    FGPositioned* r = range.first->second;
-    if (aFilter) {
-      if (aFilter->hasTypeRange() && !aFilter->passType(r->type())) {
-        return NULL;
-      }
-      
-      if (!aFilter->pass(r)) {
-        return NULL;
-      }
-    } // of have a filter
-  
-    return r;
-  } // of short-circuit logic for single-element range
-  
-// multiple matches, we need to actually check the distance to each one
-  double minDist = HUGE_VAL;
-  FGPositionedRef result;
-  NamedPositionedIndex::const_iterator it = range.first;
-  SGVec3d cartOrigin(SGVec3d::fromGeod(aOrigin));
-  
-  for (; it != range.second; ++it) {
-    FGPositioned* r = it->second;
-    if (aFilter) {
-      if (aFilter->hasTypeRange() && !aFilter->passType(r->type())) {
-        continue;
-      }
-      
-      if (!aFilter->pass(r)) {
-        continue;
-      }
-    }
-    
-  // find distance
-    double d2 = distSqr(cartOrigin, r->cart());
-    if (d2 < minDist) {
-      minDist = d2;
-      result = r;
-    }
-  }
-  
-  return result;
-}
-
 //////////////////////////////////////////////////////////////////////////////
 
 class OrderByName
@@ -592,88 +509,54 @@ FGPositioned::Filter::passType(Type aTy) const
   return (minType() <= aTy) && (maxType() >= aTy);
 }
 
-static FGPositioned::List
-findAllSortedByRange(const NamedPositionedIndex& aIndex, 
-                             const std::string& aName, const SGGeod& aPos, FGPositioned::Filter* aFilter)
+static FGPositioned::List 
+findAll(const NamedPositionedIndex& aIndex, 
+                             const std::string& aName, FGPositioned::Filter* aFilter)
 {
   FGPositioned::List result;
-  NamedIndexRange range = aIndex.equal_range(aName);
-  for (; range.first != range.second; ++range.first) {
-    FGPositioned* candidate = range.first->second;
-    if (aFilter) {
-      if (aFilter->hasTypeRange() && !aFilter->passType(candidate->type())) {
-        continue;
-      }
-      
-      if (!aFilter->pass(candidate)) {
-        continue;
-      }
-    }
-    
-    result.push_back(range.first->second);
+  if (aName.empty()) {
+    return result;
   }
   
-  sortByDistance(aPos, result);
-  return result;
-}
-
-static FGPositionedRef
-findWithPartial(const NamedPositionedIndex& aIndex, const std::string& aName, 
-                    FGPositioned::Filter* aFilter, int aOffset, bool& aNext)
-{
-  // see comment in findNextWithPartialId concerning upperBoundId
   std::string upperBoundId = aName;
   upperBoundId[upperBoundId.size()-1]++;
   NamedPositionedIndex::const_iterator upperBound = aIndex.lower_bound(upperBoundId);
+  NamedPositionedIndex::const_iterator it = aIndex.lower_bound(aName);
   
-  NamedIndexRange range = aIndex.equal_range(aName);
-  FGPositionedRef result;
-  
-  while (range.first != upperBound) {
-    for (; range.first != range.second; ++range.first) {
-      FGPositionedRef candidate = range.first->second;
-      if (aFilter) {
-        if (aFilter->hasTypeRange() && !aFilter->passType(candidate->type())) {
-          continue;
-        }
-        
-        if (!aFilter->pass(candidate)) {
-          continue;
-        }
+  for (; it != upperBound; ++it) {
+    FGPositionedRef candidate = it->second;
+    if (aFilter) {
+      if (aFilter->hasTypeRange() && !aFilter->passType(candidate->type())) {
+        continue;
       }
       
-      if (result) {
-        aNext = true;
-        return result;
-      } else if (aOffset == 0) {
-        // okay, found our result. we need to go around once more to set aNext
-        result = candidate;
-      } else {
-        --aOffset; // seen one more valid result, decrement the count
+      if (!aFilter->pass(candidate)) {
+        continue;
       }
     }
     
-    // Unable to match the filter with this range - try the next range.
-    range = aIndex.equal_range(range.second->first);
+    result.push_back(candidate);
   }
   
-  // if we fell out, we reached the end of the valid range. We might have a
-  // valid result, but we definitiely don't have a next result.
-  aNext = false;
-  return result;  
+  return result;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
-FGPositioned::FGPositioned(Type ty, const std::string& aIdent, const SGGeod& aPos, bool aIndexed) :
+FGPositioned::FGPositioned(Type ty, const std::string& aIdent, const SGGeod& aPos) :
   mPosition(aPos),
   mType(ty),
   mIdent(aIdent)
 {  
+}
+
+void FGPositioned::init(bool aIndexed)
+{
   SGReferenced::get(this); // hold an owning ref, for the moment
+  mCart = SGVec3d::fromGeod(mPosition);
   
   if (aIndexed) {
-    assert(ty != TAXIWAY && ty != PAVEMENT);
+    assert(mType != TAXIWAY && mType != PAVEMENT);
     addToIndices(this);
   }
 }
@@ -687,13 +570,15 @@ FGPositioned::~FGPositioned()
 FGPositioned*
 FGPositioned::createUserWaypoint(const std::string& aIdent, const SGGeod& aPos)
 {
-  return new FGPositioned(WAYPOINT, aIdent, aPos, true);
+  FGPositioned* wpt = new FGPositioned(WAYPOINT, aIdent, aPos);
+  wpt->init(true);
+  return wpt;
 }
 
-SGVec3d
+const SGVec3d&
 FGPositioned::cart() const
 {
-  return SGVec3d::fromGeod(mPosition);
+  return mCart;
 }
 
 FGPositioned::Type FGPositioned::typeFromName(const std::string& aName)
@@ -770,7 +655,13 @@ const char* FGPositioned::nameForType(Type aTy)
 FGPositionedRef
 FGPositioned::findClosestWithIdent(const std::string& aIdent, const SGGeod& aPos, Filter* aFilter)
 {
-  return namedFindClosest(global_identIndex, aIdent, aPos, aFilter);
+  FGPositioned::List r(findAll(global_identIndex, aIdent, aFilter));
+  if (r.empty()) {
+    return FGPositionedRef();
+  }
+  
+  sortByRange(r, aPos);
+  return r.front();
 }
 
 FGPositioned::List
@@ -783,15 +674,15 @@ FGPositioned::findWithinRange(const SGGeod& aPos, double aRangeNm, Filter* aFilt
 }
 
 FGPositioned::List
-FGPositioned::findAllWithIdentSortedByRange(const std::string& aIdent, const SGGeod& aPos, Filter* aFilter)
+FGPositioned::findAllWithIdent(const std::string& aIdent, Filter* aFilter)
 {
-  return findAllSortedByRange(global_identIndex, aIdent, aPos, aFilter);
+  return findAll(global_identIndex, aIdent, aFilter);
 }
 
 FGPositioned::List
-FGPositioned::findAllWithNameSortedByRange(const std::string& aName, const SGGeod& aPos, Filter* aFilter)
+FGPositioned::findAllWithName(const std::string& aName, Filter* aFilter)
 {
-  return findAllSortedByRange(global_nameIndex, aName, aPos, aFilter);
+  return findAll(global_nameIndex, aName, aFilter);
 }
 
 FGPositionedRef
@@ -861,115 +752,24 @@ FGPositioned::findNextWithPartialId(FGPositionedRef aCur, const std::string& aId
   return NULL; // Reached the end of the valid sequence with no match.  
 }
   
-FGPositionedRef
-FGPositioned::findWithPartialId(const std::string& aId, Filter* aFilter, int aOffset, bool& aNext)
-{
-  return findWithPartial(global_identIndex, aId, aFilter, aOffset, aNext);
-}
-
-
-FGPositionedRef
-FGPositioned::findWithPartialName(const std::string& aName, Filter* aFilter, int aOffset, bool& aNext)
-{
-  return findWithPartial(global_nameIndex, aName, aFilter, aOffset, aNext);
-}
-
-/**
- * Wrapper filter which proxies to an inner filter, but also ensures the
- * ident starts with supplied partial ident.
- */
-class PartialIdentFilter : public FGPositioned::Filter
+void
+FGPositioned::sortByRange(List& aResult, const SGGeod& aPos)
 {
-public:
-  PartialIdentFilter(const std::string& ident, FGPositioned::Filter* filter) :
-    _inner(filter)
-  {
-    _ident = boost::to_upper_copy(ident);
+  SGVec3d cartPos(SGVec3d::fromGeod(aPos));
+// computer ordering values
+  Octree::FindNearestResults r;
+  List::iterator it = aResult.begin(), lend = aResult.end();
+  for (; it != lend; ++it) {
+    double d2 = distSqr((*it)->cart(), cartPos);
+    r.push_back(Octree::OrderedPositioned(*it, d2));
   }
   
-  virtual bool pass(FGPositioned* aPos) const
-  {
-    if (!_inner->pass(aPos)) {
-      return false;
-    }
-    
-    return (boost::algorithm::starts_with(aPos->ident(), _ident));
-  }
-    
-  virtual FGPositioned::Type minType() const
-  { return _inner->minType(); }
-    
-  virtual FGPositioned::Type maxType() const
-  { return _inner->maxType(); }
-    
-private:
-  std::string _ident;
-  FGPositioned::Filter* _inner;
-};
-
-static FGPositionedRef
-findClosestWithPartial(const SGGeod& aPos, FGPositioned::Filter* aFilter, int aOffset, bool& aNext)
-{
-  // why aOffset +2 ? at offset=3, we want the fourth search result, but also
-  // to know if the fifth result exists (to set aNext flag for iterative APIs)
-  FGPositioned::List matches;
-  Octree::findNearestN(SGVec3d::fromGeod(aPos), aOffset + 2, 1000 * SG_NM_TO_METER, aFilter, matches);
+// sort
+  std::sort(r.begin(), r.end());
   
-  if ((int) matches.size() <= aOffset) {
-    SG_LOG(SG_GENERAL, SG_INFO, "findClosestWithPartial, couldn't match enough with prefix");
-    aNext = false;
-    return NULL; // couldn't find a match within the cutoff distance
+// convert to a plain list
+  unsigned int count = aResult.size();
+  for (unsigned int i=0; i<count; ++i) {
+    aResult[i] = r[i].get();
   }
-  
-  aNext = ((int) matches.size() >= (aOffset + 2));
-  return matches[aOffset];
-
 }
-
-FGPositionedRef
-FGPositioned::findClosestWithPartialId(const SGGeod& aPos, const std::string& aId, Filter* aFilter, int aOffset, bool& aNext)
-{
-  PartialIdentFilter pf(aId, aFilter);
-  return findClosestWithPartial(aPos, &pf, aOffset, aNext);
-}
-
-/**
- * Wrapper filter which proxies to an inner filter, but also ensures the
- * name starts with supplied partial name.
- */
-class PartialNameFilter : public FGPositioned::Filter
-{
-public:
-  PartialNameFilter(const std::string& nm, FGPositioned::Filter* filter) :
-  _inner(filter)
-  {
-    _name = nm;
-  }
-  
-  virtual bool pass(FGPositioned* aPos) const
-  {
-    if (!_inner->pass(aPos)) {
-      return false;
-    }
-    
-    return (boost::algorithm::istarts_with(aPos->name(), _name));
-  }
-  
-  virtual FGPositioned::Type minType() const
-  { return _inner->minType(); }
-  
-  virtual FGPositioned::Type maxType() const
-  { return _inner->maxType(); }
-  
-private:
-  std::string _name;
-  FGPositioned::Filter* _inner;
-};
-
-FGPositionedRef
-FGPositioned::findClosestWithPartialName(const SGGeod& aPos, const std::string& aName, Filter* aFilter, int aOffset, bool& aNext)
-{
-  PartialNameFilter pf(aName, aFilter);
-  return findClosestWithPartial(aPos, &pf, aOffset, aNext);
-}
-
index d5f9b3672d135522fa7caaa818db1ecec4c7278b..27d807a7264c0d0418c8dba72d98e4cff64e240c 100644 (file)
@@ -84,9 +84,9 @@ public:
   { return mPosition; }
 
   /**
-   * Compute the cartesian position associated with this object
+   *  The cartesian position associated with this object
    */
-  SGVec3d cart() const;
+  const SGVec3d& cart() const;
 
   double latitude() const
   { return mPosition.getLatitudeDeg(); }
@@ -157,27 +157,20 @@ public:
   static FGPositionedRef findNextWithPartialId(FGPositionedRef aCur, const std::string& aId, Filter* aFilter = NULL);
   
   /**
-   * As above, but searches using an offset index
-   */
-  static FGPositionedRef findWithPartialId(const std::string& aId, Filter* aFilter, int aOffset, bool& aNext);
-
-  /**
-   * As above, but search names instead of idents
+   * Find all items with the specified ident
+   * @param aFilter - optional filter on items
    */
-  static FGPositionedRef findWithPartialName(const std::string& aName, Filter* aFilter, int aOffset, bool& aNext);
+  static List findAllWithIdent(const std::string& aIdent, 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
+   * As above, but searches names instead of idents
    */
-  static List findAllWithIdentSortedByRange(const std::string& aIdent, const SGGeod& aPos, Filter* aFilter = NULL);
+  static List findAllWithName(const std::string& aName, Filter* aFilter = NULL);
   
   /**
-   * As above, but searches names instead of idents
+   * Sort an FGPositionedList by distance from a position
    */
-  static List findAllWithNameSortedByRange(const std::string& aName, const SGGeod& aPos, Filter* aFilter = NULL);
+  static void sortByRange(List&, const SGGeod& aPos);
   
   /**
    * Find the closest item to a position, which pass the specified filter
@@ -201,18 +194,6 @@ public:
    */
   static List findClosestN(const SGGeod& aPos, unsigned int aN, double aCutoffNm, Filter* aFilter = NULL);
   
-  /**
-   * Find the closest match based on partial id (with an offset to allow selecting the n-th closest).
-   * Cutoff distance is limited internally, to avoid making this very slow.
-   */
-  static FGPositionedRef findClosestWithPartialId(const SGGeod& aPos, const std::string& aId, Filter* aFilter, int aOffset, bool& aNext);
-
-  /**
-   * As above, but matches on name
-   */
-  static FGPositionedRef findClosestWithPartialName(const SGGeod& aPos, const std::string& aName, Filter* aFilter, int aOffset, bool& aNext);
-  
-  
   /**
    * Map a candidate type string to a real type. Returns INVALID if the string
    * does not correspond to a defined type.
@@ -227,12 +208,15 @@ public:
   static FGPositioned* createUserWaypoint(const std::string& aIdent, const SGGeod& aPos);
 protected:
   
-  FGPositioned(Type ty, const std::string& aIdent, const SGGeod& aPos, bool aIndex = true);
+  FGPositioned(Type ty, const std::string& aIdent, const SGGeod& aPos);
+  
+  void init(bool aIndexed);
   
   // can't be const right now, navrecord at least needs to fix up the position
   // after navaids are parsed
   SGGeod mPosition; 
   
+  SGVec3d mCart; // once mPosition is const, this can be const too
   const Type mType;
   const std::string mIdent;
 };