]> git.mxchange.org Git - flightgear.git/commitdiff
Work on visualisation of Vias
authorJames Turner <zakalawe@mac.com>
Sun, 22 Nov 2015 20:14:03 +0000 (20:14 +0000)
committerJames Turner <zakalawe@mac.com>
Fri, 11 Dec 2015 19:43:25 +0000 (13:43 -0600)
src/GUI/WaypointList.cxx
src/Navaids/routePath.cxx
src/Navaids/routePath.hxx

index 93384c348425cf1ee9cfe003c76bcf28b3b57ff6..5b010f0d2690a7e6a9b14fce8dc0df9149b6510a 100644 (file)
@@ -465,42 +465,52 @@ void WaypointList::drawRow(int dx, int dy, int rowIndex, int y,
 void WaypointList::drawRowText(int x, int baseline, int rowIndex, const RoutePath& path)
 {
     flightgear::Waypt* wp(_model->waypointAt(rowIndex));
-    bool isDiscontinuity = (wp->type() == "discontinuity");
+    const bool isDiscontinuity = (wp->type() == "discontinuity");
+    const bool isVia = (wp->type() == "via");
 
     char buffer[128];
-    int count = ::snprintf(buffer, 128, "%03d   %-5s", rowIndex, wp->ident().c_str());
+    int count;
 
-    FGPositioned* src = wp->source();
-    if (src && !src->name().empty() && (src->name() != wp->ident())) {
-      // append name if present, and different to id
-      ::snprintf(buffer + count, 128 - count, " (%s)", src->name().c_str());
-    }
+    if (isVia) {
+        // VIA has long ident but no name
+        count = ::snprintf(buffer, 128, "%03d   %s", rowIndex, wp->ident().c_str());
+        drawClippedString(legendFont, buffer, x, baseline, 300);
+        x += 300 + PUSTR_LGAP;
+    } else {
+        count = ::snprintf(buffer, 128, "%03d   %-5s", rowIndex, wp->ident().c_str());
 
-    drawClippedString(legendFont, buffer, x, baseline, 300);
-    x += 300 + PUSTR_LGAP;
+        FGPositioned* src = wp->source();
+        if (src && !src->name().empty() && (src->name() != wp->ident())) {
+          // append name if present, and different to id
+          ::snprintf(buffer + count, 128 - count, " (%s)", src->name().c_str());
+        }
 
-    if (isDiscontinuity) {
-        return;
-    }
+        drawClippedString(legendFont, buffer, x, baseline, 300);
+        x += 300 + PUSTR_LGAP;
 
-    if (_showLatLon) {
-      // only show for non-dynamic waypoints
-      if (!wp->flag(WPT_DYNAMIC)) {
-        SGGeod p(wp->position());
-        char ns = (p.getLatitudeDeg() > 0.0) ? 'N' : 'S';
-        char ew = (p.getLongitudeDeg() > 0.0) ? 'E' : 'W';
+        if (isDiscontinuity) {
+            return;
+        }
 
-        ::snprintf(buffer, 128 - count, "%4.2f%c %4.2f%c",
-          fabs(p.getLongitudeDeg()), ew, fabs(p.getLatitudeDeg()), ns);
-      } else {
-        buffer[0] = 0;
-      }
-    } else if (rowIndex > 0) {
-      double courseDeg = path.trackForIndex(rowIndex);
-      double distanceM = path.distanceForIndex(rowIndex);
-      ::snprintf(buffer, 128 - count, "%03.0f %5.1fnm",
-        courseDeg, distanceM * SG_METER_TO_NM);
-    }
+        if (_showLatLon) {
+          // only show for non-dynamic waypoints
+          if (!wp->flag(WPT_DYNAMIC)) {
+            SGGeod p(wp->position());
+            char ns = (p.getLatitudeDeg() > 0.0) ? 'N' : 'S';
+            char ew = (p.getLongitudeDeg() > 0.0) ? 'E' : 'W';
+
+            ::snprintf(buffer, 128 - count, "%4.2f%c %4.2f%c",
+              fabs(p.getLongitudeDeg()), ew, fabs(p.getLatitudeDeg()), ns);
+          } else {
+            buffer[0] = 0;
+          }
+        } else if (rowIndex > 0) {
+          double courseDeg = path.trackForIndex(rowIndex);
+          double distanceM = path.distanceForIndex(rowIndex);
+          ::snprintf(buffer, 128 - count, "%03.0f %5.1fnm",
+            courseDeg, distanceM * SG_METER_TO_NM);
+        }
+    } // of is not a VIA waypoint
 
     puFont* f = &legendFont;
   f->drawString(buffer, x, baseline);
index cae2fd7110129dbba2ae49208296df1d7f0d3042..8f7ccb6685af48976cef851ff2f60196b248bac1 100644 (file)
@@ -179,8 +179,8 @@ struct TurnInfo
 };
 
 /**
- * given a turn exit position and heading, and an arbitrary origin postion, 
- * compute the turn center / angle the matches. Certain configurations may
+ * given a turn exit position and heading, and an arbitrary origin position,
+ * compute the turn center / angle that matches. Certain configurations may
  * fail, especially if the origin is less than two turn radii from the exit pos.
  */
 TurnInfo turnCenterAndAngleFromExit(const SGGeod& pt, double outHeadingDeg,
@@ -199,7 +199,7 @@ TurnInfo turnCenterAndAngleFromExit(const SGGeod& pt, double outHeadingDeg,
     double courseToTC, distanceToTC, az2;
     SGGeodesy::inverse(origin, r.turnCenter, courseToTC, az2, distanceToTC);
     if (distanceToTC < turnRadiusM) {
-        SG_LOG(SG_NAVAID, SG_WARN, "turnCenterAndAngleFromExit: origin point to close to turn center");
+        SG_LOG(SG_NAVAID, SG_WARN, "turnCenterAndAngleFromExit: origin point too close to turn center");
         return r;
     }
 
@@ -253,6 +253,8 @@ public:
       if (ty == "hdgToAlt") {
         flyOver = true;
       }
+    } else if (ty == "discontinuity") {
+
     } else {
       pos = wpt->position();
       posValid = true;
@@ -284,8 +286,11 @@ public:
       }
     }
 
-    if (posValid && !legCourseValid && previous.posValid) {
-    // check for duplicate points now
+    if (wpt->type() == "via") {
+        // even though both ends may be known, we don't
+        // want to compute a leg course for a VIA
+    } else if (posValid && !legCourseValid && previous.posValid) {
+        // check for duplicate points now
       if (previous.wpt->matches(wpt)) {
           skipped = true;
       }
@@ -300,7 +305,7 @@ public:
             legCourseTrue = SGGeodesy::courseDeg(previous.pos, pos);
             legCourseValid = true;
         }
-    }
+    } // of not a VIA
   }
 
   void computeLegCourse(const WayptData& previous, double radiusM)
