Durk reminded me of this - when we're missing procedures data (the common case), synthesise a plausible (but possibly dangerously unrealistic) departure and approach. Will work fine for airports in gentle terrain, and likely kill you at challenging airports. You have been warned.
mutable PositionedIDVec mTaxiways;
PositionedIDVec mPavements;
- std::vector<flightgear::SID*> mSIDs;
- std::vector<flightgear::STAR*> mSTARs;
- std::vector<flightgear::Approach*> mApproaches;
+ typedef SGSharedPtr<flightgear::SID> SIDRef;
+ typedef SGSharedPtr<flightgear::STAR> STARRef;
+ typedef SGSharedPtr<flightgear::Approach> ApproachRef;
+
+ std::vector<SIDRef> mSIDs;
+ std::vector<STARRef> mSTARs;
+ std::vector<ApproachRef> mApproaches;
};
// find basic airport location info from airport database
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/tuple/tuple.hpp>
+#include <boost/foreach.hpp>
#include <simgear/misc/strutils.hxx>
#include <simgear/structure/exception.hxx>
return "";
}
+flightgear::SID* createDefaultSID(FGRunway* aRunway)
+{
+ if (!aRunway) {
+ return NULL;
+ }
+
+ double runwayElevFt = aRunway->end().getElevationFt();
+ WayptVec wpts;
+ std::ostringstream ss;
+ ss << aRunway->ident() << "-3";
+
+ SGGeod p = aRunway->pointOnCenterline(aRunway->lengthM() + (3.0 * SG_NM_TO_METER));
+ p.setElevationFt(runwayElevFt + 2000.0);
+ wpts.push_back(new BasicWaypt(p, ss.str(), NULL));
+
+ ss.str("");
+ ss << aRunway->ident() << "-6";
+ p = aRunway->pointOnCenterline(aRunway->lengthM() + (6.0 * SG_NM_TO_METER));
+ p.setElevationFt(runwayElevFt + 4000.0);
+ wpts.push_back(new BasicWaypt(p, ss.str(), NULL));
+
+ ss.str("");
+ ss << aRunway->ident() << "-9";
+ p = aRunway->pointOnCenterline(aRunway->lengthM() + (9.0 * SG_NM_TO_METER));
+ p.setElevationFt(runwayElevFt + 6000.0);
+ wpts.push_back(new BasicWaypt(p, ss.str(), NULL));
+
+ BOOST_FOREACH(Waypt* w, wpts) {
+ w->setFlag(WPT_DEPARTURE);
+ w->setFlag(WPT_GENERATED);
+ }
+
+ return SID::createTempSID("DEFAULT", aRunway, wpts);
+}
+
void FGRouteMgr::setSID(const char* aIdent)
{
FGAirport* apt = _plan->departureAirport();
return;
}
+ if (!strcmp(aIdent, "DEFAULT")) {
+ _plan->setSID(createDefaultSID(_plan->departureRunway()));
+ return;
+ }
+
string ident(aIdent);
size_t hyphenPos = ident.find('-');
if (hyphenPos != string::npos) {
return "";
}
+flightgear::Approach* createDefaultApproach(FGRunway* aRunway)
+{
+ if (!aRunway) {
+ return NULL;
+ }
+
+ double thresholdElevFt = aRunway->threshold().getElevationFt();
+ const double approachHeightFt = 2000.0;
+ double glideslopeDistanceM = (approachHeightFt * SG_FEET_TO_METER) /
+ tan(3.0 * SG_DEGREES_TO_RADIANS);
+
+ std::ostringstream ss;
+ ss << aRunway->ident() << "-12";
+ WayptVec wpts;
+ SGGeod p = aRunway->pointOnCenterline(-12.0 * SG_NM_TO_METER);
+ p.setElevationFt(thresholdElevFt + 4000);
+ wpts.push_back(new BasicWaypt(p, ss.str(), NULL));
+
+
+ p = aRunway->pointOnCenterline(-8.0 * SG_NM_TO_METER);
+ p.setElevationFt(thresholdElevFt + approachHeightFt);
+ ss.str("");
+ ss << aRunway->ident() << "-8";
+ wpts.push_back(new BasicWaypt(p, ss.str(), NULL));
+
+ p = aRunway->pointOnCenterline(-glideslopeDistanceM);
+ p.setElevationFt(thresholdElevFt + approachHeightFt);
+
+ ss.str("");
+ ss << aRunway->ident() << "-GS";
+ wpts.push_back(new BasicWaypt(p, ss.str(), NULL));
+
+ wpts.push_back(new RunwayWaypt(aRunway, NULL));
+
+ BOOST_FOREACH(Waypt* w, wpts) {
+ w->setFlag(WPT_APPROACH);
+ w->setFlag(WPT_GENERATED);
+ }
+
+ return Approach::createTempApproach("DEFAULT", aRunway, wpts);
+}
+
void FGRouteMgr::setApproach(const char* aIdent)
{
FGAirport* apt = _plan->destinationAirport();
+ if (!strcmp(aIdent, "DEFAULT")) {
+ _plan->setApproach(createDefaultApproach(_plan->destinationRunway()));
+ return;
+ }
+
if (!apt || (aIdent == NULL)) {
_plan->setApproach(NULL);
} else {
FGAirportRef _departure, _destination;
FGRunway* _departureRunway, *_destinationRunway;
- SID* _sid;
- STAR* _star;
- Approach* _approach;
+ SGSharedPtr<SID> _sid;
+ SGSharedPtr<STAR> _star;
+ SGSharedPtr<Approach> _approach;
std::string _sidTransition, _starTransition;
double _totalDistance;
class AdjacentWaypoint;
class InAirwayFilter;
-class Airway : public RouteBase
+class Airway
{
public:
virtual std::string ident() const
{
}
+
+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)
{
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;
+}
////////////////////////////////////////////////////////////////////////////
class Transition : public Procedure
{
public:
+ virtual ~Transition() { ; }
+
bool route(WayptVec& aPath);
Procedure* parent() const
WayptVec _primary;
};
+typedef SGSharedPtr<Transition> TransitionRef;
+
/**
* Describe an approach procedure, including the missed approach
* segment
class Approach : public Procedure
{
public:
+ virtual ~Approach() { ; }
+
FGRunwayRef runway()
{ return _runway; }
virtual ProcedureType type() const
{ return _type; }
+
+ static Approach* createTempApproach(const std::string& aIdent, FGRunway* aRunway, const WayptVec& aPath);
private:
friend class NavdataVisitor;
FGRunwayRef _runway;
ProcedureType _type;
- typedef std::map<WayptRef, Transition*> WptTransitionMap;
+ typedef std::map<WayptRef, TransitionRef> WptTransitionMap;
WptTransitionMap _transitions;
WayptVec _primary; // unify these?
ArrivalDeparture(const std::string& aIdent, FGAirport* apt);
-
void addRunway(FGRunwayRef aRwy);
- typedef std::map<FGRunwayRef, Transition*> RunwayTransitionMap;
+ typedef std::map<FGRunwayRef, TransitionRef> RunwayTransitionMap;
RunwayTransitionMap _runways;
virtual WayptFlag flagType() const = 0;
+
+ void setCommon(const WayptVec& aWps);
+
private:
friend class NavdataVisitor;
void addTransition(Transition* aTrans);
- void setCommon(const WayptVec& aWps);
-
void addRunwayTransition(FGRunwayRef aRwy, Transition* aTrans);
FGAirport* _airport;
WayptVec _common;
- typedef std::map<WayptRef, Transition*> WptTransitionMap;
+ typedef std::map<WayptRef, TransitionRef> WptTransitionMap;
WptTransitionMap _enrouteTransitions;
class SID : public ArrivalDeparture
{
-public:
+public:
+ virtual ~SID() { ; }
+
virtual bool route(FGRunwayRef aWay, Transition* aTrans, WayptVec& aPath);
virtual ProcedureType type() const
{ return PROCEDURE_SID; }
+ static SID* createTempSID(const std::string& aIdent, FGRunway* aRunway, const WayptVec& aPath);
protected:
virtual WayptFlag flagType() const
{ return WPT_DEPARTURE; }
class STAR : public ArrivalDeparture
{
-public:
+public:
+ virtual ~STAR() { ; }
+
virtual bool route(FGRunwayRef aWay, Transition* aTrans, WayptVec& aPath);
virtual ProcedureType type() const
typedef std::vector<WayptRef> WayptVec;
-class RouteBase
+class RouteBase : public SGReferenced
{
public:
/**