delete cur;
}
}
+
+// delete legs
+ BOOST_FOREACH(Leg* l, _legs) {
+ delete l;
+ }
}
FlightPlan* FlightPlan::clone(const string& newIdent) const
}
_legs.clear();
+ if (_delegate) {
+ _delegate->runCleared();
+ }
unlockDelegate();
}
++count;
}
}
+
+ // test if the current leg will be removed
+ bool currentIsBeingCleared = false;
+ Leg* curLeg = currentLeg();
+ if (curLeg) {
+ currentIsBeingCleared = curLeg->waypoint()->flag(flag);
+ }
_currentIndex -= count;
+
+ // if we're clearing the current waypoint, what shall we do with the
+ // index? there's various options, but safest is to select no waypoint
+ // and let the use re-activate.
+ // http://code.google.com/p/flightgear-bugs/issues/detail?id=1134
+ if (currentIsBeingCleared) {
+ SG_LOG(SG_GENERAL, SG_INFO, "currentIsBeingCleared:" << currentIsBeingCleared);
+ _currentIndex = -1;
+ }
// now delete and remove
RemoveWithFlag rf(flag);
lockDelegate();
_waypointsChanged = true;
- if (count > 0) {
+ if ((count > 0) || currentIsBeingCleared) {
_currentWaypointChanged = true;
}
_legs.erase(it, _legs.end());
+
+ if (_legs.empty()) { // maybe all legs were deleted
+ if (_delegate) {
+ _delegate->runCleared();
+ }
+ }
+
unlockDelegate();
return rf.numDeleted();
}
_currentWaypointChanged = true;
unlockDelegate();
}
+
+void FlightPlan::finish()
+{
+ if (_currentIndex == -1) {
+ return;
+ }
+
+ lockDelegate();
+ _currentIndex = -1;
+ _currentWaypointChanged = true;
+
+ if (_delegate) {
+ _delegate->runFinished();
+ }
+
+ unlockDelegate();
+}
int FlightPlan::findWayptIndex(const SGGeod& aPos) const
{
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")) {
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")) {
} 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);
}
}
+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) {
_deleteWithPlan(false),
_inner(NULL)
{
-
}
FlightPlan::Delegate::~Delegate()
-{
-
+{
}
void FlightPlan::Delegate::removeInner(Delegate* d)
{
if (!_inner) {
- return;
+ throw sg_exception("FlightPlan delegate not found");
}
if (_inner == d) {
if (_inner) _inner->runCurrentWaypointChanged();
currentWaypointChanged();
}
-
+
+void FlightPlan::Delegate::runCleared()
+{
+ if (_inner) _inner->runCleared();
+ cleared();
+}
+
+void FlightPlan::Delegate::runFinished()
+{
+ if (_inner) _inner->runFinished();
+ endOfFlightPlan();
+}
+
} // of namespace flightgear