@@ -309,8 +314,12 @@ public:
           return;
       }
 
-      if (wpt->type() == "hold") {
-
+      if ((wpt->type() == "hold") ||
+              (wpt->type() == "discontinuity") ||
+              (wpt->type()  == "via"))
+      {
+          // do nothing, we can't compute a valid leg course for these types
+          // we'll generate shrap turns in the path but that's no problem.
       } else if (wpt->type() == "runway") {
           FGRunway* rwy = static_cast<RunwayWaypt*>(wpt.get())->runway();
           flyOver = true;
@@ -339,7 +348,7 @@ public:
               legCourseTrue = wpt->headingRadialDeg() + magVar;
               legCourseValid = true;
           } // of pos not valid
-      } // of neither hold nor runway
+      } // of general case
   }
 
     SGGeod pointOnEntryTurnFromHeading(double headingDeg) const
@@ -1000,6 +1009,14 @@ SGGeodVec RoutePath::pathForIndex(int index) const
       // ideally we'd show a stippled line to connect the route?
     return SGGeodVec();
   }
+
+  if (ty == "discontinuity") {
+    return SGGeodVec(); // no points for a discontinuity of course
+  }
+
+  if (ty == "via") {
+      return pathForVia(static_cast<Via*>(d->waypoints[index].wpt.get()), index);
+  }
   
   if (ty== "hold") {
     return pathForHold((Hold*) d->waypoints[index].wpt.get());
@@ -1061,6 +1078,28 @@ SGGeod RoutePath::positionForIndex(int index) const
   return d->waypoints[index].pos;
 }
 
