namespace flightgear
{
+
+static void markWaypoints(WayptVec& wps, WayptFlag f)
+{
+ for (unsigned int i=0; i<wps.size(); ++i) {
+ wps[i]->setFlag(f, true);
+ }
+}
Procedure::Procedure(const string& aIdent) :
_ident(aIdent)
{
}
-Approach::Approach(const string& aIdent) :
- Procedure(aIdent)
+Approach::Approach(const string& aIdent, ProcedureType ty) :
+ Procedure(aIdent),
+ _type(ty)
{
}
+
+Approach* Approach::createTempApproach(const std::string& aIdent, FGRunway* aRunway, const WayptVec& aPath)
+{
+ Approach* app = new Approach(aIdent, PROCEDURE_APPROACH_RNAV);
+ app->setRunway(aRunway);
+ app->setPrimaryAndMissed(aPath, WayptVec());
+ return app;
+}
void Approach::setRunway(FGRunwayRef aRwy)
{
_runway = aRwy;
}
+FGAirport* Approach::airport() const
+{
+ return _runway->airport();
+}
+
+RunwayVec Approach::runways() const
+{
+ RunwayVec r;
+ r.push_back(_runway);
+ return r;
+}
+
void Approach::setPrimaryAndMissed(const WayptVec& aPrimary, const WayptVec& aMissed)
{
_primary = aPrimary;
_primary[0]->setFlag(WPT_IAF, true);
_primary[_primary.size()-1]->setFlag(WPT_FAF, true);
+ markWaypoints(_primary, WPT_APPROACH);
_missed = aMissed;
if (!_missed.empty()) {
// mark the first point as the published missed-approach point
_missed[0]->setFlag(WPT_MAP, true);
-
- // mark all the points as being on the missed approach route
- for (unsigned int i=0; i<_missed.size(); ++i) {
- _missed[i]->setFlag(WPT_MISS, true);
- }
+ markWaypoints(_missed, WPT_MISS);
+ markWaypoints(_missed, WPT_APPROACH);
}
}
{
WayptRef entry = aTrans->enroute();
_transitions[entry] = aTrans;
+ aTrans->mark(WPT_APPROACH);
}
bool Approach::route(WayptRef aIAF, WayptVec& aWps)
{
- WptTransitionMap::iterator it;
- bool haveTrans = false;
- for (it = _transitions.begin(); it != _transitions.end(); ++it) {
- Transition* t= it->second;
- if (t->route(aIAF, aWps)) {
- haveTrans = true;
- break;
+ if (aIAF.valid()) {
+ WptTransitionMap::iterator it;
+ bool haveTrans = false;
+ for (it = _transitions.begin(); it != _transitions.end(); ++it) {
+ Transition* t= it->second;
+ if (t->enroute()->matches(aIAF)) {
+ t->route(aWps);
+ haveTrans = true;
+ break;
+ }
+ } // of transitions iteration
+
+ if (!haveTrans) {
+ SG_LOG(SG_GENERAL, SG_INFO, "approach " << ident() << " has no transition " <<
+ "for IAF: " << aIAF->ident());
+ return false;
}
- } // of transitions iteration
-
- if (!haveTrans) {
- SG_LOG(SG_GENERAL, SG_INFO, "approach " << ident() << " has no transition " <<
- "for IAF: " << aIAF->ident());
- return false;
}
- aWps.insert(aWps.end(), _primary.begin(), _primary.end());
- aWps.push_back(new RunwayWaypt(_runway, NULL));
- aWps.insert(aWps.end(), _missed.begin(), _missed.end());
- return true;
+ return routeFromVectors(aWps);
}
bool Approach::routeFromVectors(WayptVec& aWps)
{
aWps.insert(aWps.end(), _primary.begin(), _primary.end());
- aWps.push_back(new RunwayWaypt(_runway, NULL));
+ RunwayWaypt* rwy = new RunwayWaypt(_runway, NULL);
+ rwy->setFlag(WPT_APPROACH);
+ aWps.push_back(rwy);
aWps.insert(aWps.end(), _missed.begin(), _missed.end());
return true;
}
+bool Approach::isApproach(ProcedureType ty)
+{
+ return (ty >= PROCEDURE_APPROACH_ILS) && (ty <= PROCEDURE_APPROACH_RNAV);
+}
+
//////////////////////////////////////////////////////////////////////////////
-ArrivalDeparture::ArrivalDeparture(const string& aIdent) :
- Procedure(aIdent)
+ArrivalDeparture::ArrivalDeparture(const string& aIdent, FGAirport* apt) :
+ Procedure(aIdent),
+ _airport(apt)
{
}
void ArrivalDeparture::addRunway(FGRunwayRef aWay)
{
+ assert(aWay->airport() == _airport);
_runways[aWay] = NULL;
}
-bool ArrivalDeparture::isForRunway(FGRunwayRef aWay) const
+bool ArrivalDeparture::isForRunway(const FGRunway* aWay) const
{
// null runway always passes
if (!aWay) {
return true;
}
- return (_runways.count(aWay));
+ FGRunwayRef r(const_cast<FGRunway*>(aWay));
+ return (_runways.count(r) > 0);
}
+RunwayVec ArrivalDeparture::runways() const
+{
+ RunwayVec r;
+ RunwayTransitionMap::const_iterator it = _runways.begin();
+ for (; it != _runways.end(); ++it) {
+ r.push_back(it->first);
+ }
+
+ return r;
+}
+
void ArrivalDeparture::addTransition(Transition* aTrans)
{
WayptRef entry = aTrans->enroute();
+ aTrans->mark(flagType());
_enrouteTransitions[entry] = aTrans;
}
+string_list ArrivalDeparture::transitionIdents() const
+{
+ string_list r;
+ WptTransitionMap::const_iterator eit;
+ for (eit = _enrouteTransitions.begin(); eit != _enrouteTransitions.end(); ++eit) {
+ r.push_back(eit->second->ident());
+ }
+ return r;
+}
+
void ArrivalDeparture::addRunwayTransition(FGRunwayRef aWay, Transition* aTrans)
{
assert(aWay->ident() == aTrans->ident());
throw sg_io_exception("adding transition for unspecified runway:" + aWay->ident(), ident());
}
+ aTrans->mark(flagType());
_runways[aWay] = aTrans;
}
void ArrivalDeparture::setCommon(const WayptVec& aWps)
{
_common = aWps;
+ markWaypoints(_common, flagType());
}
-bool ArrivalDeparture::commonRoute(Waypt* aEnroute, WayptVec& aPath, FGRunwayRef aRwy)
+bool ArrivalDeparture::commonRoute(Transition* t, WayptVec& aPath, FGRunwayRef aRwy)
{
// assume we're routing from enroute, to the runway.
// for departures, we'll flip the result points
- Transition* t = findTransitionByEnroute(aEnroute);
WayptVec::iterator firstCommon = _common.begin();
if (t) {
- t->route(aEnroute, aPath);
+ t->route(aPath);
Waypt* transEnd = t->procedureEnd();
for (; firstCommon != _common.end(); ++firstCommon) {
// common section after the transition.
firstCommon = _common.begin();
} else {
- if (aEnroute && !(*firstCommon)->matches(aEnroute)) {
- return false;
- }
+ // no tranasition
} // of not using a transition
// append (some) common points
}
SG_LOG(SG_GENERAL, SG_INFO, ident() << " using runway transition for " << r->first->ident());
- r->second->route(NULL, aPath);
+ r->second->route(aPath);
return true;
}
return w;
}
-WayptRef ArrivalDeparture::findTransitionByName(const string& aIdent) const
+Transition* ArrivalDeparture::findTransitionByName(const string& aIdent) const
{
WptTransitionMap::const_iterator eit;
for (eit = _enrouteTransitions.begin(); eit != _enrouteTransitions.end(); ++eit) {
- WayptRef c = eit->second->enroute();
- if (c->ident() == aIdent) {
- return c;
+ if (eit->second->ident() == aIdent) {
+ return eit->second;
}
}
////////////////////////////////////////////////////////////////////////////
-SID::SID(const string& aIdent) :
- ArrivalDeparture(aIdent)
+SID::SID(const string& aIdent, FGAirport* apt) :
+ ArrivalDeparture(aIdent, apt)
{
}
-bool SID::route(FGRunwayRef aWay, Waypt* aEnroute, WayptVec& aPath)
+bool SID::route(FGRunwayRef aWay, Transition* trans, WayptVec& aPath)
{
if (!isForRunway(aWay)) {
SG_LOG(SG_GENERAL, SG_WARN, "SID " << ident() << " not for runway " << aWay->ident());
}
WayptVec path;
- if (!commonRoute(aEnroute, path, aWay)) {
+ if (!commonRoute(trans, path, aWay)) {
return false;
}
return true;
}
+
+SID* SID::createTempSID(const std::string& aIdent, FGRunway* aRunway, const WayptVec& aPath)
+{
+// flip waypoints since SID stores them reversed
+ WayptVec path;
+ std::back_insert_iterator<WayptVec> bi(path);
+ std::reverse_copy(aPath.begin(), aPath.end(), bi);
+
+ SID* sid = new SID(aIdent, aRunway->airport());
+ sid->setCommon(path);
+ sid->addRunway(aRunway);
+ return sid;
+}
////////////////////////////////////////////////////////////////////////////
-STAR::STAR(const string& aIdent) :
- ArrivalDeparture(aIdent)
+STAR::STAR(const string& aIdent, FGAirport* apt) :
+ ArrivalDeparture(aIdent, apt)
{
}
-bool STAR::route(FGRunwayRef aWay, Waypt* aEnroute, WayptVec& aPath)
+bool STAR::route(FGRunwayRef aWay, Transition* trans, WayptVec& aPath)
{
if (aWay && !isForRunway(aWay)) {
return false;
}
- return commonRoute(aEnroute, aPath, aWay);
+ return commonRoute(trans, aPath, aWay);
}
/////////////////////////////////////////////////////////////////////////////
-Transition::Transition(const std::string& aIdent, Procedure* aPr,
- const WayptVec& aWps) :
- _ident(aIdent),
- _parent(aPr),
- _primary(aWps)
+Transition::Transition(const std::string& aIdent, ProcedureType ty, Procedure* aPr) :
+ Procedure(aIdent),
+ _type(ty),
+ _parent(aPr)
{
assert(aPr);
- assert(!_primary.empty());
+}
+void Transition::setPrimary(const WayptVec& aWps)
+{
+ _primary = aWps;
+ assert(!_primary.empty());
_primary[0]->setFlag(WPT_TRANSITION, true);
}
return _primary[_primary.size() - 1];
}
-bool Transition::route(Waypt* aEnroute, WayptVec& aPath)
+bool Transition::route(WayptVec& aPath)
{
- if (aEnroute && !enroute()->matches(aEnroute)) {
- return false;
- }
-
aPath.insert(aPath.end(), _primary.begin(), _primary.end());
return true;
}
+FGAirport* Transition::airport() const
+{
+ return _parent->airport();
+}
+
+void Transition::mark(WayptFlag f)
+{
+ markWaypoints(_primary, f);
+}
+
} // of namespace