From 57cb0a809bfeaf6781f463634a25081af9fdce5a Mon Sep 17 00:00:00 2001 From: James Turner Date: Sat, 14 Aug 2010 19:16:28 +0100 Subject: [PATCH] Fix bug 150 (airports not found in GPS search) 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 | 3 +- src/Airports/runwaybase.cxx | 4 +- src/Airports/simple.cxx | 1 + src/Instrumentation/dclgps.cxx | 3 +- src/Instrumentation/gps.cxx | 103 ++++------- src/Instrumentation/gps.hxx | 4 +- src/Navaids/fixlist.cxx | 1 + src/Navaids/markerbeacon.cxx | 1 + src/Navaids/navrecord.cxx | 1 + src/Navaids/positioned.cxx | 312 ++++++--------------------------- src/Navaids/positioned.hxx | 42 ++--- 11 files changed, 115 insertions(+), 360 deletions(-) diff --git a/src/Airports/pavement.cxx b/src/Airports/pavement.cxx index 7e5f60763..4f06a9a1d 100755 --- a/src/Airports/pavement.cxx +++ b/src/Airports/pavement.cxx @@ -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) diff --git a/src/Airports/runwaybase.cxx b/src/Airports/runwaybase.cxx index fd82406ad..1131e22a0 100644 --- a/src/Airports/runwaybase.cxx +++ b/src/Airports/runwaybase.cxx @@ -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 diff --git a/src/Airports/simple.cxx b/src/Airports/simple.cxx index 249e5a72b..a418bd414 100644 --- a/src/Airports/simple.cxx +++ b/src/Airports/simple.cxx @@ -63,6 +63,7 @@ FGAirport::FGAirport(const string &id, const SGGeod& location, const SGGeod& tow mRunwaysLoaded(false), mTaxiwaysLoaded(true) { + init(true); // init FGPositioned } diff --git a/src/Instrumentation/dclgps.cxx b/src/Instrumentation/dclgps.cxx index d3da8e828..018e943c4 100644 --- a/src/Instrumentation/dclgps.cxx +++ b/src/Instrumentation/dclgps.cxx @@ -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(); } diff --git a/src/Instrumentation/gps.cxx b/src/Instrumentation/gps.cxx index 06647d4ad..9ebe8d6ea 100644 --- a/src/Instrumentation/gps.cxx +++ b/src/Instrumentation/gps.cxx @@ -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 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 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); } diff --git a/src/Instrumentation/gps.hxx b/src/Instrumentation/gps.hxx index cbdca3bc4..d6c3a7069 100644 --- a/src/Instrumentation/gps.hxx +++ b/src/Instrumentation/gps.hxx @@ -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? diff --git a/src/Navaids/fixlist.cxx b/src/Navaids/fixlist.cxx index 835a2b1b5..50c06ac56 100644 --- a/src/Navaids/fixlist.cxx +++ b/src/Navaids/fixlist.cxx @@ -39,6 +39,7 @@ FGFix::FGFix(const std::string& aIdent, const SGGeod& aPos) : FGPositioned(FIX, aIdent, aPos) { + init(true); // init FGPositioned } // Constructor diff --git a/src/Navaids/markerbeacon.cxx b/src/Navaids/markerbeacon.cxx index 3a49e3280..651879961 100644 --- a/src/Navaids/markerbeacon.cxx +++ b/src/Navaids/markerbeacon.cxx @@ -65,4 +65,5 @@ FGMarkerBeaconRecord::FGMarkerBeaconRecord(Type aTy, FGRunway* aRunway, const SG FGPositioned(aTy, string(), aPos), _runway(aRunway) { + init(true); // init FGPositioned } diff --git a/src/Navaids/navrecord.cxx b/src/Navaids/navrecord.cxx index 041c12f1a..a22bebb69 100644 --- a/src/Navaids/navrecord.cxx +++ b/src/Navaids/navrecord.cxx @@ -82,6 +82,7 @@ FGNavRecord::FGNavRecord(Type aTy, const std::string& aIdent, } } + init(true); // init FGPositioned (now position is adjusted) } void FGNavRecord::initAirportRelation() diff --git a/src/Navaids/positioned.cxx b/src/Navaids/positioned.cxx index 48f284648..591f52e45 100644 --- a/src/Navaids/positioned.cxx +++ b/src/Navaids/positioned.cxx @@ -22,6 +22,8 @@ # include "config.h" #endif +#include "positioned.hxx" + #include #include #include // for sort @@ -35,7 +37,7 @@ #include #include -#include "positioned.hxx" + typedef std::multimap NamedPositionedIndex; typedef std::pair 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= (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); -} - diff --git a/src/Navaids/positioned.hxx b/src/Navaids/positioned.hxx index d5f9b3672..27d807a72 100644 --- a/src/Navaids/positioned.hxx +++ b/src/Navaids/positioned.hxx @@ -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; }; -- 2.39.5