"Waypt::createFromProperties");
}
- WayptRef nd(createInstance(aOwner, aProp->getStringValue("type")));
+ try {
+ WayptRef nd(createInstance(aOwner, aProp->getStringValue("type")));
+ nd->initFromProperties(aProp);
+ return nd;
+ } catch (sg_exception& e) {
+ SG_LOG(SG_GENERAL, SG_WARN, "failed to create waypoint, trying basic:" << e.getMessage());
+ }
+
+// if we failed to make the waypoint, try again making a basic waypoint.
+// this handles the case where a navaid waypoint is missing, for example
+ WayptRef nd(new BasicWaypt(aOwner));
nd->initFromProperties(aProp);
return nd;
}
std::fstream f;
f.open(p.str().c_str(), fstream::out | fstream::app);
if (!f.is_open()) {
- SG_LOG(SG_GENERAL, SG_WARN, "unable to open:" << p.str());
+ SG_LOG(SG_NAVAID, SG_WARN, "unable to open:" << p.str());
return;
}
NavdataVisitor visitor(aApt, aPath);
readXML(aPath.str(), visitor);
} catch (sg_io_exception& ex) {
- SG_LOG(SG_GENERAL, SG_WARN, "failure parsing procedures: " << aPath.str() <<
+ SG_LOG(SG_NAVAID, SG_WARN, "failure parsing procedures: " << aPath.str() <<
"\n\t" << ex.getMessage() << "\n\tat:" << ex.getLocation().asString());
} catch (sg_exception& ex) {
- SG_LOG(SG_GENERAL, SG_WARN, "failure parsing procedures: " << aPath.str() <<
+ SG_LOG(SG_NAVAID, SG_WARN, "failure parsing procedures: " << aPath.str() <<
"\n\t" << ex.getMessage());
}
}
-
-////////////////////////////////////////////////////////////////////////////
-
-FlightPlan::FlightPlan() :
- _currentIndex(-1),
- _departureRunway(NULL),
- _destinationRunway(NULL),
- _sid(NULL),
- _star(NULL),
- _approach(NULL),
- _delegate(NULL)
-{
-
-}
-
-FlightPlan::~FlightPlan()
-{
-
-}
-
-FlightPlan* FlightPlan::clone(const string& newIdent) const
-{
- FlightPlan* c = new FlightPlan();
- c->_ident = newIdent.empty() ? _ident : newIdent;
-
-// copy destination / departure data.
- c->setDeparture(_departure);
- c->setDeparture(_departureRunway);
-
- if (_approach) {
- c->setApproach(_approach);
- } else if (_destinationRunway) {
- c->setDestination(_destinationRunway);
- } else if (_destination) {
- c->setDestination(_destination);
- }
-
- c->setSTAR(_star);
- c->setSID(_sid);
-
-// copy legs
- for (int l=0; l < numLegs(); ++l) {
- c->_legs.push_back(_legs[l]->cloneFor(c));
- }
-
- return c;
-}
-
-void FlightPlan::setIdent(const string& s)
-{
- _ident = s;
-}
-
-string FlightPlan::ident() const
-{
- return _ident;
-}
-
-FlightPlan::Leg* FlightPlan::insertWayptAtIndex(Waypt* aWpt, int aIndex)
-{
- if (!aWpt) {
- return NULL;
- }
-
- WayptVec wps;
- wps.push_back(aWpt);
-
- int index = aIndex;
- if ((aIndex == -1) || (aIndex > (int) _legs.size())) {
- index = _legs.size();
- }
-
- insertWayptsAtIndex(wps, index);
- return legAtIndex(aIndex);
-}
-
-void FlightPlan::insertWayptsAtIndex(const WayptVec& wps, int aIndex)
-{
- if (wps.empty()) {
- return;
- }
-
- int index = aIndex;
- if ((aIndex == -1) || (aIndex > (int) _legs.size())) {
- index = _legs.size();
- }
-
- LegVec::iterator it = _legs.begin();
- it += index;
-
- int endIndex = index + wps.size() - 1;
- if (_currentIndex >= endIndex) {
- _currentIndex += wps.size();
- }
-
- LegVec newLegs;
- BOOST_FOREACH(WayptRef wp, wps) {
- newLegs.push_back(new Leg(this, wp));
- }
-
- _legs.insert(it, newLegs.begin(), newLegs.end());
- rebuildLegData();
-
- if (_delegate) {
- _delegate->runWaypointsChanged();
- }
-}
-
-void FlightPlan::deleteIndex(int aIndex)
-{
- int index = aIndex;
- if (aIndex < 0) { // negative indices count the the end
- index = _legs.size() + index;
- }
-
- if ((index < 0) || (index >= numLegs())) {
- SG_LOG(SG_AUTOPILOT, SG_WARN, "removeAtIndex with invalid index:" << aIndex);
- return;
- }
- LegVec::iterator it = _legs.begin();
- it += index;
- Leg* l = *it;
- _legs.erase(it);
- delete l;
-
- bool curChanged = false;
- if (_currentIndex == index) {
- // current waypoint was removed
- curChanged = true;
- } else if (_currentIndex > index) {
- --_currentIndex; // shift current index down if necessary
- }
-
- rebuildLegData();
- if (_delegate) {
- _delegate->runWaypointsChanged();
- if (curChanged) {
- _delegate->runCurrentWaypointChanged();
- }
- }
-}
-
-void FlightPlan::clear()
-{
- _currentIndex = -1;
- BOOST_FOREACH(Leg* l, _legs) {
- delete l;
- }
- _legs.clear();
- rebuildLegData();
- if (_delegate) {
- _delegate->runDepartureChanged();
- _delegate->runArrivalChanged();
- _delegate->runWaypointsChanged();
- _delegate->runCurrentWaypointChanged();
- }
-}
-
-int FlightPlan::clearWayptsWithFlag(WayptFlag flag)
-{
- int count = 0;
- for (unsigned int i=0; i<_legs.size(); ++i) {
- Leg* l = _legs[i];
- if (!l->waypoint()->flag(flag)) {
- continue;
- }
-
- // okay, we're going to clear this leg
- ++count;
- if (_currentIndex > (int) i) {
- --_currentIndex;
- }
-
- delete l;
- LegVec::iterator it = _legs.begin();
- it += i;
- _legs.erase(it);
- }
-
- if (count == 0) {
- return 0; // nothing was cleared, don't fire the delegate
- }
-
- rebuildLegData();
- if (_delegate) {
- _delegate->runWaypointsChanged();
- _delegate->runCurrentWaypointChanged();
- }
-
- return count;
-}
-
-void FlightPlan::setCurrentIndex(int index)
-{
- if ((index < -1) || (index >= numLegs())) {
- throw sg_range_exception("invalid leg index", "FlightPlan::setCurrentIndex");
- }
-
- if (index == _currentIndex) {
- return;
- }
-
- _currentIndex = index;
- if (_delegate) {
- _delegate->runCurrentWaypointChanged();
- }
-}
-
-int FlightPlan::findWayptIndex(const SGGeod& aPos) const
-{
- for (int i=0; i<numLegs(); ++i) {
- if (_legs[i]->waypoint()->matches(aPos)) {
- return i;
- }
- }
-
- return -1;
-}
-
-FlightPlan::Leg* FlightPlan::currentLeg() const
-{
- if ((_currentIndex < 0) || (_currentIndex >= numLegs()))
- return NULL;
- return legAtIndex(_currentIndex);
-}
-
-FlightPlan::Leg* FlightPlan::previousLeg() const
-{
- if (_currentIndex == 0) {
- return NULL;
- }
-
- return legAtIndex(_currentIndex - 1);
-}
-
-FlightPlan::Leg* FlightPlan::nextLeg() const
-{
- if ((_currentIndex < 0) || ((_currentIndex + 1) >= numLegs())) {
- return NULL;
- }
-
- return legAtIndex(_currentIndex + 1);
-}
-
-FlightPlan::Leg* FlightPlan::legAtIndex(int index) const
-{
- if ((index < 0) || (index >= numLegs())) {
- throw sg_range_exception("index out of range", "FlightPlan::legAtIndex");
- }
-
- return _legs[index];
-}
-
-int FlightPlan::findLegIndex(const Leg *l) const
-{
- for (unsigned int i=0; i<_legs.size(); ++i) {
- if (_legs[i] == l) {
- return i;
- }
- }
-
- return -1;
-}
-
-void FlightPlan::setDeparture(FGAirport* apt)
-{
- if (apt == _departure) {
- return;
- }
-
- _departure = apt;
- _departureRunway = NULL;
- setSID((SID*)NULL);
-
- if (_delegate) {
- _delegate->runDepartureChanged();
- }
-}
-
-void FlightPlan::setDeparture(FGRunway* rwy)
-{
- if (_departureRunway == rwy) {
- return;
- }
-
- _departureRunway = rwy;
- if (rwy->airport() != _departure) {
- _departure = rwy->airport();
- setSID((SID*)NULL);
- }
-
- if (_delegate) {
- _delegate->runDepartureChanged();
- }
-}
-
-void FlightPlan::setSID(SID* sid, const std::string& transition)
-{
- if (sid == _sid) {
- return;
- }
-
- _sid = sid;
- _sidTransition = transition;
-
- if (_delegate) {
- _delegate->runDepartureChanged();
- }
-}
-
-void FlightPlan::setSID(Transition* trans)
-{
- if (!trans) {
- setSID((SID*) NULL);
- return;
- }
-
- if (trans->parent()->type() != PROCEDURE_SID)
- throw sg_exception("FlightPlan::setSID: transition does not belong to a SID");
-
- setSID((SID*) trans->parent(), trans->ident());
-}
-
-Transition* FlightPlan::sidTransition() const
-{
- if (!_sid || _sidTransition.empty()) {
- return NULL;
- }
-
- return _sid->findTransitionByName(_sidTransition);
-}
-
-void FlightPlan::setDestination(FGAirport* apt)
-{
- if (apt == _destination) {
- return;
- }
-
- _destination = apt;
- _destinationRunway = NULL;
- setSTAR((STAR*)NULL);
-
- if (_delegate) {
- _delegate->runArrivalChanged();
- }
-}
-
-void FlightPlan::setDestination(FGRunway* rwy)
-{
- if (_destinationRunway == rwy) {
- return;
- }
-
- _destinationRunway = rwy;
- if (_destination != rwy->airport()) {
- _destination = rwy->airport();
- setSTAR((STAR*)NULL);
- }
-
- if (_delegate) {
- _delegate->runArrivalChanged();
- }
-}
-
-void FlightPlan::setSTAR(STAR* star, const std::string& transition)
-{
- if (_star == star) {
- return;
- }
-
- _star = star;
- _starTransition = transition;
-
- if (_delegate) {
- _delegate->runArrivalChanged();
- }
-}
-
-void FlightPlan::setSTAR(Transition* trans)
-{
- if (!trans) {
- setSTAR((STAR*) NULL);
- return;
- }
-
- if (trans->parent()->type() != PROCEDURE_STAR)
- throw sg_exception("FlightPlan::setSTAR: transition does not belong to a STAR");
-
- setSTAR((STAR*) trans->parent(), trans->ident());
-}
-
-Transition* FlightPlan::starTransition() const
-{
- if (!_star || _starTransition.empty()) {
- return NULL;
- }
-
- return _star->findTransitionByName(_starTransition);
-}
-
-void FlightPlan::setApproach(flightgear::Approach *app)
-{
- if (_approach == app) {
- return;
- }
-
- _approach = app;
- if (app) {
- // keep runway + airport in sync
- if (_destinationRunway != _approach->runway()) {
- _destinationRunway = _approach->runway();
- }
-
- if (_destination != _destinationRunway->airport()) {
- _destination = _destinationRunway->airport();
- }
- }
-
- if (_delegate) {
- _delegate->runArrivalChanged();
- }
-}
-
-bool FlightPlan::save(const SGPath& path)
-{
- SG_LOG(SG_IO, SG_INFO, "Saving route to " << path.str());
- try {
- SGPropertyNode_ptr d(new SGPropertyNode);
- d->setIntValue("version", 2);
-
- if (_departure) {
- d->setStringValue("departure/airport", _departure->ident());
- if (_sid) {
- d->setStringValue("departure/sid", _sid->ident());
- }
-
- if (_departureRunway) {
- d->setStringValue("departure/runway", _departureRunway->ident());
- }
- }
-
- if (_destination) {
- d->setStringValue("destination/airport", _destination->ident());
- if (_star) {
- d->setStringValue("destination/star", _star->ident());
- }
-
- if (_approach) {
- d->setStringValue("destination/approach", _approach->ident());
- }
-
- //d->setStringValue("destination/transition", destination->getStringValue("transition"));
-
- if (_destinationRunway) {
- d->setStringValue("destination/runway", _destinationRunway->ident());
- }
- }
-
- // route nodes
- SGPropertyNode* routeNode = d->getChild("route", 0, true);
- for (unsigned int i=0; i<_legs.size(); ++i) {
- Waypt* wpt = _legs[i]->waypoint();
- wpt->saveAsNode(routeNode->getChild("wp", i, true));
- } // of waypoint iteration
- 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());
- return false;
- }
-}
-
-bool FlightPlan::load(const SGPath& path)
-{
- if (!path.exists())
- {
- SG_LOG(SG_IO, 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());
-
- bool Status = false;
- try {
- readProperties(path.str(), routeData);
- } catch (sg_exception& ) {
- // if XML parsing fails, the file might be simple textual list of waypoints
- Status = loadPlainTextRoute(path);
- routeData = 0;
- }
-
- if (routeData.valid())
- {
- try {
- int version = routeData->getIntValue("version", 1);
- if (version == 1) {
- loadVersion1XMLRoute(routeData);
- } else if (version == 2) {
- loadVersion2XMLRoute(routeData);
- } else {
- throw sg_io_exception("unsupported XML route version");
- }
- Status = true;
- } catch (sg_exception& e) {
- SG_LOG(SG_IO, SG_ALERT, "Failed to load flight-plan '" << e.getOrigin()
- << "'. " << e.getMessage());
- Status = false;
- }
- }
-
- rebuildLegData();
- if (_delegate) {
- _delegate->runWaypointsChanged();
- }
-
- return Status;
-}
-
-void FlightPlan::loadXMLRouteHeader(SGPropertyNode_ptr routeData)
-{
- // departure nodes
- SGPropertyNode* dep = routeData->getChild("departure");
- if (dep) {
- string depIdent = dep->getStringValue("airport");
- setDeparture((FGAirport*) fgFindAirportID(depIdent));
- if (_departure) {
- if (dep->hasChild("runway")) {
- setDeparture(_departure->getRunwayByIdent(dep->getStringValue("runway")));
- }
-
- if (dep->hasChild("sid")) {
- setSID(_departure->findSIDWithIdent(dep->getStringValue("sid")));
- }
- // departure->setStringValue("transition", dep->getStringValue("transition"));
- }
- }
-
- // destination
- SGPropertyNode* dst = routeData->getChild("destination");
- if (dst) {
- setDestination((FGAirport*) fgFindAirportID(dst->getStringValue("airport")));
- if (_destination) {
- if (dst->hasChild("runway")) {
- setDestination(_destination->getRunwayByIdent(dst->getStringValue("runway")));
- }
-
- if (dst->hasChild("star")) {
- setSTAR(_destination->findSTARWithIdent(dst->getStringValue("star")));
- }
-
- if (dst->hasChild("approach")) {
- setApproach(_destination->findApproachWithIdent(dst->getStringValue("approach")));
- }
- }
-
- // destination->setStringValue("transition", dst->getStringValue("transition"));
- }
-
- // alternate
- SGPropertyNode* alt = routeData->getChild("alternate");
- if (alt) {
- //alternate->setStringValue(alt->getStringValue("airport"));
- }
-
- // cruise
- SGPropertyNode* crs = routeData->getChild("cruise");
- if (crs) {
- // cruise->setDoubleValue("speed-kts", crs->getDoubleValue("speed-kts"));
- // cruise->setDoubleValue("mach", crs->getDoubleValue("mach"));
- // cruise->setDoubleValue("altitude-ft", crs->getDoubleValue("altitude-ft"));
- } // of cruise data loading
-
-}
-
-void FlightPlan::loadVersion2XMLRoute(SGPropertyNode_ptr routeData)
-{
- loadXMLRouteHeader(routeData);
-
- // route nodes
- _legs.clear();
- SGPropertyNode_ptr routeNode = routeData->getChild("route", 0);
- for (int i=0; i<routeNode->nChildren(); ++i) {
- SGPropertyNode_ptr wpNode = routeNode->getChild("wp", i);
- Leg* l = new Leg(this, Waypt::createFromProperties(NULL, wpNode));
- _legs.push_back(l);
- } // of route iteration
-}
-
-void FlightPlan::loadVersion1XMLRoute(SGPropertyNode_ptr routeData)
-{
- loadXMLRouteHeader(routeData);
-
- // _legs nodes
- _legs.clear();
- SGPropertyNode_ptr routeNode = routeData->getChild("route", 0);
- for (int i=0; i<routeNode->nChildren(); ++i) {
- SGPropertyNode_ptr wpNode = routeNode->getChild("wp", i);
- Leg* l = new Leg(this, parseVersion1XMLWaypt(wpNode));
- _legs.push_back(l);
- } // of route iteration
-
-}
-
-WayptRef FlightPlan::parseVersion1XMLWaypt(SGPropertyNode* aWP)
-{
- SGGeod lastPos;
- if (!_legs.empty()) {
- lastPos = _legs.back()->waypoint()->position();
- } else if (_departure) {
- lastPos = _departure->geod();
- }
-
- WayptRef w;
- string ident(aWP->getStringValue("ident"));
- if (aWP->hasChild("longitude-deg")) {
- // explicit longitude/latitude
- w = new BasicWaypt(SGGeod::fromDeg(aWP->getDoubleValue("longitude-deg"),
- aWP->getDoubleValue("latitude-deg")), ident, NULL);
-
- } 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(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);
- }
-
- w = new BasicWaypt(pos, ident, NULL);
- }
-
- double altFt = aWP->getDoubleValue("altitude-ft", -9999.9);
- if (altFt > -9990.0) {
- w->setAltitude(altFt, RESTRICT_AT);
- }
-
- return w;
-}
-
-bool FlightPlan::loadPlainTextRoute(const SGPath& path)
-{
- try {
- sg_gzifstream in(path.str().c_str());
- if (!in.is_open()) {
- throw sg_io_exception("Cannot open file for reading.");
- }
-
- _legs.clear();
- while (!in.eof()) {
- string line;
- getline(in, line, '\n');
- // trim CR from end of line, if found
- if (line[line.size() - 1] == '\r') {
- line.erase(line.size() - 1, 1);
- }
-
- line = simgear::strutils::strip(line);
- if (line.empty() || (line[0] == '#')) {
- continue; // ignore empty/comment lines
- }
-
- WayptRef w = waypointFromString(line);
- if (!w) {
- throw sg_io_exception("Failed to create waypoint from line '" + line + "'.");
- }
-
- _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());
- _legs.clear();
- return false;
- }
-
- return true;
-}
-
-double FlightPlan::magvarDegAt(const SGGeod& pos) const
-{
- double jd = globals->get_time_params()->getJD();
- return sgGetMagVar(pos, jd) * SG_RADIANS_TO_DEGREES;
-}
-
-WayptRef FlightPlan::waypointFromString(const string& tgt )
-{
- string target(boost::to_upper_copy(tgt));
- WayptRef wpt;
-
- // extract altitude
- double altFt = 0.0;
- RouteRestriction altSetting = RESTRICT_NONE;
-
- size_t pos = target.find( '@' );
- if ( pos != string::npos ) {
- altFt = atof( target.c_str() + pos + 1 );
- target = target.substr( 0, pos );
- if ( !strcmp(fgGetString("/sim/startup/units"), "meter") )
- altFt *= SG_METER_TO_FEET;
- altSetting = RESTRICT_AT;
- }
-
- // check for lon,lat
- pos = target.find( ',' );
- if ( pos != string::npos ) {
- double lon = atof( target.substr(0, pos).c_str());
- double lat = atof( target.c_str() + pos + 1);
- char buf[32];
- char ew = (lon < 0.0) ? 'W' : 'E';
- char ns = (lat < 0.0) ? 'S' : 'N';
- snprintf(buf, 32, "%c%03d%c%03d", ew, (int) fabs(lon), ns, (int)fabs(lat));
-
- wpt = new BasicWaypt(SGGeod::fromDeg(lon, lat), buf, NULL);
- if (altSetting != RESTRICT_NONE) {
- wpt->setAltitude(altFt, altSetting);
- }
- return wpt;
- }
-
- SGGeod basePosition;
- if (_legs.empty()) {
- // route is empty, use current position
- basePosition = globals->get_aircraft_position();
- } else {
- basePosition = _legs.back()->waypoint()->position();
- }
-
- 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());
- return NULL;
- }
-
- double magvar = magvarDegAt(basePosition);
-
- if (pieces.size() == 1) {
- wpt = new NavaidWaypoint(p, NULL);
- } else if (pieces.size() == 3) {
- // navaid/radial/distance-nm notation
- double radial = atof(pieces[1].c_str()),
- distanceNm = atof(pieces[2].c_str());
- radial += magvar;
- wpt = new OffsetNavaidWaypoint(p, NULL, radial, distanceNm);
- } 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());
- return NULL;
- }
-
- if (!apt->hasRunwayWithIdent(pieces[1])) {
- SG_LOG(SG_AUTOPILOT, SG_INFO, "No runway: " << pieces[1] << " at " << pieces[0]);
- return NULL;
- }
-
- FGRunway* runway = apt->getRunwayByIdent(pieces[1]);
- wpt = new NavaidWaypoint(runway, NULL);
- } else if (pieces.size() == 4) {
- // 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]);
- return NULL;
- }
-
- double r1 = atof(pieces[1].c_str()),
- r2 = atof(pieces[3].c_str());
- r1 += magvar;
- r2 += magvar;
-
- 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);
- return NULL;
- }
-
- std::string name = p->ident() + "-" + p2->ident();
- wpt = new BasicWaypt(intersection, name, NULL);
- }
-
- if (!wpt) {
- SG_LOG(SG_AUTOPILOT, SG_INFO, "Unable to parse waypoint:" << target);
- return NULL;
- }
-
- if (altSetting != RESTRICT_NONE) {
- wpt->setAltitude(altFt, altSetting);
- }
- return wpt;
-}
-
-FlightPlan::Leg::Leg(FlightPlan* owner, WayptRef wpt) :
- _parent(owner),
- _speedRestrict(RESTRICT_NONE),
- _altRestrict(RESTRICT_NONE),
- _waypt(wpt)
-{
- if (!wpt.valid()) {
- throw sg_exception("can't create FlightPlan::Leg without underlying waypoint");
- }
- _speed = _altitudeFt = 0;
-}
-
-FlightPlan::Leg* FlightPlan::Leg::cloneFor(FlightPlan* owner) const
-{
- Leg* c = new Leg(owner, _waypt);
-// clone local data
- c->_speed = _speed;
- c->_speedRestrict = _speedRestrict;
- c->_altitudeFt = _altitudeFt;
- c->_altRestrict = _altRestrict;
-
- return c;
-}
-
-FlightPlan::Leg* FlightPlan::Leg::nextLeg() const
-{
- return _parent->legAtIndex(index() + 1);
-}
-
-unsigned int FlightPlan::Leg::index() const
-{
- return _parent->findLegIndex(this);
-}
-
-int FlightPlan::Leg::altitudeFt() const
-{
- if (_altRestrict != RESTRICT_NONE) {
- return _altitudeFt;
- }
-
- return _waypt->altitudeFt();
-}
-
-int FlightPlan::Leg::speed() const
-{
- if (_speedRestrict != RESTRICT_NONE) {
- return _speed;
- }
-
- return _waypt->speed();
-}
-
-int FlightPlan::Leg::speedKts() const
-{
- return speed();
-}
-
-double FlightPlan::Leg::speedMach() const
-{
- if (!isMachRestrict(_speedRestrict)) {
- return 0.0;
- }
-
- return -(_speed / 100.0);
-}
-
-RouteRestriction FlightPlan::Leg::altitudeRestriction() const
-{
- if (_altRestrict != RESTRICT_NONE) {
- return _altRestrict;
- }
-
- return _waypt->altitudeRestriction();
-}
-
-RouteRestriction FlightPlan::Leg::speedRestriction() const
-{
- if (_speedRestrict != RESTRICT_NONE) {
- return _speedRestrict;
- }
-
- return _waypt->speedRestriction();
-}
-
-void FlightPlan::Leg::setSpeed(RouteRestriction ty, double speed)
-{
- _speedRestrict = ty;
- if (isMachRestrict(ty)) {
- _speed = (speed * -100);
- } else {
- _speed = speed;
- }
-}
-
-void FlightPlan::Leg::setAltitude(RouteRestriction ty, int altFt)
-{
- _altRestrict = ty;
- _altitudeFt = altFt;
-}
-
-double FlightPlan::Leg::courseDeg() const
-{
- return _courseDeg;
-}
-
-double FlightPlan::Leg::distanceNm() const
-{
- return _pathDistance;
-}
-
-double FlightPlan::Leg::distanceAlongRoute() const
-{
- return _distanceAlongPath;
-}
-
-void FlightPlan::rebuildLegData()
-{
- _totalDistance = 0.0;
- int lastLeg = static_cast<int>(_legs.size()) - 1;
- for (int l=0; l<lastLeg; ++l) {
- Leg* cur = _legs[l];
- Leg* next = _legs[l + 1];
-
- std::pair<double, double> crsDist =
- next->waypoint()->courseAndDistanceFrom(cur->waypoint()->position());
- _legs[l]->_courseDeg = crsDist.first;
- _legs[l]->_pathDistance = crsDist.second * SG_METER_TO_NM;
- _legs[l]->_distanceAlongPath = _totalDistance;
- _totalDistance += crsDist.second * SG_METER_TO_NM;
- } // of legs iteration
-}
-
-void FlightPlan::setDelegate(Delegate* d)
-{
- // wrap any existing delegate(s) in the new one
- d->_inner = _delegate;
- _delegate = d;
-}
-
-void FlightPlan::removeDelegate(Delegate* d)
-{
- if (d == _delegate) {
- _delegate = _delegate->_inner;
- } else if (_delegate) {
- _delegate->removeInner(d);
- }
-}
-
-FlightPlan::Delegate::Delegate() :
- _inner(NULL)
-{
-
-}
-
-FlightPlan::Delegate::~Delegate()
-{
-
-}
-
-void FlightPlan::Delegate::removeInner(Delegate* d)
-{
- if (!_inner) {
- return;
- }
-
- if (_inner == d) {
- // replace with grand-child
- _inner = d->_inner;
- } else { // recurse downwards
- _inner->removeInner(d);
- }
-}
-
-void FlightPlan::Delegate::runDepartureChanged()
-{
- if (_inner) _inner->runDepartureChanged();
- departureChanged();
-}
-
-void FlightPlan::Delegate::runArrivalChanged()
-{
- if (_inner) _inner->runArrivalChanged();
- arrivalChanged();
-}
-
-void FlightPlan::Delegate::runWaypointsChanged()
-{
- if (_inner) _inner->runWaypointsChanged();
- waypointsChanged();
-}
-
-void FlightPlan::Delegate::runCurrentWaypointChanged()
-{
- if (_inner) _inner->runCurrentWaypointChanged();
- currentWaypointChanged();
-}
} // of namespace flightgear