1
0
Fork 0

NavDisplay: time-bound the spatial query.

At large search ranges (320 or 640NM range on the 777), the search time can blow up, especially if distant airports are being loaded. Add a time-bounded spatial query, and use it, so performance stays tolerable.
This commit is contained in:
James Turner 2012-12-30 17:01:48 +00:00
parent d0e9503766
commit 851029143e
5 changed files with 40 additions and 9 deletions

View file

@ -998,9 +998,16 @@ void NavDisplay::findItems()
if (!_cachedItemsValid) {
Filter filt(this);
filt.minRunwayLengthFt = fgGetDouble("/sim/navdb/min-runway-length-ft", 2000);
_itemsInRange = FGPositioned::findClosestN(_pos, _maxSymbols, _rangeNm, &filt);
bool wasTimeLimited;
_itemsInRange = FGPositioned::findClosestNPartial(_pos, _maxSymbols, _rangeNm,
&filt, wasTimeLimited);
_cachedItemsValid = true;
_cachedPos = SGVec3d::fromGeod(_pos);
if (wasTimeLimited) {
// re-query next frame, to load incrementally
_cachedItemsValid = false;
}
}
// sort by distance from pos, so symbol limits are accurate

View file

@ -223,7 +223,7 @@ int Branch::childMask() const
return result;
}
void findNearestN(const SGVec3d& aPos, unsigned int aN, double aCutoffM, FGPositioned::Filter* aFilter, FGPositioned::List& aResults)
bool findNearestN(const SGVec3d& aPos, unsigned int aN, double aCutoffM, FGPositioned::Filter* aFilter, FGPositioned::List& aResults, int aCutoffMsec)
{
aResults.clear();
FindNearestPQueue pq;
@ -231,13 +231,17 @@ void findNearestN(const SGVec3d& aPos, unsigned int aN, double aCutoffM, FGPosit
pq.push(Ordered<Node*>(global_spatialOctree, 0));
double cut = aCutoffM;
while (!pq.empty()) {
SGTimeStamp tm;
tm.stamp();
while (!pq.empty() && (tm.elapsedMSec() < aCutoffMsec)) {
if (!results.empty()) {
// terminate the search if we have sufficent results, and we are
// sure no node still on the queue contains a closer match
double furthestResultOrder = results.back().order();
// std::cout << "furthest result:" << furthestResultOrder << ", top node order:" << pq.top().order() << std::endl;
if ((results.size() >= aN) && (furthestResultOrder < pq.top().order())) {
// clear the PQ to mark this has 'full results' instead of partial
pq = FindNearestPQueue();
break;
}
}
@ -245,7 +249,6 @@ void findNearestN(const SGVec3d& aPos, unsigned int aN, double aCutoffM, FGPosit
Node* nd = pq.top().get();
pq.pop();
// std::cout << "visiting:" << std::oct << nd->guid() << "(" << std::dec << nd->guid() << ")" << std::endl;
nd->visit(aPos, cut, aFilter, results, pq);
} // of queue iteration
@ -257,6 +260,8 @@ void findNearestN(const SGVec3d& aPos, unsigned int aN, double aCutoffM, FGPosit
for (unsigned int r=0; r<numResults; ++r) {
aResults[r] = results[r].get();
}
return !pq.empty();
}
bool findAllWithinRange(const SGVec3d& aPos, double aRangeM, FGPositioned::Filter* aFilter, FGPositioned::List& aResults, int aCutoffMsec)

View file

@ -215,7 +215,7 @@ namespace Octree
mutable bool childrenLoaded;
};
void findNearestN(const SGVec3d& aPos, unsigned int aN, double aCutoffM, FGPositioned::Filter* aFilter, FGPositioned::List& aResults);
bool findNearestN(const SGVec3d& aPos, unsigned int aN, double aCutoffM, FGPositioned::Filter* aFilter, FGPositioned::List& aResults, int aCutoffMsec);
bool findAllWithinRange(const SGVec3d& aPos, double aRangeM, FGPositioned::Filter* aFilter, FGPositioned::List& aResults, int aCutoffMsec);
} // of namespace Octree

View file

@ -251,10 +251,23 @@ FGPositioned::findClosestN(const SGGeod& aPos, unsigned int aN, double aCutoffNm
validateSGGeod(aPos);
List result;
Octree::findNearestN(SGVec3d::fromGeod(aPos), aN, aCutoffNm * SG_NM_TO_METER, aFilter, result);
int limitMsec = 0xffff;
Octree::findNearestN(SGVec3d::fromGeod(aPos), aN, aCutoffNm * SG_NM_TO_METER, aFilter, result, limitMsec);
return result;
}
FGPositioned::List
FGPositioned::findClosestNPartial(const SGGeod& aPos, unsigned int aN, double aCutoffNm, Filter* aFilter, bool &aPartial)
{
validateSGGeod(aPos);
List result;
int limitMsec = 32;
aPartial = Octree::findNearestN(SGVec3d::fromGeod(aPos), aN, aCutoffNm * SG_NM_TO_METER, aFilter, result,
limitMsec);
return result;
}
void
FGPositioned::sortByRange(List& aResult, const SGGeod& aPos)
{

View file

@ -210,7 +210,13 @@ public:
* @param aCutoffNm - maximum distance to search within, in nautical miles
*/
static List findClosestN(const SGGeod& aPos, unsigned int aN, double aCutoffNm, Filter* aFilter = NULL);
/**
* Same as above, but with a time-bound in msec too.
*/
static List findClosestNPartial(const SGGeod& aPos, unsigned int aN, double aCutoffNm, Filter* aFilter,
bool& aPartial);
/**
* Map a candidate type string to a real type. Returns INVALID if the string
* does not correspond to a defined type.