]> git.mxchange.org Git - flightgear.git/commitdiff
NavDisplay: time-bound the spatial query.
authorJames Turner <jmt@Bishop.local>
Sun, 30 Dec 2012 17:01:48 +0000 (17:01 +0000)
committerJames Turner <jmt@Bishop.local>
Sun, 30 Dec 2012 17:01:48 +0000 (17:01 +0000)
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.

src/Cockpit/NavDisplay.cxx
src/Navaids/PositionedOctree.cxx
src/Navaids/PositionedOctree.hxx
src/Navaids/positioned.cxx
src/Navaids/positioned.hxx

index 6c344aa9d08a228341d41f9209f9fd5b6fd6ca2e..efd2c30a33b88008da83f4b816dd5c2342493c8f 100644 (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
index 9f6908f831433d76a1c51126257c09baf333e0b9..781fee8f220c17999b96aa4e6ce90da00f4bd75f 100644 (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)
index 747ce985b5aa6944c4843a38845c760b9bf2c9e3..3a830349c6cf5e34b3ff63a025bd7fe7a360abba 100644 (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
 
index e7a1e58c53d8a30c0e4028834ad8b4839258eb36..92250b90686b4aa99d2fd4904b665e54e4b407c4 100644 (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)
 {
index f4707cbc26a28de3604217df17bb9f3f70ace567..e978bb6d66178004a051e78244dc206f459df30f 100644 (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.