+SGGeodVec RoutePath::pathForVia(Via* via, int index) const
+{
+    // previous waypoint must be valid for a VIA
+    if ((index == 0) || !d->waypoints[index-1].posValid) {
+        return SGGeodVec();
+    }
+
+    const WayptData& prev(d->waypoints[index-1]);
+    WayptVec enrouteWaypoints = via->expandToWaypoints(prev.wpt);
+    SGGeodVec r;
+
+    WayptVec::const_iterator it;
+    SGGeod legStart = prev.wpt->position();
+    for (it = enrouteWaypoints.begin(); it != enrouteWaypoints.end(); ++it) {
+        // interpolate directly into the result vector
+        interpolateGreatCircle(legStart, (*it)->position(), r);
+        legStart = (*it)->position();
+    }
+
+    return r;
+}
+
 SGGeodVec RoutePath::pathForHold(Hold* hold) const
 {
   int turnSteps = 16;
@@ -1117,6 +1156,11 @@ double RoutePath::computeDistanceForIndex(int index) const
         return 0.0;
     }
 
+
+    if (d->waypoints[index].wpt->type() == "via") {
+        return distanceForVia(static_cast<Via*>(d->waypoints[index].wpt.get()), index);
+    }
+
     const WayptData& prev(d->previousValidWaypoint(index));
   double dist = SGGeodesy::distanceM(prev.turnExitPos,
                               d->waypoints[index].turnEntryPos);
@@ -1130,6 +1174,27 @@ double RoutePath::computeDistanceForIndex(int index) const
   return dist;
 }
 
+double RoutePath::distanceForVia(Via* via, int index) const
+{
+    // previous waypoint must be valid for a VIA
+    if ((index == 0) || !d->waypoints[index-1].posValid) {
+        return 0.0;
+    }
+
+    const WayptData& prev(d->waypoints[index-1]);
+    WayptVec enrouteWaypoints = via->expandToWaypoints(prev.wpt);
+    double dist = 0.0;
+
+    WayptVec::const_iterator it;
+    SGGeod legStart = prev.wpt->position();
+    for (it = enrouteWaypoints.begin(); it != enrouteWaypoints.end(); ++it) {
+        dist += SGGeodesy::distanceM(legStart, (*it)->position());
+        legStart = (*it)->position();
+    }
+
+    return dist;
+}
+
 double RoutePath::trackForIndex(int index) const
 {
     if (d->waypoints[index].skipped)
@@ -1190,8 +1255,12 @@ SGGeod RoutePath::positionForDistanceFrom(int index, double distanceM) const
         return d->waypoints[sz - 1].pos;
     }
 
+
     const WayptData& wpt(d->waypoints[index]);
     const WayptData& next(d->waypoints[index+1]);
+    if (next.wpt->type() == "via") {
+        return positionAlongVia(static_cast<Via*>(next.wpt.get()), index, distanceM);
+    }
 
     if (wpt.turnPathDistanceM > distanceM) {
         // on the exit path of current wpt
@@ -1209,3 +1278,8 @@ SGGeod RoutePath::positionForDistanceFrom(int index, double distanceM) const
     // linear between turn exit and turn entry points
     return SGGeodesy::direct(wpt.turnExitPos, next.legCourseTrue, distanceM);
 }
+
+SGGeod RoutePath::positionAlongVia(Via* via, int previousIndex, double distanceM) const
+{
+
+}
index 49b44de4a01d2b3db0285700b765980c6eac86b8..b6e3102bf6c19e5c9a333a76ef087315ada46c21 100644 (file)
@@ -31,6 +31,7 @@ namespace flightgear
 {
   class Hold;
   class FlightPlan;
+  class Via;
 }
 
 typedef std::vector<SGGeod> SGGeodVec;
@@ -59,9 +60,13 @@ private:
   void commonInit();
   
   double computeDistanceForIndex(int index) const;
-    
+
+  double distanceForVia(flightgear::Via *via, int index) const;
+
+
   SGGeodVec pathForHold(flightgear::Hold* hold) const;
-  
+  SGGeodVec pathForVia(flightgear::Via* via, int index) const;
+  SGGeod positionAlongVia(flightgear::Via* via, int previousIndex, double distanceM) const;
   
   void interpolateGreatCircle(const SGGeod& aFrom, const SGGeod& aTo, SGGeodVec& r) const;