1
0
Fork 0
flightgear/src/Navaids/route.hxx

451 lines
11 KiB
C++
Raw Normal View History

/**
* route.hxx - defines basic route and route-element classes. Route elements
* are specialised into waypoints and related things. Routes are any class tha
* owns a collection (list, tree, graph) of route elements - such as airways,
* procedures or a flight plan.
*/
// Written by James Turner, started 2009.
//
// Copyright (C) 2009 Curtis L. Olson
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef FG_ROUTE_HXX
#define FG_ROUTE_HXX
// std
#include <vector>
#include <map>
#include <iosfwd>
// Simgear
#include <simgear/structure/SGReferenced.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/props/props.hxx>
// forward decls
class FGPositioned;
class SGPath;
class FGRunway;
#include <Airports/simple.hxx>
typedef SGSharedPtr<FGAirport> FGAirportRef;
namespace flightgear
{
// forward decls
class RouteBase;
class Waypt;
class NavdataVisitor;
class SID;
class STAR;
class Transition;
typedef SGSharedPtr<Waypt> WayptRef;
typedef enum {
WPT_MAP = 1 << 0, ///< missed approach point
WPT_IAF = 1 << 1, ///< initial approach fix
WPT_FAF = 1 << 2, ///< final approach fix
WPT_OVERFLIGHT = 1 << 3, ///< must overfly the point directly
WPT_TRANSITION = 1 << 4, ///< transition to/from enroute structure
WPT_MISS = 1 << 5, ///< segment is part of missed approach
/// waypoint position is dynamic, i.e moves based on other criteria,
/// such as altitude, inbound course, or so on.
WPT_DYNAMIC = 1 << 6,
/// waypoint was created automatically (not manually entered/loaded)
/// for example waypoints from airway routing or a procedure
WPT_GENERATED = 1 << 7,
WPT_DEPARTURE = 1 << 8,
WPT_ARRIVAL = 1 << 9,
/// waypoint generated by VNAV / speed management profile,
/// for step climbs or top of descent
WPT_PSEUDO = 1 << 10,
WPT_APPROACH = 1 << 11
} WayptFlag;
typedef enum {
RESTRICT_NONE,
RESTRICT_AT,
RESTRICT_ABOVE,
RESTRICT_BELOW,
SPEED_RESTRICT_MACH, ///< encode an 'AT' restriction in Mach, not IAS
RESTRICT_DELETE, ///< ignore underlying restriction (on a leg)
RESTRICT_COMPUTED, ///< data is computed, not a real restriction
SPEED_COMPUTED_MACH ///< variant on above to encode a Mach value
} RouteRestriction;
bool isMachRestrict(RouteRestriction rr);
/**
* Abstract base class for waypoints (and things that are treated similarly
* by navigation systems)
*/
class Waypt : public SGReferenced
{
public:
virtual ~Waypt();
RouteBase* owner() const
{ return _owner; }
/**
* Return true course (in degrees) and distance (in metres) from the provided
* position to this waypoint
*/
virtual std::pair<double, double> courseAndDistanceFrom(const SGGeod& aPos) const;
virtual SGGeod position() const = 0;
/**
* The Positioned associated with this element, if one exists
*/
virtual FGPositioned* source() const
{ return NULL; }
virtual double altitudeFt() const
{ return _altitudeFt; }
virtual double speed() const
{ return _speed; }
// wrapper - asserts if restriction type is _MACH
double speedKts() const;
// wrapper - asserts if restriction type is not _MACH
double speedMach() const;
virtual RouteRestriction altitudeRestriction() const
{ return _altRestrict; }
virtual RouteRestriction speedRestriction() const
{ return _speedRestrict; }
void setAltitude(double aAlt, RouteRestriction aRestrict);
void setSpeed(double aSpeed, RouteRestriction aRestrict);
/**
* Identifier assoicated with the waypoint. Human-readable, but
* possibly quite terse, and definitiely not unique.
*/
virtual std::string ident() const;
/**
* Test if the specified flag is set for this element
*/
virtual bool flag(WayptFlag aFlag) const;
void setFlag(WayptFlag aFlag, bool aV = true);
/**
* Factory method
*/
static WayptRef createFromProperties(RouteBase* aOwner, SGPropertyNode_ptr aProp);
void saveAsNode(SGPropertyNode* node) const;
/**
* Test if this element and another are 'the same', i.e matching
* ident and lat/lon are approximately equal
*/
bool matches(Waypt* aOther) const;
/**
* Test if this element and a position 'the same'
* this can be defined by either position, ident or both
*/
bool matches(const SGGeod& aPos) const;
virtual std::string type() const = 0;
/**
* Magentic variation at/in the vicinity of the waypoint.
* For some waypoint types this will always return 0.
*/
virtual double magvarDeg() const;
/**
* return the assoicated heading or radial for this waypoint.
* The exact meaning varies by type - for a hold it's the inbound radial,
* for a DME intercept it's the heading to hold, and so on.
*/
virtual double headingRadialDeg() const;
protected:
friend class NavdataVisitor;
Waypt(RouteBase* aOwner);
/**
* Persistence helper - read node properties from a file
*/
virtual void initFromProperties(SGPropertyNode_ptr aProp);
/**
* Persistence helper - save this element to a node
*/
virtual void writeToProperties(SGPropertyNode_ptr aProp) const;
typedef Waypt* (FactoryFunction)(RouteBase* aOwner) ;
static void registerFactory(const std::string aNodeType, FactoryFunction* aFactory);
double _altitudeFt;
double _speed; // knots IAS or mach
RouteRestriction _altRestrict;
RouteRestriction _speedRestrict;
private:
/**
* Create an instance of a concrete subclass, or throw an exception
*/
static Waypt* createInstance(RouteBase* aOwner, const std::string& aTypeName);
RouteBase* _owner;
unsigned short _flags;
mutable double _magVarDeg;
};
typedef std::vector<WayptRef> WayptVec;
class RouteBase
{
public:
/**
*
*/
virtual std::string ident() const = 0;
static void loadAirportProcedures(const SGPath& aPath, FGAirport* aApt);
static void dumpRouteToKML(const WayptVec& aRoute, const std::string& aName);
static void dumpRouteToKMLLineString(const std::string& aIdent,
const WayptVec& aRoute, std::ostream& aStream);
private:
};
class FlightPlan : public RouteBase
{
public:
FlightPlan();
virtual ~FlightPlan();
virtual std::string ident() const;
void setIdent(const std::string& s);
FlightPlan* clone(const std::string& newIdent = std::string()) const;
/**
* flight-plan leg encapsulation
*/
class Leg
{
public:
FlightPlan* owner() const
{ return _parent; }
Waypt* waypoint() const
{ return _waypt; }
// reutrn the next leg after this one
Leg* nextLeg() const;
unsigned int index() const;
int altitudeFt() const;
int speed() const;
int speedKts() const;
double speedMach() const;
RouteRestriction altitudeRestriction() const;
RouteRestriction speedRestriction() const;
void setSpeed(RouteRestriction ty, double speed);
void setAltitude(RouteRestriction ty, int altFt);
double courseDeg() const;
double distanceNm() const;
double distanceAlongRoute() const;
private:
friend class FlightPlan;
Leg(FlightPlan* owner, WayptRef wpt);
Leg* cloneFor(FlightPlan* owner) const;
FlightPlan* _parent;
RouteRestriction _speedRestrict, _altRestrict;
int _speed;
int _altitudeFt;
WayptRef _waypt;
/// length of this leg following the flown path
mutable double _pathDistance;
mutable double _courseDeg;
/// total distance of this leg from departure point
mutable double _distanceAlongPath;
};
class Delegate
{
public:
virtual ~Delegate();
virtual void departureChanged() { }
virtual void arrivalChanged() { }
virtual void waypointsChanged() { }
virtual void currentWaypointChanged() { }
protected:
Delegate();
private:
void removeInner(Delegate* d);
void runDepartureChanged();
void runArrivalChanged();
void runWaypointsChanged();
void runCurrentWaypointChanged();
friend class FlightPlan;
Delegate* _inner;
};
Leg* insertWayptAtIndex(Waypt* aWpt, int aIndex);
void insertWayptsAtIndex(const WayptVec& wps, int aIndex);
void deleteIndex(int index);
void clear();
int clearWayptsWithFlag(WayptFlag flag);
int currentIndex() const
{ return _currentIndex; }
void setCurrentIndex(int index);
Leg* currentLeg() const;
Leg* nextLeg() const;
Leg* previousLeg() const;
int numLegs() const
{ return _legs.size(); }
Leg* legAtIndex(int index) const;
int findLegIndex(const Leg* l) const;
int findWayptIndex(const SGGeod& aPos) const;
bool load(const SGPath& p);
bool save(const SGPath& p);
FGAirportRef departureAirport() const
{ return _departure; }
FGAirportRef destinationAirport() const
{ return _destination; }
FGRunway* departureRunway() const
{ return _departureRunway; }
FGRunway* destinationRunway() const
{ return _destinationRunway; }
Approach* approach() const
{ return _approach; }
void setDeparture(FGAirport* apt);
void setDeparture(FGRunway* rwy);
SID* sid() const
{ return _sid; }
Transition* sidTransition() const;
void setSID(SID* sid, const std::string& transition = std::string());
void setSID(Transition* sidWithTrans);
void setDestination(FGAirport* apt);
void setDestination(FGRunway* rwy);
/**
* note setting an approach will implicitly update the destination
* airport and runway to match
*/
void setApproach(Approach* app);
STAR* star() const
{ return _star; }
Transition* starTransition() const;
void setSTAR(STAR* star, const std::string& transition = std::string());
void setSTAR(Transition* starWithTrans);
double totalDistanceNm() const
{ return _totalDistance; }
/**
* Create a WayPoint from a string in the following format:
* - simple identifier
* - decimal-lon,decimal-lat
* - airport-id/runway-id
* - navaid/radial-deg/offset-nm
*/
WayptRef waypointFromString(const std::string& target);
void setDelegate(Delegate* d);
void removeDelegate(Delegate* d);
private:
bool loadPlainTextRoute(const SGPath& path);
void loadVersion1XMLRoute(SGPropertyNode_ptr routeData);
void loadVersion2XMLRoute(SGPropertyNode_ptr routeData);
void loadXMLRouteHeader(SGPropertyNode_ptr routeData);
WayptRef parseVersion1XMLWaypt(SGPropertyNode* aWP);
double magvarDegAt(const SGGeod& pos) const;
std::string _ident;
int _currentIndex;
FGAirportRef _departure, _destination;
FGRunway* _departureRunway, *_destinationRunway;
SID* _sid;
STAR* _star;
Approach* _approach;
std::string _sidTransition, _starTransition;
double _totalDistance;
void rebuildLegData();
typedef std::vector<Leg*> LegVec;
LegVec _legs;
Delegate* _delegate;
};
} // of namespace flightgear
#endif // of FG_ROUTE_HXX