]> git.mxchange.org Git - flightgear.git/commitdiff
Fix auto-routing by airways.
authorJames Turner <jmt@Bishop.local>
Sun, 30 Dec 2012 16:12:11 +0000 (16:12 +0000)
committerJames Turner <jmt@Bishop.local>
Sun, 30 Dec 2012 16:12:11 +0000 (16:12 +0000)
When the from and to points are not on the enroute structure, check the initial and final legs for large turns (more than 90-degrees) from the overall route course. If found, kill the leg, to generate more natural route and avoid very sharp turns in the terminal area.

src/Navaids/airways.cxx
src/Navaids/airways.hxx

index 70ff237c7538c929c6331fe824fad440b897fc4e..0000cdfa0652ed24a9a877027f53195f0710b825 100644 (file)
@@ -190,6 +190,13 @@ void Airway::Network::addEdge(int aWay, const SGGeod& aStartPos,
 
 //////////////////////////////////////////////////////////////////////////////
 
+static double headingDiffDeg(double a, double b)
+{
+    double rawDiff = b - a;
+    SG_NORMALIZE_RANGE(rawDiff, -180.0, 180.0);
+    return rawDiff;
+}
+    
 bool Airway::Network::inNetwork(PositionedID posID) const
 {
   NetworkMembershipDict::iterator it = _inNetworkCache.find(posID);
@@ -228,19 +235,46 @@ bool Airway::Network::route(WayptRef aFrom, WayptRef aTo,
     return false;
   }
   
-  if (exactTo) {
+  return cleanGeneratedPath(aFrom, aTo, aPath, exactTo, exactFrom);
+}
+  
+bool Airway::Network::cleanGeneratedPath(WayptRef aFrom, WayptRef aTo, WayptVec& aPath,
+                                bool exactTo, bool exactFrom)
+{
+  // path cleaning phase : various cases to handle here.
+  // if either the TO or FROM waypoints were 'exact', i.e part of the enroute
+  // structure, we don't want to duplicate them. This happens frequently with
+  // published SIDs and STARs.
+  // secondly, if the waypoints are NOT on the enroute structure, the course to
+  // them may be a significant dog-leg. Check how the leg course deviates
+  // from the direct course FROM->TO, and delete the first/last leg if it's more
+  // than 90 degrees out.
+  // note we delete a maximum of one leg, and no more. This is a heuristic - we
+  // could check the next (previous) legs, but at some point we'll end up
+  // deleting too much.
+  
+  const double MAX_DOG_LEG = 90.0;
+  double enrouteCourse = SGGeodesy::courseDeg(aFrom->position(), aTo->position()),
+  finalLegCourse = SGGeodesy::courseDeg(aPath.back()->position(), aTo->position());
+  
+  bool isDogLeg = fabs(headingDiffDeg(enrouteCourse, finalLegCourse)) > MAX_DOG_LEG;
+  if (exactTo || isDogLeg) {
     aPath.pop_back();
   }
   
-  if (exactFrom) {
-    // edge case - if from and to are equal, which can happen, don't
-    // crash here. This happens routing EGPH -> EGCC; 'DCS' is common
-    // to the EGPH departure and EGCC STAR.
-    if (!aPath.empty()) {
-      aPath.erase(aPath.begin());
-    }
+  // edge case - if from and to are equal, which can happen, don't
+  // crash here. This happens routing EGPH -> EGCC; 'DCS' is common
+  // to the EGPH departure and EGCC STAR.
+  if (aPath.empty()) {
+    return true;
   }
   
+  double initialLegCourse = SGGeodesy::courseDeg(aFrom->position(), aPath.front()->position());
+  isDogLeg = fabs(headingDiffDeg(enrouteCourse, initialLegCourse)) > MAX_DOG_LEG;
+  if (exactFrom || isDogLeg) {
+    aPath.erase(aPath.begin());
+  }
+
   return true;
 }
 
index 514cb6187b2879c837597150ed9745b90e25e6bf..6942f30741175ee5e17c3b0b59f5ce49ea2f1854 100644 (file)
@@ -71,6 +71,9 @@ public:
   
     int findAirway(const std::string& aName, double aTop, double aBase);
 
+    bool cleanGeneratedPath(WayptRef aFrom, WayptRef aTo, WayptVec& aPath,
+                            bool exactTo, bool exactFrom);
+      
     bool search2(FGPositionedRef aStart, FGPositionedRef aDest, WayptVec& aRoute);
   
     /**