]> git.mxchange.org Git - flightgear.git/blobdiff - src/Navaids/FlightPlan.cxx
Flightplan delegate hook for clearing the FP.
[flightgear.git] / src / Navaids / FlightPlan.cxx
index fd7f7fb1d20e4464d695aedd80613833db1c997c..eda1e2db5e6f852cf44af8c1bc3b476b73e2726e 100644 (file)
@@ -189,7 +189,7 @@ void FlightPlan::deleteIndex(int aIndex)
   }
   
   if ((index < 0) || (index >= numLegs())) {
-    SG_LOG(SG_AUTOPILOT, SG_WARN, "removeAtIndex with invalid index:" << aIndex);
+    SG_LOG(SG_NAVAID, SG_WARN, "removeAtIndex with invalid index:" << aIndex);
     return;
   }
   
@@ -226,6 +226,9 @@ void FlightPlan::clear()
   }
   _legs.clear();  
   
+  if (_delegate) {
+    _delegate->runCleared();
+  }
   unlockDelegate();
 }
   
@@ -239,7 +242,6 @@ public:
   bool operator()(FlightPlan::Leg* leg) const
   {
     if (leg->waypoint()->flag(flag)) {
-      std::cout << "deleting" << leg << std::endl;
       delete leg;
       ++delCount;
       return true;
@@ -512,7 +514,7 @@ void FlightPlan::setApproach(flightgear::Approach *app)
   
 bool FlightPlan::save(const SGPath& path)
 {
-  SG_LOG(SG_IO, SG_INFO, "Saving route to " << path.str());
+  SG_LOG(SG_NAVAID, SG_INFO, "Saving route to " << path.str());
   try {
     SGPropertyNode_ptr d(new SGPropertyNode);
     d->setIntValue("version", 2);
@@ -554,7 +556,7 @@ bool FlightPlan::save(const SGPath& path)
     writeProperties(path.str(), d, true /* write-all */);
     return true;
   } catch (sg_exception& e) {
-    SG_LOG(SG_IO, SG_ALERT, "Failed to save flight-plan '" << path.str() << "'. " << e.getMessage());
+    SG_LOG(SG_NAVAID, SG_ALERT, "Failed to save flight-plan '" << path.str() << "'. " << e.getMessage());
     return false;
   }
 }
@@ -563,13 +565,13 @@ bool FlightPlan::load(const SGPath& path)
 {
   if (!path.exists())
   {
-    SG_LOG(SG_IO, SG_ALERT, "Failed to load flight-plan '" << path.str()
+    SG_LOG(SG_NAVAID, SG_ALERT, "Failed to load flight-plan '" << path.str()
            << "'. The file does not exist.");
     return false;
   }
   
   SGPropertyNode_ptr routeData(new SGPropertyNode);
-  SG_LOG(SG_IO, SG_INFO, "going to read flight-plan from:" << path.str());
+  SG_LOG(SG_NAVAID, SG_INFO, "going to read flight-plan from:" << path.str());
   
   bool Status = false;
   lockDelegate();
@@ -595,7 +597,7 @@ bool FlightPlan::load(const SGPath& path)
       }
       Status = true;
     } catch (sg_exception& e) {
-      SG_LOG(SG_IO, SG_ALERT, "Failed to load flight-plan '" << e.getOrigin()
+      SG_LOG(SG_NAVAID, SG_ALERT, "Failed to load flight-plan '" << e.getOrigin()
              << "'. " << e.getMessage());
       Status = false;
     }
@@ -613,8 +615,9 @@ void FlightPlan::loadXMLRouteHeader(SGPropertyNode_ptr routeData)
     string depIdent = dep->getStringValue("airport");
     setDeparture((FGAirport*) fgFindAirportID(depIdent));
     if (_departure) {
-      if (dep->hasChild("runway")) {
-        setDeparture(_departure->getRunwayByIdent(dep->getStringValue("runway")));
+      string rwy(dep->getStringValue("runway"));
+      if (_departure->hasRunwayWithIdent(rwy)) {
+        setDeparture(_departure->getRunwayByIdent(rwy));
       }
     
       if (dep->hasChild("sid")) {
@@ -629,8 +632,9 @@ void FlightPlan::loadXMLRouteHeader(SGPropertyNode_ptr routeData)
   if (dst) {
     setDestination((FGAirport*) fgFindAirportID(dst->getStringValue("airport")));
     if (_destination) {
-      if (dst->hasChild("runway")) {
-        setDestination(_destination->getRunwayByIdent(dst->getStringValue("runway")));
+      string rwy(dst->getStringValue("runway"));
+      if (_destination->hasRunwayWithIdent(rwy)) {
+        setDestination(_destination->getRunwayByIdent(rwy));
       }
       
       if (dst->hasChild("star")) {
@@ -710,18 +714,23 @@ WayptRef FlightPlan::parseVersion1XMLWaypt(SGPropertyNode* aWP)
   } else {
     string nid = aWP->getStringValue("navid", ident.c_str());
     FGPositionedRef p = FGPositioned::findClosestWithIdent(nid, lastPos);
-    if (!p) {
-      throw sg_io_exception("bad route file, unknown navid:" + nid);
+    SGGeod pos;
+    
+    if (p) {
+      pos = p->geod();
+    } else {
+      SG_LOG(SG_GENERAL, SG_WARN, "unknown navaid in flightplan:" << nid);
+      pos = SGGeod::fromDeg(aWP->getDoubleValue("longitude-deg"),
+                            aWP->getDoubleValue("latitude-deg"));
     }
     
-    SGGeod pos(p->geod());
     if (aWP->hasChild("offset-nm") && aWP->hasChild("offset-radial")) {
       double radialDeg = aWP->getDoubleValue("offset-radial");
       // convert magnetic radial to a true radial!
       radialDeg += magvarDegAt(pos);
       double offsetNm = aWP->getDoubleValue("offset-nm");
       double az2;
-      SGGeodesy::direct(p->geod(), radialDeg, offsetNm * SG_NM_TO_METER, pos, az2);
+      SGGeodesy::direct(pos, radialDeg, offsetNm * SG_NM_TO_METER, pos, az2);
     }
     
     w = new BasicWaypt(pos, ident, NULL);
@@ -765,7 +774,7 @@ bool FlightPlan::loadPlainTextRoute(const SGPath& path)
       _legs.push_back(new Leg(this, w));
     } // of line iteration
   } catch (sg_exception& e) {
-    SG_LOG(SG_IO, SG_ALERT, "Failed to load route from: '" << path.str() << "'. " << e.getMessage());
+    SG_LOG(SG_NAVAID, SG_ALERT, "Failed to load route from: '" << path.str() << "'. " << e.getMessage());
     _legs.clear();
     return false;
   }
@@ -825,7 +834,7 @@ WayptRef FlightPlan::waypointFromString(const string& tgt )
   string_list pieces(simgear::strutils::split(target, "/"));
   FGPositionedRef p = FGPositioned::findClosestWithIdent(pieces.front(), basePosition);
   if (!p) {
-    SG_LOG( SG_AUTOPILOT, SG_INFO, "Unable to find FGPositioned with ident:" << pieces.front());
+    SG_LOG( SG_NAVAID, SG_INFO, "Unable to find FGPositioned with ident:" << pieces.front());
     return NULL;
   }
   
@@ -842,12 +851,12 @@ WayptRef FlightPlan::waypointFromString(const string& tgt )
   } else if (pieces.size() == 2) {
     FGAirport* apt = dynamic_cast<FGAirport*>(p.ptr());
     if (!apt) {
-      SG_LOG(SG_AUTOPILOT, SG_INFO, "Waypoint is not an airport:" << pieces.front());
+      SG_LOG(SG_NAVAID, SG_INFO, "Waypoint is not an airport:" << pieces.front());
       return NULL;
     }
     
     if (!apt->hasRunwayWithIdent(pieces[1])) {
-      SG_LOG(SG_AUTOPILOT, SG_INFO, "No runway: " << pieces[1] << " at " << pieces[0]);
+      SG_LOG(SG_NAVAID, SG_INFO, "No runway: " << pieces[1] << " at " << pieces[0]);
       return NULL;
     }
     
@@ -857,7 +866,7 @@ WayptRef FlightPlan::waypointFromString(const string& tgt )
     // navid/radial/navid/radial notation     
     FGPositionedRef p2 = FGPositioned::findClosestWithIdent(pieces[2], basePosition);
     if (!p2) {
-      SG_LOG( SG_AUTOPILOT, SG_INFO, "Unable to find FGPositioned with ident:" << pieces[2]);
+      SG_LOG( SG_NAVAID, SG_INFO, "Unable to find FGPositioned with ident:" << pieces[2]);
       return NULL;
     }
     
@@ -869,7 +878,7 @@ WayptRef FlightPlan::waypointFromString(const string& tgt )
     SGGeod intersection;
     bool ok = SGGeodesy::radialIntersection(p->geod(), r1, p2->geod(), r2, intersection);
     if (!ok) {
-      SG_LOG(SG_AUTOPILOT, SG_INFO, "no valid intersection for:" << target);
+      SG_LOG(SG_NAVAID, SG_INFO, "no valid intersection for:" << target);
       return NULL;
     }
     
@@ -878,7 +887,7 @@ WayptRef FlightPlan::waypointFromString(const string& tgt )
   }
   
   if (!wpt) {
-    SG_LOG(SG_AUTOPILOT, SG_INFO, "Unable to parse waypoint:" << target);
+    SG_LOG(SG_NAVAID, SG_INFO, "Unable to parse waypoint:" << target);
     return NULL;
   }
   
@@ -1029,6 +1038,39 @@ void FlightPlan::rebuildLegData()
   }
 }
   
+SGGeod FlightPlan::pointAlongRoute(int aIndex, double aOffsetNm) const
+{
+  if (aIndex >= (int) _legs.size()) {
+    throw sg_range_exception();
+  }
+  
+  const int lastLeg = static_cast<int>(_legs.size()) - 1;
+// convert the relative offset and leg index into an absolute, positive
+// distance in nm from the route origin. This means we can simply walk
+// forwards to find the actual leg.
+  Leg* leg = _legs[(aIndex >= 0) ? aIndex : lastLeg];
+  double absolutePathDistance = leg->_distanceAlongPath + aOffsetNm;
+  if (absolutePathDistance < 0.0) {
+    return _legs[0]->waypoint()->position(); // begining of route
+  }
+  
+  if (absolutePathDistance > _totalDistance) {
+    return _legs[lastLeg]->waypoint()->position(); // end of route
+  }
+  
+// find the leg containing the absolute distance
+  for (int l=0; l<lastLeg; ++l) {
+    leg = _legs[l];
+    if (absolutePathDistance < leg->_pathDistance) {
+      break; // found our matching leg
+    }
+    absolutePathDistance -= leg->_pathDistance;
+  } // of forwards walk along route to find leg
+  
+  return SGGeodesy::direct(leg->waypoint()->position(),
+                               leg->_courseDeg, absolutePathDistance * SG_NM_TO_METER);
+}
+    
 void FlightPlan::lockDelegate()
 {
   if (_delegateLock == 0) {
@@ -1166,5 +1208,11 @@ void FlightPlan::Delegate::runCurrentWaypointChanged()
   if (_inner) _inner->runCurrentWaypointChanged();
   currentWaypointChanged();
 }
+
+void FlightPlan::Delegate::runCleared()
+{
+  if (_inner) _inner->runCleared();
+  cleared();
+}  
   
 } // of namespace flightgear