Create a real FlightPlan (and Leg) class
Convert the route-manager to use a flight-plan internally, and expose flightplan, leg and procedure data to Nasal. Move the Level-D parser into its own file.
This commit is contained in:
parent
563ed19f97
commit
1b7b69b498
24 changed files with 3111 additions and 1666 deletions
|
@ -172,7 +172,7 @@ void FGRunway::setReciprocalRunway(FGRunway* other)
|
|||
_reciprocal = other;
|
||||
}
|
||||
|
||||
std::vector<flightgear::SID*> FGRunway::getSIDs()
|
||||
std::vector<flightgear::SID*> FGRunway::getSIDs() const
|
||||
{
|
||||
std::vector<flightgear::SID*> result;
|
||||
for (unsigned int i=0; i<_airport->numSIDs(); ++i) {
|
||||
|
@ -185,7 +185,7 @@ std::vector<flightgear::SID*> FGRunway::getSIDs()
|
|||
return result;
|
||||
}
|
||||
|
||||
std::vector<flightgear::STAR*> FGRunway::getSTARs()
|
||||
std::vector<flightgear::STAR*> FGRunway::getSTARs() const
|
||||
{
|
||||
std::vector<flightgear::STAR*> result;
|
||||
for (unsigned int i=0; i<_airport->numSTARs(); ++i) {
|
||||
|
@ -198,3 +198,16 @@ std::vector<flightgear::STAR*> FGRunway::getSTARs()
|
|||
return result;
|
||||
}
|
||||
|
||||
std::vector<flightgear::Approach*> FGRunway::getApproaches() const
|
||||
{
|
||||
std::vector<flightgear::Approach*> result;
|
||||
for (unsigned int i=0; i<_airport->numApproaches(); ++i) {
|
||||
flightgear::Approach* s = _airport->getApproachByIndex(i);
|
||||
if (s->runway() == this) {
|
||||
result.push_back(s);
|
||||
}
|
||||
} // of approaches at the airport iteration
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ class SGPropertyNode;
|
|||
namespace flightgear {
|
||||
class SID;
|
||||
class STAR;
|
||||
class Approach;
|
||||
}
|
||||
|
||||
class FGRunway : public FGRunwayBase
|
||||
|
@ -124,12 +125,15 @@ public:
|
|||
/**
|
||||
* Get SIDs (DPs) associated with this runway
|
||||
*/
|
||||
std::vector<flightgear::SID*> getSIDs();
|
||||
std::vector<flightgear::SID*> getSIDs() const;
|
||||
|
||||
/**
|
||||
* Get STARs associared with this runway
|
||||
*/
|
||||
std::vector<flightgear::STAR*> getSTARs();
|
||||
std::vector<flightgear::STAR*> getSTARs() const;
|
||||
|
||||
|
||||
std::vector<flightgear::Approach*> getApproaches() const;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -406,7 +406,7 @@ void FGAirport::loadProcedures() const
|
|||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, ident() << ": loading procedures from " << path.str());
|
||||
Route::loadAirportProcedures(path, const_cast<FGAirport*>(this));
|
||||
RouteBase::loadAirportProcedures(path, const_cast<FGAirport*>(this));
|
||||
}
|
||||
|
||||
void FGAirport::loadSceneryDefinitions() const
|
||||
|
@ -469,128 +469,6 @@ void FGAirport::readTowerData(SGPropertyNode* aRoot)
|
|||
_tower_location = SGGeod::fromDegM(lon, lat, fieldElevationM + elevM);
|
||||
}
|
||||
|
||||
bool FGAirport::buildApproach(Waypt* aEnroute, STAR* aSTAR, FGRunway* aRwy, WayptVec& aRoute)
|
||||
{
|
||||
loadProcedures();
|
||||
|
||||
if ((aRwy && (aRwy->airport() != this))) {
|
||||
throw sg_exception("invalid parameters", "FGAirport::buildApproach");
|
||||
}
|
||||
|
||||
if (aSTAR) {
|
||||
bool ok = aSTAR->route(aRwy, aEnroute, aRoute);
|
||||
if (!ok) {
|
||||
SG_LOG(SG_GENERAL, SG_WARN, ident() << ": build approach, STAR " << aSTAR->ident()
|
||||
<< " failed to route from transition " << aEnroute->ident());
|
||||
return false;
|
||||
}
|
||||
} else if (aEnroute) {
|
||||
// no a STAR specified, just use enroute point directly
|
||||
aRoute.push_back(aEnroute);
|
||||
}
|
||||
|
||||
if (!aRwy) {
|
||||
// no runway selected yet, but we loaded the STAR, so that's fine, we're done
|
||||
return true;
|
||||
}
|
||||
|
||||
// build the approach (possibly including transition), and including the missed segment
|
||||
vector<Approach*> aps;
|
||||
for (unsigned int j=0; j<mApproaches.size();++j) {
|
||||
if (mApproaches[j]->runway() == aRwy) {
|
||||
aps.push_back(mApproaches[j]);
|
||||
}
|
||||
} // of approach filter by runway
|
||||
|
||||
if (aps.empty()) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, ident() << "; no approaches defined for runway " << aRwy->ident());
|
||||
// could build a fallback approach here
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned int k=0; k<aps.size(); ++k) {
|
||||
if (aps[k]->route(aRoute.back(), aRoute)) {
|
||||
return true;
|
||||
}
|
||||
} // of initial approach iteration
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, ident() << ": unable to find transition to runway "
|
||||
<< aRwy->ident() << ", assume vectors");
|
||||
|
||||
WayptRef v(new ATCVectors(NULL, this));
|
||||
aRoute.push_back(v);
|
||||
return aps.front()->routeFromVectors(aRoute);
|
||||
}
|
||||
|
||||
pair<flightgear::SID*, WayptRef>
|
||||
FGAirport::selectSID(const SGGeod& aDest, FGRunway* aRwy)
|
||||
{
|
||||
loadProcedures();
|
||||
|
||||
WayptRef enroute;
|
||||
flightgear::SID* sid = NULL;
|
||||
double d = 1e9;
|
||||
|
||||
for (unsigned int i=0; i<mSIDs.size(); ++i) {
|
||||
if (aRwy && !mSIDs[i]->isForRunway(aRwy)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WayptRef e = mSIDs[i]->findBestTransition(aDest);
|
||||
if (!e) {
|
||||
continue; // strange, but let's not worry about it
|
||||
}
|
||||
|
||||
// assert(e->isFixedPosition());
|
||||
double ed = SGGeodesy::distanceM(aDest, e->position());
|
||||
if (ed < d) { // new best match
|
||||
enroute = e;
|
||||
d = ed;
|
||||
sid = mSIDs[i];
|
||||
}
|
||||
} // of SID iteration
|
||||
|
||||
if (!mSIDs.empty() && !sid) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, ident() << "selectSID, no SID found (runway="
|
||||
<< (aRwy ? aRwy->ident() : "no runway preference"));
|
||||
}
|
||||
|
||||
return std::make_pair(sid, enroute);
|
||||
}
|
||||
|
||||
pair<STAR*, WayptRef>
|
||||
FGAirport::selectSTAR(const SGGeod& aOrigin, FGRunway* aRwy)
|
||||
{
|
||||
loadProcedures();
|
||||
|
||||
WayptRef enroute;
|
||||
STAR* star = NULL;
|
||||
double d = 1e9;
|
||||
|
||||
for (unsigned int i=0; i<mSTARs.size(); ++i) {
|
||||
if (!mSTARs[i]->isForRunway(aRwy)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "STAR " << mSTARs[i]->ident() << " is valid for runway");
|
||||
WayptRef e = mSTARs[i]->findBestTransition(aOrigin);
|
||||
if (!e) {
|
||||
continue; // strange, but let's not worry about it
|
||||
}
|
||||
|
||||
// assert(e->isFixedPosition());
|
||||
double ed = SGGeodesy::distanceM(aOrigin, e->position());
|
||||
if (ed < d) { // new best match
|
||||
enroute = e;
|
||||
d = ed;
|
||||
star = mSTARs[i];
|
||||
}
|
||||
} // of STAR iteration
|
||||
|
||||
return std::make_pair(star, enroute);
|
||||
}
|
||||
|
||||
|
||||
void FGAirport::addSID(flightgear::SID* aSid)
|
||||
{
|
||||
mSIDs.push_back(aSid);
|
||||
|
@ -666,6 +544,18 @@ Approach* FGAirport::getApproachByIndex(unsigned int aIndex) const
|
|||
return mApproaches[aIndex];
|
||||
}
|
||||
|
||||
Approach* FGAirport::findApproachWithIdent(const std::string& aIdent) const
|
||||
{
|
||||
loadProcedures();
|
||||
for (unsigned int i=0; i<mApproaches.size(); ++i) {
|
||||
if (mApproaches[i]->ident() == aIdent) {
|
||||
return mApproaches[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FGAirport::setCommStations(CommStationList& comms)
|
||||
{
|
||||
mCommStations.swap(comms);
|
||||
|
|
|
@ -188,7 +188,8 @@ public:
|
|||
|
||||
unsigned int numApproaches() const;
|
||||
flightgear::Approach* getApproachByIndex(unsigned int aIndex) const;
|
||||
|
||||
flightgear::Approach* findApproachWithIdent(const std::string& aIdent) const;
|
||||
|
||||
/**
|
||||
* Syntactic wrapper around FGPositioned::findClosest - find the closest
|
||||
* match for filter, and return it cast to FGAirport. The default filter
|
||||
|
@ -216,22 +217,6 @@ public:
|
|||
*/
|
||||
static char** searchNamesAndIdents(const std::string& aFilter);
|
||||
|
||||
bool buildApproach(flightgear::Waypt* aEnroute, flightgear::STAR* aSTAR,
|
||||
FGRunway* aRwy, flightgear::WayptVec& aRoute);
|
||||
|
||||
/**
|
||||
* Given a destiation point, select the best SID and transition waypt from
|
||||
* this airport. Returns (NULL,NULL) is no SIDs are defined, otherwise the
|
||||
* best SID/transition is that which is closest to the destination point.
|
||||
*/
|
||||
std::pair<flightgear::SID*, flightgear::WayptRef> selectSID(const SGGeod& aDest, FGRunway* aRwy);
|
||||
|
||||
/**
|
||||
* Select a STAR and enroute transition waypt, given an origin (departure) position.
|
||||
* returns (NULL, NULL) is no suitable STAR is exists
|
||||
*/
|
||||
std::pair<flightgear::STAR*, flightgear::WayptRef> selectSTAR(const SGGeod& aOrigin, FGRunway* aRwy);
|
||||
|
||||
void setCommStations(flightgear::CommStationList& comms);
|
||||
|
||||
flightgear::CommStationList commStationsOfType(FGPositioned::Type aTy) const;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -44,7 +44,8 @@ typedef SGSharedPtr<FGAirport> FGAirportRef;
|
|||
*
|
||||
*/
|
||||
|
||||
class FGRouteMgr : public SGSubsystem
|
||||
class FGRouteMgr : public SGSubsystem,
|
||||
public flightgear::FlightPlan::Delegate
|
||||
{
|
||||
public:
|
||||
FGRouteMgr();
|
||||
|
@ -55,11 +56,6 @@ public:
|
|||
void bind ();
|
||||
void unbind ();
|
||||
void update (double dt);
|
||||
|
||||
void insertWayptAtIndex(flightgear::Waypt* aWpt, int aIndex);
|
||||
flightgear::WayptRef removeWayptAtIndex(int index);
|
||||
|
||||
void clearRoute();
|
||||
|
||||
typedef enum {
|
||||
ROUTE_HIGH_AIRWAYS, ///< high-level airways routing
|
||||
|
@ -74,34 +70,31 @@ public:
|
|||
* used as the final waypoint.
|
||||
*/
|
||||
bool routeToIndex(int index, RouteType aRouteType);
|
||||
|
||||
void autoRoute();
|
||||
|
||||
bool isRouteActive() const;
|
||||
|
||||
int currentIndex() const
|
||||
{ return _currentIndex; }
|
||||
|
||||
int currentIndex() const;
|
||||
|
||||
void setFlightPlan(flightgear::FlightPlan* plan);
|
||||
flightgear::FlightPlan* flightPlan() const;
|
||||
|
||||
void clearRoute();
|
||||
|
||||
flightgear::Waypt* currentWaypt() const;
|
||||
flightgear::Waypt* nextWaypt() const;
|
||||
flightgear::Waypt* previousWaypt() const;
|
||||
|
||||
const flightgear::WayptVec& waypts() const
|
||||
{ return _route; }
|
||||
int numLegs() const;
|
||||
|
||||
// deprecated
|
||||
int numWaypts() const
|
||||
{ return _route.size(); }
|
||||
|
||||
{ return numLegs(); }
|
||||
|
||||
// deprecated
|
||||
flightgear::Waypt* wayptAtIndex(int index) const;
|
||||
|
||||
|
||||
SGPropertyNode_ptr wayptNodeAtIndex(int index) const;
|
||||
|
||||
/**
|
||||
* Find a waypoint in the route, by position, and return its index, or
|
||||
* -1 if no matching waypoint was found in the route.
|
||||
*/
|
||||
int findWayptIndex(const SGGeod& aPos) const;
|
||||
|
||||
|
||||
void removeLegAtIndex(int aIndex);
|
||||
|
||||
/**
|
||||
* Activate a built route. This checks for various mandatory pieces of
|
||||
* data, such as departure and destination airports, and creates waypoints
|
||||
|
@ -125,38 +118,20 @@ public:
|
|||
bool saveRoute(const SGPath& p);
|
||||
bool loadRoute(const SGPath& p);
|
||||
|
||||
flightgear::WayptRef waypointFromString(const std::string& target);
|
||||
|
||||
/**
|
||||
* Helper command to setup current airport/runway if necessary
|
||||
*/
|
||||
void initAtPosition();
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
flightgear::WayptRef waypointFromString(const std::string& target);
|
||||
|
||||
FGAirportRef departureAirport() const;
|
||||
FGAirportRef destinationAirport() const;
|
||||
|
||||
FGRunway* departureRunway() const;
|
||||
FGRunway* destinationRunway() const;
|
||||
|
||||
private:
|
||||
flightgear::WayptVec _route;
|
||||
int _currentIndex;
|
||||
flightgear::FlightPlan* _plan;
|
||||
|
||||
time_t _takeoffTime;
|
||||
time_t _touchdownTime;
|
||||
FGAirportRef _departure;
|
||||
FGAirportRef _destination;
|
||||
|
||||
|
||||
// automatic inputs
|
||||
SGPropertyNode_ptr lon;
|
||||
SGPropertyNode_ptr lat;
|
||||
SGPropertyNode_ptr alt;
|
||||
SGPropertyNode_ptr magvar;
|
||||
|
||||
// automatic outputs
|
||||
|
@ -215,11 +190,11 @@ private:
|
|||
|
||||
InputListener *listener;
|
||||
SGPropertyNode_ptr mirror;
|
||||
|
||||
void departureChanged();
|
||||
|
||||
virtual void departureChanged();
|
||||
void buildDeparture(flightgear::WayptRef enroute, flightgear::WayptVec& wps);
|
||||
|
||||
void arrivalChanged();
|
||||
virtual void arrivalChanged();
|
||||
void buildArrival(flightgear::WayptRef enroute, flightgear::WayptVec& wps);
|
||||
|
||||
/**
|
||||
|
@ -227,16 +202,11 @@ private:
|
|||
* modified (waypoints added, inserted, removed). Notably, this fires the
|
||||
* 'edited' signal.
|
||||
*/
|
||||
void waypointsChanged();
|
||||
virtual void waypointsChanged();
|
||||
|
||||
void update_mirror();
|
||||
|
||||
void currentWaypointChanged();
|
||||
|
||||
/**
|
||||
* Parse a route/wp node (from a saved, property-lsit formatted route)
|
||||
*/
|
||||
void parseRouteWaypoint(SGPropertyNode* aWP);
|
||||
virtual void currentWaypointChanged();
|
||||
|
||||
/**
|
||||
* Check if we've reached the final waypoint.
|
||||
|
@ -244,14 +214,6 @@ private:
|
|||
*/
|
||||
bool checkFinished();
|
||||
|
||||
|
||||
bool loadPlainTextRoute(const SGPath& path);
|
||||
|
||||
void loadVersion1XMLRoute(SGPropertyNode_ptr routeData);
|
||||
void loadVersion2XMLRoute(SGPropertyNode_ptr routeData);
|
||||
void loadXMLRouteHeader(SGPropertyNode_ptr routeData);
|
||||
flightgear::WayptRef parseVersion1XMLWaypt(SGPropertyNode* aWP);
|
||||
|
||||
/**
|
||||
* Predicate for helping the UI - test if at least one waypoint was
|
||||
* entered by the user (as opposed to being generated by the route-manager)
|
||||
|
@ -263,12 +225,27 @@ private:
|
|||
const char* getDepartureName() const;
|
||||
void setDepartureICAO(const char* aIdent);
|
||||
|
||||
const char* getDepartureRunway() const;
|
||||
void setDepartureRunway(const char* aIdent);
|
||||
|
||||
const char* getSID() const;
|
||||
void setSID(const char* aIdent);
|
||||
|
||||
const char* getDestinationICAO() const;
|
||||
const char* getDestinationName() const;
|
||||
void setDestinationICAO(const char* aIdent);
|
||||
|
||||
PropertyWatcher* _departureWatcher;
|
||||
PropertyWatcher* _arrivalWatcher;
|
||||
const char* getDestinationRunway() const;
|
||||
void setDestinationRunway(const char* aIdent);
|
||||
|
||||
const char* getApproach() const;
|
||||
void setApproach(const char* aIdent);
|
||||
|
||||
const char* getSTAR() const;
|
||||
void setSTAR(const char* aIdent);
|
||||
|
||||
double getDepartureFieldElevation() const;
|
||||
double getDestinationFieldElevation() const;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -682,7 +682,7 @@ void MapWidget::paintRoute()
|
|||
return;
|
||||
}
|
||||
|
||||
RoutePath path(_route->waypts());
|
||||
RoutePath path(_route->flightPlan());
|
||||
|
||||
// first pass, draw the actual lines
|
||||
glLineWidth(2.0);
|
||||
|
|
|
@ -37,20 +37,19 @@ enum {
|
|||
static const double BLINK_TIME = 0.3;
|
||||
static const int DRAG_START_DISTANCE_PX = 5;
|
||||
|
||||
class RouteManagerWaypointModel :
|
||||
class FlightPlanWaypointModel :
|
||||
public WaypointList::Model,
|
||||
public SGPropertyChangeListener
|
||||
{
|
||||
public:
|
||||
RouteManagerWaypointModel()
|
||||
{
|
||||
_rm = static_cast<FGRouteMgr*>(globals->get_subsystem("route-manager"));
|
||||
|
||||
FlightPlanWaypointModel(flightgear::FlightPlan* fp) :
|
||||
_fp(fp)
|
||||
{
|
||||
SGPropertyNode* routeEdited = fgGetNode("/autopilot/route-manager/signals/edited", true);
|
||||
routeEdited->addChangeListener(this);
|
||||
}
|
||||
|
||||
virtual ~RouteManagerWaypointModel()
|
||||
~FlightPlanWaypointModel()
|
||||
{
|
||||
SGPropertyNode* routeEdited = fgGetNode("/autopilot/route-manager/signals/edited", true);
|
||||
routeEdited->removeChangeListener(this);
|
||||
|
@ -59,12 +58,12 @@ public:
|
|||
// implement WaypointList::Model
|
||||
virtual unsigned int numWaypoints() const
|
||||
{
|
||||
return _rm->numWaypts();
|
||||
return _fp->numLegs();
|
||||
}
|
||||
|
||||
virtual int currentWaypoint() const
|
||||
{
|
||||
return _rm->currentIndex();
|
||||
return _fp->currentIndex();
|
||||
}
|
||||
|
||||
virtual flightgear::Waypt* waypointAt(unsigned int index) const
|
||||
|
@ -73,12 +72,12 @@ public:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return _rm->wayptAtIndex(index);
|
||||
return _fp->legAtIndex(index)->waypoint();
|
||||
}
|
||||
|
||||
virtual void deleteAt(unsigned int index)
|
||||
{
|
||||
_rm->removeWayptAtIndex(index);
|
||||
_fp->deleteIndex(index);
|
||||
}
|
||||
|
||||
virtual void moveWaypointToIndex(unsigned int srcIndex, unsigned int destIndex)
|
||||
|
@ -89,13 +88,15 @@ public:
|
|||
}
|
||||
|
||||
unsigned int currentWpIndex = currentWaypoint();
|
||||
WayptRef w(_rm->removeWayptAtIndex(srcIndex));
|
||||
WayptRef w(waypointAt(currentWpIndex));
|
||||
_fp->deleteIndex(currentWpIndex);
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "wpt:" << w->ident());
|
||||
_rm->insertWayptAtIndex(w, destIndex);
|
||||
_fp->insertWayptAtIndex(w, destIndex);
|
||||
|
||||
if (srcIndex == currentWpIndex) {
|
||||
// current waypoint was moved
|
||||
_rm->jumpToIndex(destIndex);
|
||||
_fp->setCurrentIndex(destIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,7 +113,7 @@ public:
|
|||
}
|
||||
}
|
||||
private:
|
||||
FGRouteMgr* _rm;
|
||||
flightgear::FlightPlan* _fp;
|
||||
SGCallback* _cb;
|
||||
};
|
||||
|
||||
|
@ -152,7 +153,9 @@ WaypointList::WaypointList(int x, int y, int width, int height) :
|
|||
{
|
||||
// pretend to be a list, so fgPopup doesn't mess with our mouse events
|
||||
type |= PUCLASS_LIST;
|
||||
setModel(new RouteManagerWaypointModel());
|
||||
flightgear::FlightPlan* fp =
|
||||
static_cast<FGRouteMgr*>(globals->get_subsystem("route-manager"))->flightPlan();
|
||||
setModel(new FlightPlanWaypointModel(fp));
|
||||
setSize(width, height);
|
||||
setValue(-1);
|
||||
|
||||
|
|
|
@ -159,7 +159,6 @@ public:
|
|||
virtual void valueChanged (SGPropertyNode * prop)
|
||||
{
|
||||
_nd->invalidatePositionedCache();
|
||||
SG_LOG(SG_INSTR, SG_INFO, "invalidating NavDisplay cache");
|
||||
}
|
||||
private:
|
||||
NavDisplay* _nd;
|
||||
|
@ -174,7 +173,6 @@ public:
|
|||
|
||||
virtual void valueChanged (SGPropertyNode * prop)
|
||||
{
|
||||
SG_LOG(SG_INSTR, SG_INFO, "forcing NavDisplay update");
|
||||
_nd->forceUpdate();
|
||||
}
|
||||
private:
|
||||
|
@ -683,9 +681,6 @@ NavDisplay::update (double delta_time_sec)
|
|||
SGVec3d cartNow(SGVec3d::fromGeod(_pos));
|
||||
double movedNm = dist(_cachedPos, cartNow) * SG_METER_TO_NM;
|
||||
_cachedItemsValid = (movedNm < 1.0);
|
||||
if (!_cachedItemsValid) {
|
||||
SG_LOG(SG_INSTR, SG_INFO, "invalidating NavDisplay cache due to moving: " << movedNm);
|
||||
}
|
||||
}
|
||||
|
||||
_vertices->clear();
|
||||
|
@ -951,7 +946,6 @@ public:
|
|||
void NavDisplay::findItems()
|
||||
{
|
||||
if (!_cachedItemsValid) {
|
||||
SG_LOG(SG_INSTR, SG_INFO, "re-validating NavDisplay cache");
|
||||
Filter filt;
|
||||
filt.minRunwayLengthFt = 2000;
|
||||
_itemsInRange = FGPositioned::findWithinRange(_pos, _rangeNm, &filt);
|
||||
|
@ -967,29 +961,31 @@ void NavDisplay::findItems()
|
|||
void NavDisplay::processRoute()
|
||||
{
|
||||
_routeSources.clear();
|
||||
RoutePath path(_route->waypts());
|
||||
flightgear::FlightPlan* fp = _route->flightPlan();
|
||||
RoutePath path(fp);
|
||||
int current = _route->currentIndex();
|
||||
|
||||
for (int w=0; w<_route->numWaypts(); ++w) {
|
||||
flightgear::WayptRef wpt(_route->wayptAtIndex(w));
|
||||
for (int l=0; l<fp->numLegs(); ++l) {
|
||||
flightgear::FlightPlan::Leg* leg = fp->legAtIndex(l);
|
||||
flightgear::WayptRef wpt(leg->waypoint());
|
||||
_routeSources.insert(wpt->source());
|
||||
|
||||
string_set state;
|
||||
state.insert("on-active-route");
|
||||
|
||||
if (w < current) {
|
||||
if (l < current) {
|
||||
state.insert("passed");
|
||||
}
|
||||
|
||||
if (w == current) {
|
||||
if (l == current) {
|
||||
state.insert("current-wp");
|
||||
}
|
||||
|
||||
if (w > current) {
|
||||
if (l > current) {
|
||||
state.insert("future");
|
||||
}
|
||||
|
||||
if (w == (current + 1)) {
|
||||
if (l == (current + 1)) {
|
||||
state.insert("next-wp");
|
||||
}
|
||||
|
||||
|
@ -999,8 +995,12 @@ void NavDisplay::processRoute()
|
|||
return; // no rules matched, we can skip this item
|
||||
}
|
||||
|
||||
SGGeod g = path.positionForIndex(w);
|
||||
SGPropertyNode* vars = _route->wayptNodeAtIndex(w);
|
||||
SGGeod g = path.positionForIndex(l);
|
||||
SGPropertyNode* vars = _route->wayptNodeAtIndex(l);
|
||||
if (!vars) {
|
||||
continue; // shouldn't happen, but let's guard against it
|
||||
}
|
||||
|
||||
double heading;
|
||||
computeWayptPropsAndHeading(wpt, g, vars, heading);
|
||||
|
||||
|
@ -1009,7 +1009,7 @@ void NavDisplay::processRoute()
|
|||
addSymbolInstance(projected, heading, r->getDefinition(), vars);
|
||||
|
||||
if (r->getDefinition()->drawRouteLeg) {
|
||||
SGGeodVec gv(path.pathForIndex(w));
|
||||
SGGeodVec gv(path.pathForIndex(l));
|
||||
if (!gv.empty()) {
|
||||
osg::Vec2 pr = projectGeod(gv[0]);
|
||||
for (unsigned int i=1; i<gv.size(); ++i) {
|
||||
|
@ -1189,6 +1189,7 @@ void NavDisplay::computePositionedState(FGPositioned* pos, string_set& states)
|
|||
states.insert("on-active-route");
|
||||
}
|
||||
|
||||
flightgear::FlightPlan* fp = _route->flightPlan();
|
||||
switch (pos->type()) {
|
||||
case FGPositioned::VOR:
|
||||
case FGPositioned::LOC:
|
||||
|
@ -1209,21 +1210,21 @@ void NavDisplay::computePositionedState(FGPositioned* pos, string_set& states)
|
|||
// mark alternates!
|
||||
// once the FMS system has some way to tell us about them, of course
|
||||
|
||||
if (pos == _route->departureAirport()) {
|
||||
if (pos == fp->departureAirport()) {
|
||||
states.insert("departure");
|
||||
}
|
||||
|
||||
if (pos == _route->destinationAirport()) {
|
||||
if (pos == fp->destinationAirport()) {
|
||||
states.insert("destination");
|
||||
}
|
||||
break;
|
||||
|
||||
case FGPositioned::RUNWAY:
|
||||
if (pos == _route->departureRunway()) {
|
||||
if (pos == fp->departureRunway()) {
|
||||
states.insert("departure");
|
||||
}
|
||||
|
||||
if (pos == _route->destinationRunway()) {
|
||||
if (pos == fp->destinationRunway()) {
|
||||
states.insert("destination");
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -724,7 +724,7 @@ void GPS::routeManagerSequenced()
|
|||
SG_LOG(SG_INSTR, SG_INFO, "GPS waypoint index is now " << index);
|
||||
|
||||
if (index > 0) {
|
||||
_prevWaypt = _routeMgr->previousWaypt();
|
||||
_prevWaypt = _routeMgr->wayptAtIndex(index - 1);
|
||||
if (_prevWaypt->flag(WPT_DYNAMIC)) {
|
||||
_wp0_position = _indicated_pos;
|
||||
} else {
|
||||
|
@ -829,7 +829,7 @@ void GPS::updateOverflight()
|
|||
|
||||
// check for wp1 being on active route - resume leg mode
|
||||
if (_routeMgr->isRouteActive()) {
|
||||
int index = _routeMgr->findWayptIndex(_currentWaypt->position());
|
||||
int index = _routeMgr->flightPlan()->findWayptIndex(_currentWaypt->position());
|
||||
if (index >= 0) {
|
||||
SG_LOG(SG_INSTR, SG_INFO, "GPS DTO, resuming LEG mode at wp:" << index);
|
||||
_mode = "leg";
|
||||
|
@ -881,7 +881,7 @@ void GPS::computeTurnData()
|
|||
return;
|
||||
}
|
||||
|
||||
WayptRef next = _routeMgr->nextWaypt();
|
||||
WayptRef next = _routeMgr->wayptAtIndex(_routeMgr->currentIndex() + 1);
|
||||
if (!next || next->flag(WPT_DYNAMIC)) {
|
||||
_anticipateTurn = false;
|
||||
return;
|
||||
|
@ -1684,7 +1684,7 @@ void GPS::insertWaypointAtIndex(int aIndex)
|
|||
string ident = _scratchNode->getStringValue("ident");
|
||||
|
||||
WayptRef wpt = new BasicWaypt(_scratchPos, ident, NULL);
|
||||
_routeMgr->insertWayptAtIndex(wpt, aIndex);
|
||||
_routeMgr->flightPlan()->insertWayptAtIndex(wpt, aIndex);
|
||||
}
|
||||
|
||||
void GPS::removeWaypointAtIndex(int aIndex)
|
||||
|
@ -1693,7 +1693,7 @@ void GPS::removeWaypointAtIndex(int aIndex)
|
|||
throw sg_range_exception("GPS::removeWaypointAtIndex: index out of bounds");
|
||||
}
|
||||
|
||||
_routeMgr->removeWayptAtIndex(aIndex);
|
||||
_routeMgr->removeLegAtIndex(aIndex);
|
||||
}
|
||||
|
||||
void GPS::tieSGGeod(SGPropertyNode* aNode, SGGeod& aRef,
|
||||
|
|
|
@ -317,7 +317,9 @@ public:
|
|||
double curAlt = _rnav->position().getElevationFt();
|
||||
|
||||
switch (_waypt->altitudeRestriction()) {
|
||||
case RESTRICT_AT: {
|
||||
case RESTRICT_AT:
|
||||
case RESTRICT_COMPUTED:
|
||||
{
|
||||
double d = curAlt - _waypt->altitudeFt();
|
||||
if (fabs(d) < 50.0) {
|
||||
SG_LOG(SG_INSTR, SG_INFO, "ConstHdgToAltCtl, reached target altitude " << _waypt->altitudeFt());
|
||||
|
@ -339,11 +341,7 @@ public:
|
|||
}
|
||||
break;
|
||||
|
||||
case RESTRICT_NONE:
|
||||
assert(false);
|
||||
break;
|
||||
case SPEED_RESTRICT_MACH:
|
||||
assert(false);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,8 @@ set(SOURCES
|
|||
route.cxx
|
||||
routePath.cxx
|
||||
waypoint.cxx
|
||||
)
|
||||
LevelDXML.cxx
|
||||
)
|
||||
|
||||
set(HEADERS
|
||||
airways.hxx
|
||||
|
@ -26,6 +27,7 @@ set(HEADERS
|
|||
route.hxx
|
||||
routePath.hxx
|
||||
waypoint.hxx
|
||||
)
|
||||
LevelDXML.hxx
|
||||
)
|
||||
|
||||
flightgear_component(Navaids "${SOURCES}" "${HEADERS}")
|
337
src/Navaids/LevelDXML.cxx
Normal file
337
src/Navaids/LevelDXML.cxx
Normal file
|
@ -0,0 +1,337 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "LevelDXML.hxx"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
#include <Navaids/waypoint.hxx>
|
||||
#include <Airports/simple.hxx>
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
namespace flightgear
|
||||
{
|
||||
|
||||
NavdataVisitor::NavdataVisitor(FGAirport* aApt, const SGPath& aPath):
|
||||
_airport(aApt),
|
||||
_path(aPath),
|
||||
_sid(NULL),
|
||||
_star(NULL),
|
||||
_approach(NULL),
|
||||
_transition(NULL),
|
||||
_procedure(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
void NavdataVisitor::startXML()
|
||||
{
|
||||
}
|
||||
|
||||
void NavdataVisitor::endXML()
|
||||
{
|
||||
}
|
||||
|
||||
void NavdataVisitor::startElement(const char* name, const XMLAttributes &atts)
|
||||
{
|
||||
_text.clear();
|
||||
string tag(name);
|
||||
if (tag == "Airport") {
|
||||
string icao(atts.getValue("ICAOcode"));
|
||||
if (_airport->ident() != icao) {
|
||||
throw sg_format_exception("Airport and ICAO mismatch", icao, _path.str());
|
||||
}
|
||||
} else if (tag == "Sid") {
|
||||
string ident(atts.getValue("Name"));
|
||||
_sid = new SID(ident, _airport);
|
||||
_procedure = _sid;
|
||||
_waypoints.clear();
|
||||
processRunways(_sid, atts);
|
||||
} else if (tag == "Star") {
|
||||
string ident(atts.getValue("Name"));
|
||||
_star = new STAR(ident, _airport);
|
||||
_procedure = _star;
|
||||
_waypoints.clear();
|
||||
processRunways(_star, atts);
|
||||
} else if ((tag == "Sid_Waypoint") ||
|
||||
(tag == "App_Waypoint") ||
|
||||
(tag == "Star_Waypoint") ||
|
||||
(tag == "AppTr_Waypoint") ||
|
||||
(tag == "SidTr_Waypoint") ||
|
||||
(tag == "RwyTr_Waypoint"))
|
||||
{
|
||||
// reset waypoint data
|
||||
_speed = 0.0;
|
||||
_altRestrict = RESTRICT_NONE;
|
||||
_altitude = 0.0;
|
||||
} else if (tag == "Approach") {
|
||||
_ident = atts.getValue("Name");
|
||||
_waypoints.clear();
|
||||
ProcedureType ty = PROCEDURE_APPROACH_RNAV;
|
||||
_approach = new Approach(_ident, ty);
|
||||
_procedure = _approach;
|
||||
} else if ((tag == "Sid_Transition") ||
|
||||
(tag == "App_Transition") ||
|
||||
(tag == "Star_Transition")) {
|
||||
_transIdent = atts.getValue("Name");
|
||||
_transition = new Transition(_transIdent, PROCEDURE_TRANSITION, _procedure);
|
||||
_transWaypts.clear();
|
||||
} else if (tag == "RunwayTransition") {
|
||||
_transIdent = atts.getValue("Runway");
|
||||
_transition = new Transition(_transIdent, PROCEDURE_RUNWAY_TRANSITION, _procedure);
|
||||
_transWaypts.clear();
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void NavdataVisitor::processRunways(ArrivalDeparture* aProc, const XMLAttributes &atts)
|
||||
{
|
||||
string v("All");
|
||||
if (atts.hasAttribute("Runways")) {
|
||||
v = atts.getValue("Runways");
|
||||
}
|
||||
|
||||
if (v == "All") {
|
||||
for (unsigned int r=0; r<_airport->numRunways(); ++r) {
|
||||
aProc->addRunway(_airport->getRunwayByIndex(r));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
vector<string> rwys;
|
||||
boost::split(rwys, v, boost::is_any_of(" ,"));
|
||||
for (unsigned int r=0; r<rwys.size(); ++r) {
|
||||
FGRunway* rwy = _airport->getRunwayByIdent(rwys[r]);
|
||||
aProc->addRunway(rwy);
|
||||
}
|
||||
}
|
||||
|
||||
void NavdataVisitor::endElement(const char* name)
|
||||
{
|
||||
string tag(name);
|
||||
if ((tag == "Sid_Waypoint") ||
|
||||
(tag == "App_Waypoint") ||
|
||||
(tag == "Star_Waypoint"))
|
||||
{
|
||||
_waypoints.push_back(buildWaypoint(_procedure));
|
||||
} else if ((tag == "AppTr_Waypoint") ||
|
||||
(tag == "SidTr_Waypoint") ||
|
||||
(tag == "RwyTr_Waypoint") ||
|
||||
(tag == "StarTr_Waypoint"))
|
||||
{
|
||||
_transWaypts.push_back(buildWaypoint(_transition));
|
||||
} else if (tag == "Sid_Transition") {
|
||||
assert(_sid);
|
||||
// SID waypoints are stored backwards, to share code with STARs
|
||||
std::reverse(_transWaypts.begin(), _transWaypts.end());
|
||||
_transition->setPrimary(_transWaypts);
|
||||
_sid->addTransition(_transition);
|
||||
} else if (tag == "Star_Transition") {
|
||||
assert(_star);
|
||||
_transition->setPrimary(_transWaypts);
|
||||
_star->addTransition(_transition);
|
||||
} else if (tag == "App_Transition") {
|
||||
assert(_approach);
|
||||
_transition->setPrimary(_transWaypts);
|
||||
_approach->addTransition(_transition);
|
||||
} else if (tag == "RunwayTransition") {
|
||||
ArrivalDeparture* ad;
|
||||
if (_sid) {
|
||||
// SID waypoints are stored backwards, to share code with STARs
|
||||
std::reverse(_transWaypts.begin(), _transWaypts.end());
|
||||
ad = _sid;
|
||||
} else {
|
||||
ad = _star;
|
||||
}
|
||||
|
||||
_transition->setPrimary(_transWaypts);
|
||||
FGRunwayRef rwy = _airport->getRunwayByIdent(_transIdent);
|
||||
ad->addRunwayTransition(rwy, _transition);
|
||||
} else if (tag == "Approach") {
|
||||
finishApproach();
|
||||
} else if (tag == "Sid") {
|
||||
finishSid();
|
||||
} else if (tag == "Star") {
|
||||
finishStar();
|
||||
} else if (tag == "Longitude") {
|
||||
_longitude = atof(_text.c_str());
|
||||
} else if (tag == "Latitude") {
|
||||
_latitude = atof(_text.c_str());
|
||||
} else if (tag == "Name") {
|
||||
_wayptName = _text;
|
||||
} else if (tag == "Type") {
|
||||
_wayptType = _text;
|
||||
} else if (tag == "Speed") {
|
||||
_speed = atoi(_text.c_str());
|
||||
} else if (tag == "Altitude") {
|
||||
_altitude = atof(_text.c_str());
|
||||
} else if (tag == "AltitudeRestriction") {
|
||||
if (_text == "at") {
|
||||
_altRestrict = RESTRICT_AT;
|
||||
} else if (_text == "above") {
|
||||
_altRestrict = RESTRICT_ABOVE;
|
||||
} else if (_text == "below") {
|
||||
_altRestrict = RESTRICT_BELOW;
|
||||
} else {
|
||||
throw sg_format_exception("Unrecognized altitude restriction", _text);
|
||||
}
|
||||
} else if (tag == "Hld_Rad_or_Inbd") {
|
||||
if (_text == "Inbd") {
|
||||
_holdRadial = -1.0;
|
||||
}
|
||||
} else if (tag == "Hld_Time_or_Dist") {
|
||||
_holdDistance = (_text == "Dist");
|
||||
} else if (tag == "Hld_Rad_value") {
|
||||
_holdRadial = atof(_text.c_str());
|
||||
} else if (tag == "Hld_Turn") {
|
||||
_holdRighthanded = (_text == "Right");
|
||||
} else if (tag == "Hld_td_value") {
|
||||
_holdTD = atof(_text.c_str());
|
||||
} else if (tag == "Hdg_Crs_value") {
|
||||
_course = atof(_text.c_str());
|
||||
} else if (tag == "DMEtoIntercept") {
|
||||
_dmeDistance = atof(_text.c_str());
|
||||
} else if (tag == "RadialtoIntercept") {
|
||||
_radial = atof(_text.c_str());
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Waypt* NavdataVisitor::buildWaypoint(RouteBase* owner)
|
||||
{
|
||||
Waypt* wp = NULL;
|
||||
if (_wayptType == "Normal") {
|
||||
// new LatLonWaypoint
|
||||
SGGeod pos(SGGeod::fromDeg(_longitude, _latitude));
|
||||
wp = new BasicWaypt(pos, _wayptName, owner);
|
||||
} else if (_wayptType == "Runway") {
|
||||
string ident = _wayptName.substr(2);
|
||||
FGRunwayRef rwy = _airport->getRunwayByIdent(ident);
|
||||
wp = new RunwayWaypt(rwy, owner);
|
||||
} else if (_wayptType == "Hold") {
|
||||
SGGeod pos(SGGeod::fromDeg(_longitude, _latitude));
|
||||
Hold* h = new Hold(pos, _wayptName, owner);
|
||||
wp = h;
|
||||
if (_holdRighthanded) {
|
||||
h->setRightHanded();
|
||||
} else {
|
||||
h->setLeftHanded();
|
||||
}
|
||||
|
||||
if (_holdDistance) {
|
||||
h->setHoldDistance(_holdTD);
|
||||
} else {
|
||||
h->setHoldTime(_holdTD * 60.0);
|
||||
}
|
||||
|
||||
if (_holdRadial >= 0.0) {
|
||||
h->setHoldRadial(_holdRadial);
|
||||
}
|
||||
} else if (_wayptType == "Vectors") {
|
||||
wp = new ATCVectors(owner, _airport);
|
||||
} else if ((_wayptType == "Intc") || (_wayptType == "VorRadialIntc")) {
|
||||
SGGeod pos(SGGeod::fromDeg(_longitude, _latitude));
|
||||
wp = new RadialIntercept(owner, _wayptName, pos, _course, _radial);
|
||||
} else if (_wayptType == "DmeIntc") {
|
||||
SGGeod pos(SGGeod::fromDeg(_longitude, _latitude));
|
||||
wp = new DMEIntercept(owner, _wayptName, pos, _course, _dmeDistance);
|
||||
} else if (_wayptType == "ConstHdgtoAlt") {
|
||||
wp = new HeadingToAltitude(owner, _wayptName, _course);
|
||||
} else if (_wayptType == "PBD") {
|
||||
SGGeod pos(SGGeod::fromDeg(_longitude, _latitude)), pos2;
|
||||
double az2;
|
||||
SGGeodesy::direct(pos, _course, _dmeDistance, pos2, az2);
|
||||
wp = new BasicWaypt(pos2, _wayptName, owner);
|
||||
} else {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "implement waypoint type:" << _wayptType);
|
||||
throw sg_format_exception("Unrecognized waypt type", _wayptType);
|
||||
}
|
||||
|
||||
assert(wp);
|
||||
if ((_altitude > 0.0) && (_altRestrict != RESTRICT_NONE)) {
|
||||
wp->setAltitude(_altitude,_altRestrict);
|
||||
}
|
||||
|
||||
if (_speed > 0.0) {
|
||||
wp->setSpeed(_speed, RESTRICT_AT); // or _BELOW?
|
||||
}
|
||||
|
||||
return wp;
|
||||
}
|
||||
|
||||
void NavdataVisitor::finishApproach()
|
||||
{
|
||||
WayptVec::iterator it;
|
||||
FGRunwayRef rwy;
|
||||
|
||||
// find the runway node
|
||||
for (it = _waypoints.begin(); it != _waypoints.end(); ++it) {
|
||||
FGPositionedRef navid = (*it)->source();
|
||||
if (!navid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (navid->type() == FGPositioned::RUNWAY) {
|
||||
rwy = (FGRunway*) navid.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rwy) {
|
||||
throw sg_format_exception("Malformed approach, no runway waypt", _ident);
|
||||
}
|
||||
|
||||
WayptVec primary(_waypoints.begin(), it);
|
||||
// erase all points up to and including the runway, to leave only the
|
||||
// missed segments
|
||||
_waypoints.erase(_waypoints.begin(), ++it);
|
||||
|
||||
_approach->setRunway(rwy);
|
||||
_approach->setPrimaryAndMissed(primary, _waypoints);
|
||||
_airport->addApproach(_approach);
|
||||
_approach = NULL;
|
||||
}
|
||||
|
||||
void NavdataVisitor::finishSid()
|
||||
{
|
||||
// reverse order, because that's how we deal with commonality between
|
||||
// STARs and SIDs. SID::route undoes this
|
||||
std::reverse(_waypoints.begin(), _waypoints.end());
|
||||
_sid->setCommon(_waypoints);
|
||||
_airport->addSID(_sid);
|
||||
_sid = NULL;
|
||||
}
|
||||
|
||||
void NavdataVisitor::finishStar()
|
||||
{
|
||||
_star->setCommon(_waypoints);
|
||||
_airport->addSTAR(_star);
|
||||
_star = NULL;
|
||||
}
|
||||
|
||||
void NavdataVisitor::data (const char * s, int len)
|
||||
{
|
||||
_text += string(s, len);
|
||||
}
|
||||
|
||||
|
||||
void NavdataVisitor::pi (const char * target, const char * data) {
|
||||
//cout << "Processing instruction " << target << ' ' << data << endl;
|
||||
}
|
||||
|
||||
void NavdataVisitor::warning (const char * message, int line, int column) {
|
||||
SG_LOG(SG_IO, SG_WARN, "Warning: " << message << " (" << line << ',' << column << ')');
|
||||
}
|
||||
|
||||
void NavdataVisitor::error (const char * message, int line, int column) {
|
||||
SG_LOG(SG_IO, SG_ALERT, "Error: " << message << " (" << line << ',' << column << ')');
|
||||
}
|
||||
|
||||
}
|
66
src/Navaids/LevelDXML.hxx
Normal file
66
src/Navaids/LevelDXML.hxx
Normal file
|
@ -0,0 +1,66 @@
|
|||
#ifndef FG_NAV_LEVELDXML_HXX
|
||||
#define FG_NAV_LEVELDXML_HXX
|
||||
|
||||
class FGAirport;
|
||||
class SGPath;
|
||||
|
||||
#include <simgear/xml/easyxml.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <Navaids/procedure.hxx>
|
||||
|
||||
namespace flightgear
|
||||
{
|
||||
|
||||
class NavdataVisitor : public XMLVisitor {
|
||||
public:
|
||||
NavdataVisitor(FGAirport* aApt, const SGPath& aPath);
|
||||
|
||||
protected:
|
||||
virtual void startXML ();
|
||||
virtual void endXML ();
|
||||
virtual void startElement (const char * name, const XMLAttributes &atts);
|
||||
virtual void endElement (const char * name);
|
||||
virtual void data (const char * s, int len);
|
||||
virtual void pi (const char * target, const char * data);
|
||||
virtual void warning (const char * message, int line, int column);
|
||||
virtual void error (const char * message, int line, int column);
|
||||
|
||||
private:
|
||||
Waypt* buildWaypoint(RouteBase* owner);
|
||||
void processRunways(ArrivalDeparture* aProc, const XMLAttributes &atts);
|
||||
|
||||
void finishApproach();
|
||||
void finishSid();
|
||||
void finishStar();
|
||||
|
||||
FGAirport* _airport;
|
||||
SGPath _path;
|
||||
std::string _text; ///< last element text value
|
||||
|
||||
SID* _sid;
|
||||
STAR* _star;
|
||||
Approach* _approach;
|
||||
Transition* _transition;
|
||||
Procedure* _procedure;
|
||||
|
||||
WayptVec _waypoints; ///< waypoint list for current approach/sid/star
|
||||
WayptVec _transWaypts; ///< waypoint list for current transition
|
||||
|
||||
std::string _wayptName;
|
||||
std::string _wayptType;
|
||||
std::string _ident; // id of segment under construction
|
||||
std::string _transIdent;
|
||||
double _longitude, _latitude, _altitude, _speed;
|
||||
RouteRestriction _altRestrict;
|
||||
|
||||
double _holdRadial; // inbound hold radial, or -1 if radial is 'inbound'
|
||||
double _holdTD; ///< hold time (seconds) or distance (nm), based on flag below
|
||||
bool _holdRighthanded;
|
||||
bool _holdDistance; // true, TD is distance in nm; false, TD is time in seconds
|
||||
|
||||
double _course, _radial, _dmeDistance;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -35,7 +35,7 @@ struct SearchContext;
|
|||
class AdjacentWaypoint;
|
||||
class InAirwayFilter;
|
||||
|
||||
class Airway : public Route
|
||||
class Airway : public RouteBase
|
||||
{
|
||||
public:
|
||||
virtual std::string ident() const
|
||||
|
|
|
@ -30,14 +30,22 @@ using std::string;
|
|||
|
||||
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)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -47,22 +55,32 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,6 +88,7 @@ void Approach::addTransition(Transition* aTrans)
|
|||
{
|
||||
WayptRef entry = aTrans->enroute();
|
||||
_transitions[entry] = aTrans;
|
||||
aTrans->mark(WPT_APPROACH);
|
||||
}
|
||||
|
||||
bool Approach::route(WayptRef aIAF, WayptVec& aWps)
|
||||
|
@ -78,8 +97,9 @@ bool Approach::route(WayptRef aIAF, WayptVec& aWps)
|
|||
bool haveTrans = false;
|
||||
for (it = _transitions.begin(); it != _transitions.end(); ++it) {
|
||||
Transition* t= it->second;
|
||||
if (t->route(aIAF, aWps)) {
|
||||
haveTrans = true;
|
||||
if (t->enroute()->matches(aIAF)) {
|
||||
t->route(aWps);
|
||||
haveTrans = true;
|
||||
break;
|
||||
}
|
||||
} // of transitions iteration
|
||||
|
@ -90,10 +110,7 @@ bool Approach::route(WayptRef aIAF, WayptVec& aWps)
|
|||
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)
|
||||
|
@ -104,34 +121,64 @@ bool Approach::routeFromVectors(WayptVec& aWps)
|
|||
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));
|
||||
}
|
||||
|
||||
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());
|
||||
|
@ -139,23 +186,24 @@ void ArrivalDeparture::addRunwayTransition(FGRunwayRef aWay, Transition* aTrans)
|
|||
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) {
|
||||
|
@ -170,9 +218,7 @@ bool ArrivalDeparture::commonRoute(Waypt* aEnroute, WayptVec& aPath, FGRunwayRef
|
|||
// 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
|
||||
|
@ -193,7 +239,7 @@ bool ArrivalDeparture::commonRoute(Waypt* aEnroute, WayptVec& aPath, FGRunwayRef
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -241,13 +287,12 @@ WayptRef ArrivalDeparture::findBestTransition(const SGGeod& aPos) const
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,12 +301,12 @@ WayptRef ArrivalDeparture::findTransitionByName(const string& aIdent) const
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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());
|
||||
|
@ -269,7 +314,7 @@ bool SID::route(FGRunwayRef aWay, Waypt* aEnroute, WayptVec& aPath)
|
|||
}
|
||||
|
||||
WayptVec path;
|
||||
if (!commonRoute(aEnroute, path, aWay)) {
|
||||
if (!commonRoute(trans, path, aWay)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -283,24 +328,25 @@ bool SID::route(FGRunwayRef aWay, Waypt* aEnroute, WayptVec& aPath)
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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) :
|
||||
_ident(aIdent),
|
||||
Transition::Transition(const std::string& aIdent, ProcedureType ty, Procedure* aPr) :
|
||||
Procedure(aIdent),
|
||||
_type(ty),
|
||||
_parent(aPr)
|
||||
{
|
||||
assert(aPr);
|
||||
|
@ -325,14 +371,20 @@ WayptRef Transition::procedureEnd() const
|
|||
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
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
#include <set>
|
||||
|
||||
#include <simgear/math/sg_types.hxx> // for string_list
|
||||
|
||||
#include <Navaids/route.hxx>
|
||||
#include <Airports/runways.hxx>
|
||||
|
||||
|
@ -32,12 +34,32 @@ namespace flightgear {
|
|||
// forward decls
|
||||
class NavdataVisitor;
|
||||
|
||||
class Procedure : public Route
|
||||
typedef std::vector<FGRunwayRef> RunwayVec;
|
||||
|
||||
typedef enum {
|
||||
PROCEDURE_INVALID,
|
||||
PROCEDURE_APPROACH_ILS,
|
||||
PROCEDURE_APPROACH_VOR,
|
||||
PROCEDURE_APPROACH_NDB,
|
||||
PROCEDURE_APPROACH_RNAV,
|
||||
PROCEDURE_SID,
|
||||
PROCEDURE_STAR,
|
||||
PROCEDURE_TRANSITION,
|
||||
PROCEDURE_RUNWAY_TRANSITION
|
||||
} ProcedureType;
|
||||
|
||||
class Procedure : public RouteBase
|
||||
{
|
||||
public:
|
||||
|
||||
public:
|
||||
virtual ProcedureType type() const = 0;
|
||||
|
||||
virtual std::string ident() const
|
||||
{ return _ident; }
|
||||
|
||||
virtual FGAirport* airport() const = 0;
|
||||
|
||||
virtual RunwayVec runways() const
|
||||
{ return RunwayVec(); }
|
||||
protected:
|
||||
Procedure(const std::string& aIdent);
|
||||
|
||||
|
@ -47,14 +69,16 @@ protected:
|
|||
/**
|
||||
* Encapsulate a transition segment
|
||||
*/
|
||||
class Transition : public Route
|
||||
class Transition : public Procedure
|
||||
{
|
||||
public:
|
||||
bool route(Waypt* aEnroute, WayptVec& aPath);
|
||||
bool route(WayptVec& aPath);
|
||||
|
||||
Procedure* parent() const
|
||||
{ return _parent; }
|
||||
|
||||
virtual FGAirport* airport() const;
|
||||
|
||||
/**
|
||||
* Return the enroute end of the transition
|
||||
*/
|
||||
|
@ -65,16 +89,19 @@ public:
|
|||
*/
|
||||
WayptRef procedureEnd() const;
|
||||
|
||||
virtual std::string ident() const
|
||||
{ return _ident; }
|
||||
|
||||
virtual ProcedureType type() const
|
||||
{ return _type; }
|
||||
|
||||
void mark(WayptFlag f);
|
||||
private:
|
||||
friend class NavdataVisitor;
|
||||
|
||||
Transition(const std::string& aIdent, Procedure* aPr);
|
||||
Transition(const std::string& aIdent, ProcedureType ty, Procedure* aPr);
|
||||
|
||||
void setPrimary(const WayptVec& aWps);
|
||||
|
||||
std::string _ident;
|
||||
ProcedureType _type;
|
||||
Procedure* _parent;
|
||||
WayptVec _primary;
|
||||
};
|
||||
|
@ -89,6 +116,12 @@ public:
|
|||
FGRunwayRef runway()
|
||||
{ return _runway; }
|
||||
|
||||
static bool isApproach(ProcedureType ty);
|
||||
|
||||
virtual FGAirport* airport() const;
|
||||
|
||||
virtual RunwayVec runways() const;
|
||||
|
||||
/**
|
||||
* Build a route from a valid IAF to the runway, including the missed
|
||||
* segment. Return false if no valid transition from the specified IAF
|
||||
|
@ -108,16 +141,19 @@ public:
|
|||
const WayptVec& missed() const
|
||||
{ return _missed; }
|
||||
|
||||
virtual ProcedureType type() const
|
||||
{ return _type; }
|
||||
private:
|
||||
friend class NavdataVisitor;
|
||||
|
||||
Approach(const std::string& aIdent);
|
||||
Approach(const std::string& aIdent, ProcedureType ty);
|
||||
|
||||
void setRunway(FGRunwayRef aRwy);
|
||||
void setPrimaryAndMissed(const WayptVec& aPrimary, const WayptVec& aMissed);
|
||||
void addTransition(Transition* aTrans);
|
||||
|
||||
FGRunwayRef _runway;
|
||||
ProcedureType _type;
|
||||
|
||||
typedef std::map<WayptRef, Transition*> WptTransitionMap;
|
||||
WptTransitionMap _transitions;
|
||||
|
@ -129,20 +165,27 @@ private:
|
|||
class ArrivalDeparture : public Procedure
|
||||
{
|
||||
public:
|
||||
virtual FGAirport* airport() const
|
||||
{ return _airport; }
|
||||
|
||||
/**
|
||||
* Predicate, test if this procedure applies to the requested runway
|
||||
*/
|
||||
virtual bool isForRunway(FGRunwayRef aWay) const;
|
||||
virtual bool isForRunway(const FGRunway* aWay) const;
|
||||
|
||||
virtual RunwayVec runways() const;
|
||||
|
||||
/**
|
||||
* Find a path between the runway and enroute structure. Waypoints
|
||||
* corresponding to the appropriate transitions and segments will be created.
|
||||
*/
|
||||
virtual bool route(FGRunwayRef aWay, Waypt* aEnroute, WayptVec& aPath) = 0;
|
||||
virtual bool route(FGRunwayRef aWay, Transition* trans, WayptVec& aPath) = 0;
|
||||
|
||||
const WayptVec& common() const
|
||||
{ return _common; }
|
||||
|
||||
string_list transitionIdents() const;
|
||||
|
||||
/**
|
||||
* Given an enroute location, find the best enroute transition point for
|
||||
* this arrival/departure. Best is currently determined as 'closest to the
|
||||
|
@ -155,14 +198,14 @@ public:
|
|||
* for the route-manager and similar code that that needs to talk about
|
||||
* transitions in a human-meaningful way (including persistence).
|
||||
*/
|
||||
WayptRef findTransitionByName(const std::string& aIdent) const;
|
||||
Transition* findTransitionByName(const std::string& aIdent) const;
|
||||
|
||||
Transition* findTransitionByEnroute(Waypt* aEnroute) const;
|
||||
protected:
|
||||
|
||||
bool commonRoute(Waypt* aEnroute, WayptVec& aPath, FGRunwayRef aRwy);
|
||||
bool commonRoute(Transition* t, WayptVec& aPath, FGRunwayRef aRwy);
|
||||
|
||||
ArrivalDeparture(const std::string& aIdent);
|
||||
ArrivalDeparture(const std::string& aIdent, FGAirport* apt);
|
||||
|
||||
|
||||
void addRunway(FGRunwayRef aRwy);
|
||||
|
@ -170,6 +213,7 @@ protected:
|
|||
typedef std::map<FGRunwayRef, Transition*> RunwayTransitionMap;
|
||||
RunwayTransitionMap _runways;
|
||||
|
||||
virtual WayptFlag flagType() const = 0;
|
||||
private:
|
||||
friend class NavdataVisitor;
|
||||
|
||||
|
@ -179,6 +223,7 @@ private:
|
|||
|
||||
void addRunwayTransition(FGRunwayRef aRwy, Transition* aTrans);
|
||||
|
||||
FGAirport* _airport;
|
||||
WayptVec _common;
|
||||
|
||||
typedef std::map<WayptRef, Transition*> WptTransitionMap;
|
||||
|
@ -190,23 +235,37 @@ private:
|
|||
class SID : public ArrivalDeparture
|
||||
{
|
||||
public:
|
||||
virtual bool route(FGRunwayRef aWay, Waypt* aEnroute, WayptVec& aPath);
|
||||
virtual bool route(FGRunwayRef aWay, Transition* aTrans, WayptVec& aPath);
|
||||
|
||||
virtual ProcedureType type() const
|
||||
{ return PROCEDURE_SID; }
|
||||
|
||||
protected:
|
||||
virtual WayptFlag flagType() const
|
||||
{ return WPT_DEPARTURE; }
|
||||
|
||||
private:
|
||||
friend class NavdataVisitor;
|
||||
|
||||
SID(const std::string& aIdent);
|
||||
SID(const std::string& aIdent, FGAirport* apt);
|
||||
};
|
||||
|
||||
class STAR : public ArrivalDeparture
|
||||
{
|
||||
public:
|
||||
virtual bool route(FGRunwayRef aWay, Waypt* aEnroute, WayptVec& aPath);
|
||||
virtual bool route(FGRunwayRef aWay, Transition* aTrans, WayptVec& aPath);
|
||||
|
||||
virtual ProcedureType type() const
|
||||
{ return PROCEDURE_STAR; }
|
||||
|
||||
protected:
|
||||
virtual WayptFlag flagType() const
|
||||
{ return WPT_ARRIVAL; }
|
||||
|
||||
private:
|
||||
friend class NavdataVisitor;
|
||||
|
||||
STAR(const std::string& aIdent);
|
||||
STAR(const std::string& aIdent, FGAirport* apt);
|
||||
};
|
||||
|
||||
} // of namespace
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -39,16 +39,22 @@
|
|||
// forward decls
|
||||
class FGPositioned;
|
||||
class SGPath;
|
||||
class FGAirport;
|
||||
class FGRunway;
|
||||
|
||||
#include <Airports/simple.hxx>
|
||||
typedef SGSharedPtr<FGAirport> FGAirportRef;
|
||||
|
||||
namespace flightgear
|
||||
{
|
||||
|
||||
// forward decls
|
||||
class Route;
|
||||
class RouteBase;
|
||||
class Waypt;
|
||||
class NavdataVisitor;
|
||||
|
||||
class SID;
|
||||
class STAR;
|
||||
class Transition;
|
||||
|
||||
typedef SGSharedPtr<Waypt> WayptRef;
|
||||
|
||||
typedef enum {
|
||||
|
@ -66,7 +72,12 @@ typedef enum {
|
|||
WPT_GENERATED = 1 << 7,
|
||||
|
||||
WPT_DEPARTURE = 1 << 8,
|
||||
WPT_ARRIVAL = 1 << 9
|
||||
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 {
|
||||
|
@ -74,9 +85,14 @@ typedef enum {
|
|||
RESTRICT_AT,
|
||||
RESTRICT_ABOVE,
|
||||
RESTRICT_BELOW,
|
||||
SPEED_RESTRICT_MACH
|
||||
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)
|
||||
|
@ -86,7 +102,7 @@ class Waypt : public SGReferenced
|
|||
public:
|
||||
virtual ~Waypt();
|
||||
|
||||
Route* owner() const
|
||||
RouteBase* owner() const
|
||||
{ return _owner; }
|
||||
|
||||
/**
|
||||
|
@ -140,7 +156,7 @@ public:
|
|||
/**
|
||||
* Factory method
|
||||
*/
|
||||
static WayptRef createFromProperties(Route* aOwner, SGPropertyNode_ptr aProp);
|
||||
static WayptRef createFromProperties(RouteBase* aOwner, SGPropertyNode_ptr aProp);
|
||||
|
||||
void saveAsNode(SGPropertyNode* node) const;
|
||||
|
||||
|
@ -173,7 +189,7 @@ public:
|
|||
protected:
|
||||
friend class NavdataVisitor;
|
||||
|
||||
Waypt(Route* aOwner);
|
||||
Waypt(RouteBase* aOwner);
|
||||
|
||||
/**
|
||||
* Persistence helper - read node properties from a file
|
||||
|
@ -185,7 +201,7 @@ protected:
|
|||
*/
|
||||
virtual void writeToProperties(SGPropertyNode_ptr aProp) const;
|
||||
|
||||
typedef Waypt* (FactoryFunction)(Route* aOwner) ;
|
||||
typedef Waypt* (FactoryFunction)(RouteBase* aOwner) ;
|
||||
static void registerFactory(const std::string aNodeType, FactoryFunction* aFactory);
|
||||
|
||||
double _altitudeFt;
|
||||
|
@ -197,16 +213,16 @@ private:
|
|||
/**
|
||||
* Create an instance of a concrete subclass, or throw an exception
|
||||
*/
|
||||
static Waypt* createInstance(Route* aOwner, const std::string& aTypeName);
|
||||
static Waypt* createInstance(RouteBase* aOwner, const std::string& aTypeName);
|
||||
|
||||
Route* _owner;
|
||||
RouteBase* _owner;
|
||||
unsigned short _flags;
|
||||
mutable double _magVarDeg;
|
||||
};
|
||||
|
||||
typedef std::vector<WayptRef> WayptVec;
|
||||
|
||||
class Route
|
||||
class RouteBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
@ -216,14 +232,219 @@ public:
|
|||
|
||||
static void loadAirportProcedures(const SGPath& aPath, FGAirport* aApt);
|
||||
|
||||
static void dumpRouteToFile(const WayptVec& aRoute, const std::string& aName);
|
||||
static void dumpRouteToKML(const WayptVec& aRoute, const std::string& aName);
|
||||
|
||||
static void dumpRouteToLineString(const std::string& aIdent,
|
||||
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
|
||||
|
|
|
@ -53,11 +53,24 @@ double pointsKnownDistanceFromGC(const SGGeoc& a, const SGGeoc&b, const SGGeoc&
|
|||
|
||||
RoutePath::RoutePath(const flightgear::WayptVec& wpts) :
|
||||
_waypts(wpts)
|
||||
{
|
||||
commonInit();
|
||||
}
|
||||
|
||||
RoutePath::RoutePath(const flightgear::FlightPlan* fp)
|
||||
{
|
||||
for (int l=0; l<fp->numLegs(); ++l) {
|
||||
_waypts.push_back(fp->legAtIndex(l)->waypoint());
|
||||
}
|
||||
commonInit();
|
||||
}
|
||||
|
||||
void RoutePath::commonInit()
|
||||
{
|
||||
_pathClimbFPM = 1200;
|
||||
_pathDescentFPM = 800;
|
||||
_pathIAS = 190;
|
||||
_pathTurnRate = 3.0; // 3 deg/sec = 180def/min = standard rate turn
|
||||
_pathTurnRate = 3.0; // 3 deg/sec = 180def/min = standard rate turn
|
||||
}
|
||||
|
||||
SGGeodVec RoutePath::pathForIndex(int index) const
|
||||
|
|
|
@ -37,12 +37,15 @@ class RoutePath
|
|||
{
|
||||
public:
|
||||
RoutePath(const flightgear::WayptVec& wpts);
|
||||
|
||||
RoutePath(const flightgear::FlightPlan* fp);
|
||||
|
||||
SGGeodVec pathForIndex(int index) const;
|
||||
|
||||
SGGeod positionForIndex(int index) const;
|
||||
|
||||
private:
|
||||
void commonInit();
|
||||
|
||||
class PathCtx;
|
||||
|
||||
SGGeodVec pathForHold(flightgear::Hold* hold) const;
|
||||
|
|
|
@ -34,7 +34,7 @@ using std::string;
|
|||
namespace flightgear
|
||||
{
|
||||
|
||||
BasicWaypt::BasicWaypt(const SGGeod& aPos, const string& aIdent, Route* aOwner) :
|
||||
BasicWaypt::BasicWaypt(const SGGeod& aPos, const string& aIdent, RouteBase* aOwner) :
|
||||
Waypt(aOwner),
|
||||
_pos(aPos),
|
||||
_ident(aIdent)
|
||||
|
@ -44,14 +44,14 @@ BasicWaypt::BasicWaypt(const SGGeod& aPos, const string& aIdent, Route* aOwner)
|
|||
}
|
||||
}
|
||||
|
||||
BasicWaypt::BasicWaypt(const SGWayPoint& aWP, Route* aOwner) :
|
||||
BasicWaypt::BasicWaypt(const SGWayPoint& aWP, RouteBase* aOwner) :
|
||||
Waypt(aOwner),
|
||||
_pos(aWP.get_target()),
|
||||
_ident(aWP.get_id())
|
||||
{
|
||||
}
|
||||
|
||||
BasicWaypt::BasicWaypt(Route* aOwner) :
|
||||
BasicWaypt::BasicWaypt(RouteBase* aOwner) :
|
||||
Waypt(aOwner)
|
||||
{
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ void BasicWaypt::writeToProperties(SGPropertyNode_ptr aProp) const
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NavaidWaypoint::NavaidWaypoint(FGPositioned* aPos, Route* aOwner) :
|
||||
NavaidWaypoint::NavaidWaypoint(FGPositioned* aPos, RouteBase* aOwner) :
|
||||
Waypt(aOwner),
|
||||
_navaid(aPos)
|
||||
{
|
||||
|
@ -90,7 +90,7 @@ NavaidWaypoint::NavaidWaypoint(FGPositioned* aPos, Route* aOwner) :
|
|||
}
|
||||
}
|
||||
|
||||
NavaidWaypoint::NavaidWaypoint(Route* aOwner) :
|
||||
NavaidWaypoint::NavaidWaypoint(RouteBase* aOwner) :
|
||||
Waypt(aOwner)
|
||||
{
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ void NavaidWaypoint::writeToProperties(SGPropertyNode_ptr aProp) const
|
|||
aProp->setDoubleValue("lat", _navaid->geod().getLatitudeDeg());
|
||||
}
|
||||
|
||||
OffsetNavaidWaypoint::OffsetNavaidWaypoint(FGPositioned* aPos, Route* aOwner,
|
||||
OffsetNavaidWaypoint::OffsetNavaidWaypoint(FGPositioned* aPos, RouteBase* aOwner,
|
||||
double aRadial, double aDistNm) :
|
||||
NavaidWaypoint(aPos, aOwner),
|
||||
_radial(aRadial),
|
||||
|
@ -151,7 +151,7 @@ OffsetNavaidWaypoint::OffsetNavaidWaypoint(FGPositioned* aPos, Route* aOwner,
|
|||
init();
|
||||
}
|
||||
|
||||
OffsetNavaidWaypoint::OffsetNavaidWaypoint(Route* aOwner) :
|
||||
OffsetNavaidWaypoint::OffsetNavaidWaypoint(RouteBase* aOwner) :
|
||||
NavaidWaypoint(aOwner)
|
||||
{
|
||||
}
|
||||
|
@ -186,13 +186,13 @@ void OffsetNavaidWaypoint::writeToProperties(SGPropertyNode_ptr aProp) const
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RunwayWaypt::RunwayWaypt(FGRunway* aPos, Route* aOwner) :
|
||||
RunwayWaypt::RunwayWaypt(FGRunway* aPos, RouteBase* aOwner) :
|
||||
Waypt(aOwner),
|
||||
_runway(aPos)
|
||||
{
|
||||
}
|
||||
|
||||
RunwayWaypt::RunwayWaypt(Route* aOwner) :
|
||||
RunwayWaypt::RunwayWaypt(RouteBase* aOwner) :
|
||||
Waypt(aOwner)
|
||||
{
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ void RunwayWaypt::writeToProperties(SGPropertyNode_ptr aProp) const
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Hold::Hold(const SGGeod& aPos, const string& aIdent, Route* aOwner) :
|
||||
Hold::Hold(const SGGeod& aPos, const string& aIdent, RouteBase* aOwner) :
|
||||
BasicWaypt(aPos, aIdent, aOwner),
|
||||
_righthanded(true),
|
||||
_isDistance(false)
|
||||
|
@ -247,7 +247,7 @@ Hold::Hold(const SGGeod& aPos, const string& aIdent, Route* aOwner) :
|
|||
setFlag(WPT_DYNAMIC);
|
||||
}
|
||||
|
||||
Hold::Hold(Route* aOwner) :
|
||||
Hold::Hold(RouteBase* aOwner) :
|
||||
BasicWaypt(aOwner),
|
||||
_righthanded(true),
|
||||
_isDistance(false)
|
||||
|
@ -308,7 +308,7 @@ void Hold::writeToProperties(SGPropertyNode_ptr aProp) const
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HeadingToAltitude::HeadingToAltitude(Route* aOwner, const string& aIdent,
|
||||
HeadingToAltitude::HeadingToAltitude(RouteBase* aOwner, const string& aIdent,
|
||||
double aMagHdg) :
|
||||
Waypt(aOwner),
|
||||
_ident(aIdent),
|
||||
|
@ -317,7 +317,7 @@ HeadingToAltitude::HeadingToAltitude(Route* aOwner, const string& aIdent,
|
|||
setFlag(WPT_DYNAMIC);
|
||||
}
|
||||
|
||||
HeadingToAltitude::HeadingToAltitude(Route* aOwner) :
|
||||
HeadingToAltitude::HeadingToAltitude(RouteBase* aOwner) :
|
||||
Waypt(aOwner)
|
||||
{
|
||||
}
|
||||
|
@ -343,7 +343,7 @@ void HeadingToAltitude::writeToProperties(SGPropertyNode_ptr aProp) const
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DMEIntercept::DMEIntercept(Route* aOwner, const string& aIdent, const SGGeod& aPos,
|
||||
DMEIntercept::DMEIntercept(RouteBase* aOwner, const string& aIdent, const SGGeod& aPos,
|
||||
double aCourseDeg, double aDistanceNm) :
|
||||
Waypt(aOwner),
|
||||
_ident(aIdent),
|
||||
|
@ -354,7 +354,7 @@ DMEIntercept::DMEIntercept(Route* aOwner, const string& aIdent, const SGGeod& aP
|
|||
setFlag(WPT_DYNAMIC);
|
||||
}
|
||||
|
||||
DMEIntercept::DMEIntercept(Route* aOwner) :
|
||||
DMEIntercept::DMEIntercept(RouteBase* aOwner) :
|
||||
Waypt(aOwner)
|
||||
{
|
||||
}
|
||||
|
@ -388,7 +388,7 @@ void DMEIntercept::writeToProperties(SGPropertyNode_ptr aProp) const
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RadialIntercept::RadialIntercept(Route* aOwner, const string& aIdent, const SGGeod& aPos,
|
||||
RadialIntercept::RadialIntercept(RouteBase* aOwner, const string& aIdent, const SGGeod& aPos,
|
||||
double aCourseDeg, double aRadial) :
|
||||
Waypt(aOwner),
|
||||
_ident(aIdent),
|
||||
|
@ -399,7 +399,7 @@ RadialIntercept::RadialIntercept(Route* aOwner, const string& aIdent, const SGGe
|
|||
setFlag(WPT_DYNAMIC);
|
||||
}
|
||||
|
||||
RadialIntercept::RadialIntercept(Route* aOwner) :
|
||||
RadialIntercept::RadialIntercept(RouteBase* aOwner) :
|
||||
Waypt(aOwner)
|
||||
{
|
||||
}
|
||||
|
@ -433,7 +433,7 @@ void RadialIntercept::writeToProperties(SGPropertyNode_ptr aProp) const
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ATCVectors::ATCVectors(Route* aOwner, FGAirport* aFacility) :
|
||||
ATCVectors::ATCVectors(RouteBase* aOwner, FGAirport* aFacility) :
|
||||
Waypt(aOwner),
|
||||
_facility(aFacility)
|
||||
{
|
||||
|
@ -444,7 +444,7 @@ ATCVectors::~ATCVectors()
|
|||
{
|
||||
}
|
||||
|
||||
ATCVectors::ATCVectors(Route* aOwner) :
|
||||
ATCVectors::ATCVectors(RouteBase* aOwner) :
|
||||
Waypt(aOwner)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -36,11 +36,11 @@ class BasicWaypt : public Waypt
|
|||
{
|
||||
public:
|
||||
|
||||
BasicWaypt(const SGGeod& aPos, const std::string& aIdent, Route* aOwner);
|
||||
BasicWaypt(const SGGeod& aPos, const std::string& aIdent, RouteBase* aOwner);
|
||||
|
||||
BasicWaypt(const SGWayPoint& aWP, Route* aOwner);
|
||||
BasicWaypt(const SGWayPoint& aWP, RouteBase* aOwner);
|
||||
|
||||
BasicWaypt(Route* aOwner);
|
||||
BasicWaypt(RouteBase* aOwner);
|
||||
|
||||
virtual SGGeod position() const
|
||||
{ return _pos; }
|
||||
|
@ -67,9 +67,9 @@ protected:
|
|||
class NavaidWaypoint : public Waypt
|
||||
{
|
||||
public:
|
||||
NavaidWaypoint(FGPositioned* aPos, Route* aOwner);
|
||||
NavaidWaypoint(FGPositioned* aPos, RouteBase* aOwner);
|
||||
|
||||
NavaidWaypoint(Route* aOwner);
|
||||
NavaidWaypoint(RouteBase* aOwner);
|
||||
|
||||
virtual SGGeod position() const;
|
||||
|
||||
|
@ -90,9 +90,9 @@ protected:
|
|||
class OffsetNavaidWaypoint : public NavaidWaypoint
|
||||
{
|
||||
public:
|
||||
OffsetNavaidWaypoint(FGPositioned* aPos, Route* aOwner, double aRadial, double aDistNm);
|
||||
OffsetNavaidWaypoint(FGPositioned* aPos, RouteBase* aOwner, double aRadial, double aDistNm);
|
||||
|
||||
OffsetNavaidWaypoint(Route* aOwner);
|
||||
OffsetNavaidWaypoint(RouteBase* aOwner);
|
||||
|
||||
virtual SGGeod position() const
|
||||
{ return _geod; }
|
||||
|
@ -120,9 +120,9 @@ private:
|
|||
class RunwayWaypt : public Waypt
|
||||
{
|
||||
public:
|
||||
RunwayWaypt(FGRunway* aPos, Route* aOwner);
|
||||
RunwayWaypt(FGRunway* aPos, RouteBase* aOwner);
|
||||
|
||||
RunwayWaypt(Route* aOwner);
|
||||
RunwayWaypt(RouteBase* aOwner);
|
||||
|
||||
virtual SGGeod position() const;
|
||||
|
||||
|
@ -148,9 +148,9 @@ private:
|
|||
class Hold : public BasicWaypt
|
||||
{
|
||||
public:
|
||||
Hold(const SGGeod& aPos, const std::string& aIdent, Route* aOwner);
|
||||
Hold(const SGGeod& aPos, const std::string& aIdent, RouteBase* aOwner);
|
||||
|
||||
Hold(Route* aOwner);
|
||||
Hold(RouteBase* aOwner);
|
||||
|
||||
void setHoldRadial(double aInboundRadial);
|
||||
void setHoldDistance(double aDistanceNm);
|
||||
|
@ -190,9 +190,9 @@ private:
|
|||
class HeadingToAltitude : public Waypt
|
||||
{
|
||||
public:
|
||||
HeadingToAltitude(Route* aOwner, const std::string& aIdent, double aMagHdg);
|
||||
HeadingToAltitude(RouteBase* aOwner, const std::string& aIdent, double aMagHdg);
|
||||
|
||||
HeadingToAltitude(Route* aOwner);
|
||||
HeadingToAltitude(RouteBase* aOwner);
|
||||
|
||||
virtual void initFromProperties(SGPropertyNode_ptr aProp);
|
||||
virtual void writeToProperties(SGPropertyNode_ptr aProp) const;
|
||||
|
@ -222,10 +222,10 @@ private:
|
|||
class DMEIntercept : public Waypt
|
||||
{
|
||||
public:
|
||||
DMEIntercept(Route* aOwner, const std::string& aIdent, const SGGeod& aPos,
|
||||
DMEIntercept(RouteBase* aOwner, const std::string& aIdent, const SGGeod& aPos,
|
||||
double aCourseDeg, double aDistanceNm);
|
||||
|
||||
DMEIntercept(Route* aOwner);
|
||||
DMEIntercept(RouteBase* aOwner);
|
||||
|
||||
virtual void initFromProperties(SGPropertyNode_ptr aProp);
|
||||
virtual void writeToProperties(SGPropertyNode_ptr aProp) const;
|
||||
|
@ -257,10 +257,10 @@ private:
|
|||
class RadialIntercept : public Waypt
|
||||
{
|
||||
public:
|
||||
RadialIntercept(Route* aOwner, const std::string& aIdent, const SGGeod& aPos,
|
||||
RadialIntercept(RouteBase* aOwner, const std::string& aIdent, const SGGeod& aPos,
|
||||
double aCourseDeg, double aRadialDeg);
|
||||
|
||||
RadialIntercept(Route* aOwner);
|
||||
RadialIntercept(RouteBase* aOwner);
|
||||
|
||||
virtual void initFromProperties(SGPropertyNode_ptr aProp);
|
||||
virtual void writeToProperties(SGPropertyNode_ptr aProp) const;
|
||||
|
@ -295,10 +295,10 @@ private:
|
|||
class ATCVectors : public Waypt
|
||||
{
|
||||
public:
|
||||
ATCVectors(Route* aOwner, FGAirport* aFacility);
|
||||
ATCVectors(RouteBase* aOwner, FGAirport* aFacility);
|
||||
virtual ~ATCVectors();
|
||||
|
||||
ATCVectors(Route* aOwner);
|
||||
ATCVectors(RouteBase* aOwner);
|
||||
|
||||
virtual void initFromProperties(SGPropertyNode_ptr aProp);
|
||||
virtual void writeToProperties(SGPropertyNode_ptr aProp) const;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "NasalPositioned.hxx"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
|
||||
#include <simgear/sg_inlines.h>
|
||||
#include <simgear/scene/material/mat.hxx>
|
||||
|
@ -48,8 +49,13 @@
|
|||
#include <Autopilot/route_mgr.hxx>
|
||||
#include <Navaids/procedure.hxx>
|
||||
|
||||
using namespace flightgear;
|
||||
|
||||
static void positionedGhostDestroy(void* g);
|
||||
static void wayptGhostDestroy(void* g);
|
||||
static void legGhostDestroy(void* g);
|
||||
static void routeBaseGhostDestroy(void* g);
|
||||
|
||||
naGhostType PositionedGhostType = { positionedGhostDestroy, "positioned" };
|
||||
|
||||
static const char* airportGhostGetMember(naContext c, void* g, naRef field, naRef* out);
|
||||
|
@ -62,12 +68,32 @@ static const char* runwayGhostGetMember(naContext c, void* g, naRef field, naRef
|
|||
naGhostType RunwayGhostType = { positionedGhostDestroy, "runway", runwayGhostGetMember, 0 };
|
||||
|
||||
static const char* wayptGhostGetMember(naContext c, void* g, naRef field, naRef* out);
|
||||
|
||||
naGhostType WayptGhostType = { wayptGhostDestroy,
|
||||
"waypoint",
|
||||
wayptGhostGetMember,
|
||||
0};
|
||||
|
||||
static const char* legGhostGetMember(naContext c, void* g, naRef field, naRef* out);
|
||||
naGhostType FPLegGhostType = { legGhostDestroy,
|
||||
"flightplan-leg",
|
||||
legGhostGetMember,
|
||||
0};
|
||||
|
||||
static const char* flightplanGhostGetMember(naContext c, void* g, naRef field, naRef* out);
|
||||
static void flightplanGhostSetMember(naContext c, void* g, naRef field, naRef value);
|
||||
|
||||
naGhostType FlightPlanGhostType = { routeBaseGhostDestroy,
|
||||
"flightplan",
|
||||
flightplanGhostGetMember,
|
||||
flightplanGhostSetMember
|
||||
};
|
||||
|
||||
static const char* procedureGhostGetMember(naContext c, void* g, naRef field, naRef* out);
|
||||
naGhostType ProcedureGhostType = { routeBaseGhostDestroy,
|
||||
"procedure",
|
||||
procedureGhostGetMember,
|
||||
0};
|
||||
|
||||
static void hashset(naContext c, naRef hash, const char* key, naRef val)
|
||||
{
|
||||
naRef s = naNewString(c);
|
||||
|
@ -117,24 +143,58 @@ static void positionedGhostDestroy(void* g)
|
|||
delete pos;
|
||||
}
|
||||
|
||||
static flightgear::Waypt* wayptGhost(naRef r)
|
||||
static Waypt* wayptGhost(naRef r)
|
||||
{
|
||||
if (naGhost_type(r) == &WayptGhostType)
|
||||
return (flightgear::Waypt*) naGhost_ptr(r);
|
||||
return (Waypt*) naGhost_ptr(r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wayptGhostDestroy(void* g)
|
||||
{
|
||||
flightgear::Waypt* wpt = (flightgear::Waypt*)g;
|
||||
if (!flightgear::Waypt::put(wpt)) // unref
|
||||
Waypt* wpt = (Waypt*)g;
|
||||
if (!Waypt::put(wpt)) // unref
|
||||
delete wpt;
|
||||
}
|
||||
|
||||
static void legGhostDestroy(void* g)
|
||||
{
|
||||
// nothing for now
|
||||
}
|
||||
|
||||
|
||||
static FlightPlan::Leg* fpLegGhost(naRef r)
|
||||
{
|
||||
if (naGhost_type(r) == &FPLegGhostType)
|
||||
return (FlightPlan::Leg*) naGhost_ptr(r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Procedure* procedureGhost(naRef r)
|
||||
{
|
||||
if (naGhost_type(r) == &ProcedureGhostType)
|
||||
return (Procedure*) naGhost_ptr(r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FlightPlan* flightplanGhost(naRef r)
|
||||
{
|
||||
if (naGhost_type(r) == &FlightPlanGhostType)
|
||||
return (FlightPlan*) naGhost_ptr(r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void routeBaseGhostDestroy(void* g)
|
||||
{
|
||||
// nothing for now
|
||||
}
|
||||
|
||||
static naRef airportPrototype;
|
||||
static naRef routePrototype;
|
||||
static naRef flightplanPrototype;
|
||||
static naRef waypointPrototype;
|
||||
static naRef geoCoordClass;
|
||||
static naRef fpLegPrototype;
|
||||
static naRef procedurePrototype;
|
||||
|
||||
naRef ghostForPositioned(naContext c, const FGPositioned* pos)
|
||||
{
|
||||
|
@ -176,16 +236,43 @@ naRef ghostForRunway(naContext c, const FGRunway* r)
|
|||
return naNewGhost2(c, &RunwayGhostType, (void*) r);
|
||||
}
|
||||
|
||||
naRef ghostForWaypt(naContext c, const flightgear::Waypt* wpt)
|
||||
naRef ghostForWaypt(naContext c, const Waypt* wpt)
|
||||
{
|
||||
if (!wpt) {
|
||||
return naNil();
|
||||
}
|
||||
|
||||
flightgear::Waypt::get(wpt); // take a ref
|
||||
Waypt::get(wpt); // take a ref
|
||||
return naNewGhost2(c, &WayptGhostType, (void*) wpt);
|
||||
}
|
||||
|
||||
naRef ghostForLeg(naContext c, const FlightPlan::Leg* leg)
|
||||
{
|
||||
if (!leg) {
|
||||
return naNil();
|
||||
}
|
||||
|
||||
return naNewGhost2(c, &FPLegGhostType, (void*) leg);
|
||||
}
|
||||
|
||||
naRef ghostForFlightPlan(naContext c, const FlightPlan* fp)
|
||||
{
|
||||
if (!fp) {
|
||||
return naNil();
|
||||
}
|
||||
|
||||
return naNewGhost2(c, &FlightPlanGhostType, (void*) fp);
|
||||
}
|
||||
|
||||
naRef ghostForProcedure(naContext c, const Procedure* proc)
|
||||
{
|
||||
if (!proc) {
|
||||
return naNil();
|
||||
}
|
||||
|
||||
return naNewGhost2(c, &ProcedureGhostType, (void*) proc);
|
||||
}
|
||||
|
||||
static const char* airportGhostGetMember(naContext c, void* g, naRef field, naRef* out)
|
||||
{
|
||||
const char* fieldName = naStr_data(field);
|
||||
|
@ -218,43 +305,299 @@ static const char* airportGhostGetMember(naContext c, void* g, naRef field, naRe
|
|||
return "";
|
||||
}
|
||||
|
||||
static const char* wayptGhostGetMember(naContext c, void* g, naRef field, naRef* out)
|
||||
static const char* waypointCommonGetMember(naContext c, Waypt* wpt, const char* fieldName, naRef* out)
|
||||
{
|
||||
const char* fieldName = naStr_data(field);
|
||||
flightgear::Waypt* wpt = (flightgear::Waypt*) g;
|
||||
|
||||
if (!strcmp(fieldName, "parents")) {
|
||||
*out = naNewVector(c);
|
||||
naVec_append(*out, waypointPrototype);
|
||||
} else if (!strcmp(fieldName, "wp_name")) *out =stringToNasal(c, wpt->ident());
|
||||
if (!strcmp(fieldName, "wp_name")) *out = stringToNasal(c, wpt->ident());
|
||||
else if (!strcmp(fieldName, "wp_type")) *out = stringToNasal(c, wpt->type());
|
||||
else if (!strcmp(fieldName, "wp_lat")) *out = naNum(wpt->position().getLatitudeDeg());
|
||||
else if (!strcmp(fieldName, "wp_lon")) *out = naNum(wpt->position().getLongitudeDeg());
|
||||
else if (!strcmp(fieldName, "wp_parent_name")) {
|
||||
flightgear::Procedure* proc = dynamic_cast<flightgear::Procedure*>(wpt->owner());
|
||||
Procedure* proc = dynamic_cast<Procedure*>(wpt->owner());
|
||||
*out = proc ? stringToNasal(c, proc->ident()) : naNil();
|
||||
} else if (!strcmp(fieldName, "wp_parent")) {
|
||||
Procedure* proc = dynamic_cast<Procedure*>(wpt->owner());
|
||||
*out = ghostForProcedure(c, proc);
|
||||
} else if (!strcmp(fieldName, "fly_type")) {
|
||||
if (wpt->type() == "hold") {
|
||||
*out = stringToNasal(c, "Hold");
|
||||
} else {
|
||||
*out = stringToNasal(c, wpt->flag(flightgear::WPT_OVERFLIGHT) ? "flyOver" : "flyBy");
|
||||
*out = stringToNasal(c, wpt->flag(WPT_OVERFLIGHT) ? "flyOver" : "flyBy");
|
||||
}
|
||||
} else if (!strcmp(fieldName, "alt_cstr")) *out = naNum(wpt->altitudeFt());
|
||||
else if (!strcmp(fieldName, "speed_cstr")) {
|
||||
double s = (wpt->speedRestriction() == flightgear::SPEED_RESTRICT_MACH)
|
||||
? wpt->speedMach() : wpt->speedKts();
|
||||
*out = naNum(s);
|
||||
} else if (!strcmp(fieldName, "leg_distance")) {
|
||||
return "please implement me";
|
||||
} else if (!strcmp(fieldName, "leg_bearing")) {
|
||||
return "please implement me";
|
||||
} else {
|
||||
return NULL; // member not found
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
static const char* wayptGhostGetMember(naContext c, void* g, naRef field, naRef* out)
|
||||
{
|
||||
const char* fieldName = naStr_data(field);
|
||||
Waypt* wpt = (flightgear::Waypt*) g;
|
||||
return waypointCommonGetMember(c, wpt, fieldName, out);
|
||||
}
|
||||
|
||||
static RouteRestriction routeRestrictionFromString(const char* s)
|
||||
{
|
||||
string u(s);
|
||||
boost::to_lower(u);
|
||||
if (u == "computed") return RESTRICT_COMPUTED;
|
||||
if (u == "at") return RESTRICT_AT;
|
||||
if (u == "mach") return SPEED_RESTRICT_MACH;
|
||||
if (u == "computed-mach") return SPEED_COMPUTED_MACH;
|
||||
if (u == "delete") return RESTRICT_DELETE;
|
||||
return RESTRICT_NONE;
|
||||
};
|
||||
|
||||
naRef routeRestrictionToNasal(naContext c, RouteRestriction rr)
|
||||
{
|
||||
switch (rr) {
|
||||
case RESTRICT_NONE: return naNil();
|
||||
case RESTRICT_AT: return stringToNasal(c, "at");
|
||||
case RESTRICT_ABOVE: return stringToNasal(c, "above");
|
||||
case RESTRICT_BELOW: return stringToNasal(c, "below");
|
||||
case SPEED_RESTRICT_MACH: return stringToNasal(c, "mach");
|
||||
case RESTRICT_COMPUTED: return stringToNasal(c, "computed");
|
||||
case SPEED_COMPUTED_MACH: return stringToNasal(c, "computed-mach");
|
||||
case RESTRICT_DELETE: return stringToNasal(c, "delete");
|
||||
}
|
||||
|
||||
return naNil();
|
||||
}
|
||||
|
||||
static const char* legGhostGetMember(naContext c, void* g, naRef field, naRef* out)
|
||||
{
|
||||
const char* fieldName = naStr_data(field);
|
||||
FlightPlan::Leg* leg = (FlightPlan::Leg*) g;
|
||||
Waypt* wpt = leg->waypoint();
|
||||
|
||||
if (!strcmp(fieldName, "parents")) {
|
||||
*out = naNewVector(c);
|
||||
naVec_append(*out, fpLegPrototype);
|
||||
} else if (!strcmp(fieldName, "alt_cstr")) {
|
||||
*out = naNum(leg->altitudeFt());
|
||||
} else if (!strcmp(fieldName, "alt_cstr_type")) {
|
||||
*out = routeRestrictionToNasal(c, leg->altitudeRestriction());
|
||||
} else if (!strcmp(fieldName, "speed_cstr")) {
|
||||
double s = isMachRestrict(leg->speedRestriction()) ? leg->speedMach() : leg->speedKts();
|
||||
*out = naNum(s);
|
||||
} else if (!strcmp(fieldName, "speed_cstr_type")) {
|
||||
*out = routeRestrictionToNasal(c, leg->speedRestriction());
|
||||
} else if (!strcmp(fieldName, "leg_distance")) {
|
||||
*out = naNum(leg->distanceNm());
|
||||
} else if (!strcmp(fieldName, "leg_bearing")) {
|
||||
*out = naNum(leg->courseDeg());
|
||||
} else if (!strcmp(fieldName, "distance_along_route")) {
|
||||
*out = naNum(leg->distanceAlongRoute());
|
||||
} else { // check for fields defined on the underlying waypoint
|
||||
return waypointCommonGetMember(c, wpt, fieldName, out);
|
||||
}
|
||||
|
||||
return ""; // success
|
||||
}
|
||||
|
||||
static const char* flightplanGhostGetMember(naContext c, void* g, naRef field, naRef* out)
|
||||
{
|
||||
const char* fieldName = naStr_data(field);
|
||||
FlightPlan* fp = (FlightPlan*) g;
|
||||
|
||||
if (!strcmp(fieldName, "parents")) {
|
||||
*out = naNewVector(c);
|
||||
naVec_append(*out, flightplanPrototype);
|
||||
} else if (!strcmp(fieldName, "id")) *out = stringToNasal(c, fp->ident());
|
||||
else if (!strcmp(fieldName, "departure")) *out = ghostForAirport(c, fp->departureAirport());
|
||||
else if (!strcmp(fieldName, "destination")) *out = ghostForAirport(c, fp->destinationAirport());
|
||||
else if (!strcmp(fieldName, "departure_runway")) *out = ghostForRunway(c, fp->departureRunway());
|
||||
else if (!strcmp(fieldName, "destination_runway")) *out = ghostForRunway(c, fp->destinationRunway());
|
||||
else if (!strcmp(fieldName, "sid")) *out = ghostForProcedure(c, fp->sid());
|
||||
else if (!strcmp(fieldName, "sid_trans")) *out = ghostForProcedure(c, fp->sidTransition());
|
||||
else if (!strcmp(fieldName, "star")) *out = ghostForProcedure(c, fp->star());
|
||||
else if (!strcmp(fieldName, "star_trans")) *out = ghostForProcedure(c, fp->starTransition());
|
||||
else if (!strcmp(fieldName, "approach")) *out = ghostForProcedure(c, fp->approach());
|
||||
else if (!strcmp(fieldName, "current")) *out = naNum(fp->currentIndex());
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
static void flightplanGhostSetMember(naContext c, void* g, naRef field, naRef value)
|
||||
{
|
||||
const char* fieldName = naStr_data(field);
|
||||
FlightPlan* fp = (FlightPlan*) g;
|
||||
|
||||
if (!strcmp(fieldName, "id")) {
|
||||
if (!naIsString(value)) naRuntimeError(c, "flightplan.id must be a string");
|
||||
fp->setIdent(naStr_data(value));
|
||||
} else if (!strcmp(fieldName, "current")) {
|
||||
int index = value.num;
|
||||
if ((index < 0) || (index >= fp->numLegs())) {
|
||||
return;
|
||||
}
|
||||
fp->setCurrentIndex(index);
|
||||
} else if (!strcmp(fieldName, "departure")) {
|
||||
FGAirport* apt = airportGhost(value);
|
||||
if (apt) {
|
||||
fp->setDeparture(apt);
|
||||
return;
|
||||
}
|
||||
|
||||
FGRunway* rwy = runwayGhost(value);
|
||||
if (rwy){
|
||||
fp->setDeparture(rwy);
|
||||
return;
|
||||
}
|
||||
|
||||
naRuntimeError(c, "bad argument type setting departure");
|
||||
} else if (!strcmp(fieldName, "destination")) {
|
||||
FGAirport* apt = airportGhost(value);
|
||||
if (apt) {
|
||||
fp->setDestination(apt);
|
||||
return;
|
||||
}
|
||||
|
||||
FGRunway* rwy = runwayGhost(value);
|
||||
if (rwy){
|
||||
fp->setDestination(rwy);
|
||||
return;
|
||||
}
|
||||
|
||||
naRuntimeError(c, "bad argument type setting destination");
|
||||
} else if (!strcmp(fieldName, "departure_runway")) {
|
||||
FGRunway* rwy = runwayGhost(value);
|
||||
if (rwy){
|
||||
fp->setDeparture(rwy);
|
||||
return;
|
||||
}
|
||||
|
||||
naRuntimeError(c, "bad argument type setting departure");
|
||||
} else if (!strcmp(fieldName, "destination_runway")) {
|
||||
FGRunway* rwy = runwayGhost(value);
|
||||
if (rwy){
|
||||
fp->setDestination(rwy);
|
||||
return;
|
||||
}
|
||||
|
||||
naRuntimeError(c, "bad argument type setting departure");
|
||||
} else if (!strcmp(fieldName, "sid")) {
|
||||
Procedure* proc = procedureGhost(value);
|
||||
if (proc && (proc->type() == PROCEDURE_SID)) {
|
||||
fp->setSID((SID*) proc);
|
||||
return;
|
||||
}
|
||||
// allow a SID transition to be set, implicitly include the SID itself
|
||||
if (proc && (proc->type() == PROCEDURE_TRANSITION)) {
|
||||
fp->setSID((Transition*) proc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (naIsString(value)) {
|
||||
FGAirport* apt = fp->departureAirport();
|
||||
fp->setSID(apt->findSIDWithIdent(naStr_data(value)));
|
||||
return;
|
||||
}
|
||||
|
||||
naRuntimeError(c, "bad argument type setting SID");
|
||||
} else if (!strcmp(fieldName, "star")) {
|
||||
Procedure* proc = procedureGhost(value);
|
||||
if (proc && (proc->type() == PROCEDURE_STAR)) {
|
||||
fp->setSTAR((STAR*) proc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (proc && (proc->type() == PROCEDURE_TRANSITION)) {
|
||||
fp->setSTAR((Transition*) proc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (naIsString(value)) {
|
||||
FGAirport* apt = fp->destinationAirport();
|
||||
fp->setSTAR(apt->findSTARWithIdent(naStr_data(value)));
|
||||
return;
|
||||
}
|
||||
|
||||
naRuntimeError(c, "bad argument type setting STAR");
|
||||
} else if (!strcmp(fieldName, "approach")) {
|
||||
Procedure* proc = procedureGhost(value);
|
||||
if (proc && Approach::isApproach(proc->type())) {
|
||||
fp->setApproach((Approach*) proc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (naIsString(value)) {
|
||||
FGAirport* apt = fp->destinationAirport();
|
||||
fp->setApproach(apt->findApproachWithIdent(naStr_data(value)));
|
||||
return;
|
||||
}
|
||||
|
||||
naRuntimeError(c, "bad argument type setting approach");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static naRef procedureTpType(naContext c, ProcedureType ty)
|
||||
{
|
||||
switch (ty) {
|
||||
case PROCEDURE_SID: return stringToNasal(c, "sid");
|
||||
case PROCEDURE_STAR: return stringToNasal(c, "star");
|
||||
case PROCEDURE_APPROACH_VOR:
|
||||
case PROCEDURE_APPROACH_ILS:
|
||||
case PROCEDURE_APPROACH_RNAV:
|
||||
case PROCEDURE_APPROACH_NDB:
|
||||
return stringToNasal(c, "IAP");
|
||||
default:
|
||||
return naNil();
|
||||
}
|
||||
}
|
||||
|
||||
static naRef procedureRadioType(naContext c, ProcedureType ty)
|
||||
{
|
||||
switch (ty) {
|
||||
case PROCEDURE_APPROACH_VOR: return stringToNasal(c, "VOR");
|
||||
case PROCEDURE_APPROACH_ILS: return stringToNasal(c, "ILS");
|
||||
case PROCEDURE_APPROACH_RNAV: return stringToNasal(c, "RNAV");
|
||||
case PROCEDURE_APPROACH_NDB: return stringToNasal(c, "NDB");
|
||||
default:
|
||||
return naNil();
|
||||
}
|
||||
}
|
||||
|
||||
static const char* procedureGhostGetMember(naContext c, void* g, naRef field, naRef* out)
|
||||
{
|
||||
const char* fieldName = naStr_data(field);
|
||||
Procedure* proc = (Procedure*) g;
|
||||
|
||||
if (!strcmp(fieldName, "parents")) {
|
||||
*out = naNewVector(c);
|
||||
naVec_append(*out, procedurePrototype);
|
||||
} else if (!strcmp(fieldName, "id")) *out = stringToNasal(c, proc->ident());
|
||||
else if (!strcmp(fieldName, "airport")) *out = ghostForAirport(c, proc->airport());
|
||||
else if (!strcmp(fieldName, "tp_type")) *out = procedureTpType(c, proc->type());
|
||||
else if (!strcmp(fieldName, "radio")) *out = procedureRadioType(c, proc->type());
|
||||
else if (!strcmp(fieldName, "runways")) {
|
||||
*out = naNewVector(c);
|
||||
BOOST_FOREACH(FGRunwayPtr rwy, proc->runways()) {
|
||||
naVec_append(*out, stringToNasal(c, rwy->ident()));
|
||||
}
|
||||
} else if (!strcmp(fieldName, "transitions")) {
|
||||
if ((proc->type() != PROCEDURE_SID) && (proc->type() != PROCEDURE_STAR)) {
|
||||
*out = naNil();
|
||||
return "";
|
||||
}
|
||||
|
||||
ArrivalDeparture* ad = static_cast<ArrivalDeparture*>(proc);
|
||||
*out = naNewVector(c);
|
||||
BOOST_FOREACH(string id, ad->transitionIdents()) {
|
||||
naVec_append(*out, stringToNasal(c, id));
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
static const char* runwayGhostGetMember(naContext c, void* g, naRef field, naRef* out)
|
||||
{
|
||||
const char* fieldName = naStr_data(field);
|
||||
|
@ -664,6 +1007,7 @@ static naRef f_airport_runway(naContext c, naRef me, int argc, naRef* args)
|
|||
}
|
||||
|
||||
std::string ident(naStr_data(args[0]));
|
||||
boost::to_upper(ident);
|
||||
if (!apt->hasRunwayWithIdent(ident)) {
|
||||
return naNil();
|
||||
}
|
||||
|
@ -680,12 +1024,18 @@ static naRef f_airport_sids(naContext c, naRef me, int argc, naRef* args)
|
|||
|
||||
naRef sids = naNewVector(c);
|
||||
|
||||
FGRunway* rwy = NULL;
|
||||
if (argc > 0 && naIsString(args[0])) {
|
||||
if (!apt->hasRunwayWithIdent(naStr_data(args[0]))) {
|
||||
return naNil();
|
||||
}
|
||||
|
||||
FGRunway* rwy = apt->getRunwayByIdent(naStr_data(args[0]));
|
||||
rwy = apt->getRunwayByIdent(naStr_data(args[0]));
|
||||
} else if (argc > 0) {
|
||||
rwy = runwayGhost(args[0]);
|
||||
}
|
||||
|
||||
if (rwy) {
|
||||
BOOST_FOREACH(flightgear::SID* sid, rwy->getSIDs()) {
|
||||
naRef procId = stringToNasal(c, sid->ident());
|
||||
naVec_append(sids, procId);
|
||||
|
@ -710,12 +1060,18 @@ static naRef f_airport_stars(naContext c, naRef me, int argc, naRef* args)
|
|||
|
||||
naRef stars = naNewVector(c);
|
||||
|
||||
FGRunway* rwy = NULL;
|
||||
if (argc > 0 && naIsString(args[0])) {
|
||||
if (!apt->hasRunwayWithIdent(naStr_data(args[0]))) {
|
||||
return naNil();
|
||||
}
|
||||
|
||||
FGRunway* rwy = apt->getRunwayByIdent(naStr_data(args[0]));
|
||||
rwy = apt->getRunwayByIdent(naStr_data(args[0]));
|
||||
} else if (argc > 0) {
|
||||
rwy = runwayGhost(args[0]);
|
||||
}
|
||||
|
||||
if (rwy) {
|
||||
BOOST_FOREACH(flightgear::STAR* s, rwy->getSTARs()) {
|
||||
naRef procId = stringToNasal(c, s->ident());
|
||||
naVec_append(stars, procId);
|
||||
|
@ -731,6 +1087,61 @@ static naRef f_airport_stars(naContext c, naRef me, int argc, naRef* args)
|
|||
return stars;
|
||||
}
|
||||
|
||||
static naRef f_airport_approaches(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FGAirport* apt = airportGhost(me);
|
||||
if (!apt) {
|
||||
naRuntimeError(c, "airport.getApproachList called on non-airport object");
|
||||
}
|
||||
|
||||
naRef approaches = naNewVector(c);
|
||||
|
||||
ProcedureType ty = PROCEDURE_INVALID;
|
||||
if ((argc > 1) && naIsString(args[1])) {
|
||||
std::string u(naStr_data(args[1]));
|
||||
boost::to_upper(u);
|
||||
if (u == "NDB") ty = PROCEDURE_APPROACH_NDB;
|
||||
if (u == "VOR") ty = PROCEDURE_APPROACH_VOR;
|
||||
if (u == "ILS") ty = PROCEDURE_APPROACH_ILS;
|
||||
if (u == "RNAV") ty = PROCEDURE_APPROACH_RNAV;
|
||||
}
|
||||
|
||||
FGRunway* rwy = NULL;
|
||||
if (argc > 0 && (rwy = runwayGhost(args[0]))) {
|
||||
// ok
|
||||
} else if (argc > 0 && naIsString(args[0])) {
|
||||
if (!apt->hasRunwayWithIdent(naStr_data(args[0]))) {
|
||||
return naNil();
|
||||
}
|
||||
|
||||
rwy = apt->getRunwayByIdent(naStr_data(args[0]));
|
||||
}
|
||||
|
||||
if (rwy) {
|
||||
BOOST_FOREACH(Approach* s, rwy->getApproaches()) {
|
||||
if ((ty != PROCEDURE_INVALID) && (s->type() != ty)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
naRef procId = stringToNasal(c, s->ident());
|
||||
naVec_append(approaches, procId);
|
||||
}
|
||||
} else {
|
||||
// no runway specified, report them all
|
||||
for (unsigned int s=0; s<apt->numApproaches(); ++s) {
|
||||
Approach* app = apt->getApproachByIndex(s);
|
||||
if ((ty != PROCEDURE_INVALID) && (app->type() != ty)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
naRef procId = stringToNasal(c, app->ident());
|
||||
naVec_append(approaches, procId);
|
||||
}
|
||||
}
|
||||
|
||||
return approaches;
|
||||
}
|
||||
|
||||
static naRef f_airport_parking(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FGAirport* apt = airportGhost(me);
|
||||
|
@ -769,6 +1180,51 @@ static naRef f_airport_parking(naContext c, naRef me, int argc, naRef* args)
|
|||
return r;
|
||||
}
|
||||
|
||||
static naRef f_airport_getSid(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FGAirport* apt = airportGhost(me);
|
||||
if (!apt) {
|
||||
naRuntimeError(c, "airport.getSid called on non-airport object");
|
||||
}
|
||||
|
||||
if ((argc != 1) || !naIsString(args[0])) {
|
||||
naRuntimeError(c, "airport.getSid passed invalid argument");
|
||||
}
|
||||
|
||||
string ident = naStr_data(args[0]);
|
||||
return ghostForProcedure(c, apt->findSIDWithIdent(ident));
|
||||
}
|
||||
|
||||
static naRef f_airport_getStar(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FGAirport* apt = airportGhost(me);
|
||||
if (!apt) {
|
||||
naRuntimeError(c, "airport.getStar called on non-airport object");
|
||||
}
|
||||
|
||||
if ((argc != 1) || !naIsString(args[0])) {
|
||||
naRuntimeError(c, "airport.getStar passed invalid argument");
|
||||
}
|
||||
|
||||
string ident = naStr_data(args[0]);
|
||||
return ghostForProcedure(c, apt->findSTARWithIdent(ident));
|
||||
}
|
||||
|
||||
static naRef f_airport_getApproach(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FGAirport* apt = airportGhost(me);
|
||||
if (!apt) {
|
||||
naRuntimeError(c, "airport.getIAP called on non-airport object");
|
||||
}
|
||||
|
||||
if ((argc != 1) || !naIsString(args[0])) {
|
||||
naRuntimeError(c, "airport.getIAP passed invalid argument");
|
||||
}
|
||||
|
||||
string ident = naStr_data(args[0]);
|
||||
return ghostForProcedure(c, apt->findApproachWithIdent(ident));
|
||||
}
|
||||
|
||||
// Returns vector of data hash for navaid of a <type>, nil on error
|
||||
// navaids sorted by ascending distance
|
||||
// navinfo([<lat>,<lon>],[<type>],[<id>])
|
||||
|
@ -1030,62 +1486,233 @@ static naRef f_tileIndex(naContext c, naRef me, int argc, naRef* args)
|
|||
|
||||
static naRef f_route(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
naRef route = naNewHash(c);
|
||||
if (argc == 0) {
|
||||
FGRouteMgr* rm = static_cast<FGRouteMgr*>(globals->get_subsystem("route-manager"));
|
||||
return ghostForFlightPlan(c, rm->flightPlan());
|
||||
}
|
||||
|
||||
// return active route hash by default,
|
||||
// other routes in the future
|
||||
if ((argc > 0) && naIsString(args[0])) {
|
||||
flightgear::FlightPlan* fp = new flightgear::FlightPlan;
|
||||
SGPath path(naStr_data(args[0]));
|
||||
if (!path.exists()) {
|
||||
naRuntimeError(c, "flightplan, no file at path %s", path.c_str());
|
||||
}
|
||||
|
||||
if (!fp->load(path)) {
|
||||
SG_LOG(SG_NASAL, SG_WARN, "failed to load flight-plan from " << path);
|
||||
delete fp;
|
||||
return naNil();
|
||||
}
|
||||
|
||||
return ghostForFlightPlan(c, fp);
|
||||
}
|
||||
|
||||
naRef parents = naNewVector(c);
|
||||
naVec_append(parents, routePrototype);
|
||||
hashset(c, route, "parents", parents);
|
||||
|
||||
return route;
|
||||
naRuntimeError(c, "bad arguments to flightplan()");
|
||||
return naNil();
|
||||
}
|
||||
|
||||
static naRef f_route_getWP(naContext c, naRef me, int argc, naRef* args)
|
||||
static naRef f_flightplan_getWP(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FGRouteMgr* rm = static_cast<FGRouteMgr*>(globals->get_subsystem("route-manager"));
|
||||
|
||||
FlightPlan* fp = flightplanGhost(me);
|
||||
if (!fp) {
|
||||
naRuntimeError(c, "flightplan.getWP called on non-flightplan object");
|
||||
}
|
||||
|
||||
int index;
|
||||
if (argc == 0) {
|
||||
index = rm->currentIndex();
|
||||
index = fp->currentIndex();
|
||||
} else {
|
||||
index = (int) naNumValue(args[0]).num;
|
||||
}
|
||||
|
||||
if ((index < 0) || (index >= rm->numWaypts())) {
|
||||
if ((index < 0) || (index >= fp->numLegs())) {
|
||||
return naNil();
|
||||
}
|
||||
|
||||
return ghostForWaypt(c, rm->wayptAtIndex(index));
|
||||
return ghostForLeg(c, fp->legAtIndex(index));
|
||||
}
|
||||
|
||||
static naRef f_route_currentWP(naContext c, naRef me, int argc, naRef* args)
|
||||
static naRef f_flightplan_currentWP(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FGRouteMgr* rm = static_cast<FGRouteMgr*>(globals->get_subsystem("route-manager"));
|
||||
return ghostForWaypt(c, rm->currentWaypt());
|
||||
}
|
||||
|
||||
static naRef f_route_nextWP(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FGRouteMgr* rm = static_cast<FGRouteMgr*>(globals->get_subsystem("route-manager"));
|
||||
flightgear::WayptRef wp = rm->nextWaypt();
|
||||
if (!wp) {
|
||||
return naNil();
|
||||
FlightPlan* fp = flightplanGhost(me);
|
||||
if (!fp) {
|
||||
naRuntimeError(c, "flightplan.currentWP called on non-flightplan object");
|
||||
}
|
||||
return ghostForWaypt(c, wp);
|
||||
return ghostForLeg(c, fp->currentLeg());
|
||||
}
|
||||
|
||||
static naRef f_route_currentIndex(naContext c, naRef me, int argc, naRef* args)
|
||||
static naRef f_flightplan_nextWP(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FGRouteMgr* rm = static_cast<FGRouteMgr*>(globals->get_subsystem("route-manager"));
|
||||
return naNum(rm->currentIndex());
|
||||
FlightPlan* fp = flightplanGhost(me);
|
||||
if (!fp) {
|
||||
naRuntimeError(c, "flightplan.nextWP called on non-flightplan object");
|
||||
}
|
||||
return ghostForLeg(c, fp->nextLeg());
|
||||
}
|
||||
|
||||
static naRef f_route_numWaypoints(naContext c, naRef me, int argc, naRef* args)
|
||||
static naRef f_flightplan_numWaypoints(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FGRouteMgr* rm = static_cast<FGRouteMgr*>(globals->get_subsystem("route-manager"));
|
||||
return naNum(rm->numWaypts());
|
||||
FlightPlan* fp = flightplanGhost(me);
|
||||
if (!fp) {
|
||||
naRuntimeError(c, "flightplan.numWaypoints called on non-flightplan object");
|
||||
}
|
||||
return naNum(fp->numLegs());
|
||||
}
|
||||
|
||||
static naRef f_flightplan_appendWP(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FlightPlan* fp = flightplanGhost(me);
|
||||
if (!fp) {
|
||||
naRuntimeError(c, "flightplan.appendWP called on non-flightplan object");
|
||||
}
|
||||
|
||||
WayptRef wp = wayptGhost(args[0]);
|
||||
int index = fp->numLegs();
|
||||
fp->insertWayptAtIndex(wp.get(), index);
|
||||
return naNum(index);
|
||||
}
|
||||
|
||||
static naRef f_flightplan_insertWP(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FlightPlan* fp = flightplanGhost(me);
|
||||
if (!fp) {
|
||||
naRuntimeError(c, "flightplan.insertWP called on non-flightplan object");
|
||||
}
|
||||
|
||||
WayptRef wp = wayptGhost(args[0]);
|
||||
int index = -1; // append
|
||||
if ((argc > 1) && naIsNum(args[1])) {
|
||||
index = (int) args[1].num;
|
||||
}
|
||||
|
||||
fp->insertWayptAtIndex(wp.get(), index);
|
||||
return naNil();
|
||||
}
|
||||
|
||||
static naRef f_flightplan_insertWPAfter(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FlightPlan* fp = flightplanGhost(me);
|
||||
if (!fp) {
|
||||
naRuntimeError(c, "flightplan.insertWPAfter called on non-flightplan object");
|
||||
}
|
||||
|
||||
WayptRef wp = wayptGhost(args[0]);
|
||||
int index = -1; // append
|
||||
if ((argc > 1) && naIsNum(args[1])) {
|
||||
index = (int) args[1].num;
|
||||
}
|
||||
|
||||
fp->insertWayptAtIndex(wp.get(), index + 1);
|
||||
return naNil();
|
||||
}
|
||||
|
||||
static naRef f_flightplan_insertWaypoints(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FlightPlan* fp = flightplanGhost(me);
|
||||
if (!fp) {
|
||||
naRuntimeError(c, "flightplan.insertWaypoints called on non-flightplan object");
|
||||
}
|
||||
|
||||
WayptVec wps;
|
||||
if (!naIsVector(args[0])) {
|
||||
naRuntimeError(c, "flightplan.insertWaypoints expects vector as first arg");
|
||||
}
|
||||
|
||||
int count = naVec_size(args[0]);
|
||||
for (int i=0; i<count; ++i) {
|
||||
Waypt* wp = wayptGhost(naVec_get(args[0], i));
|
||||
if (wp) {
|
||||
wps.push_back(wp);
|
||||
}
|
||||
}
|
||||
|
||||
int index = -1; // append
|
||||
if ((argc > 1) && naIsNum(args[1])) {
|
||||
index = (int) args[1].num;
|
||||
}
|
||||
|
||||
fp->insertWayptsAtIndex(wps, index);
|
||||
return naNil();
|
||||
}
|
||||
|
||||
static naRef f_flightplan_clearPlan(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FlightPlan* fp = flightplanGhost(me);
|
||||
if (!fp) {
|
||||
naRuntimeError(c, "flightplan.clearPlan called on non-flightplan object");
|
||||
}
|
||||
|
||||
fp->clear();
|
||||
return naNil();
|
||||
}
|
||||
|
||||
static WayptFlag wayptFlagFromString(const char* s)
|
||||
{
|
||||
if (!strcmp(s, "sid")) return WPT_DEPARTURE;
|
||||
if (!strcmp(s, "star")) return WPT_ARRIVAL;
|
||||
if (!strcmp(s, "approach")) return WPT_APPROACH;
|
||||
if (!strcmp(s, "missed")) return WPT_MISS;
|
||||
if (!strcmp(s, "pseudo")) return WPT_PSEUDO;
|
||||
|
||||
return (WayptFlag) 0;
|
||||
}
|
||||
|
||||
static naRef f_flightplan_clearWPType(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FlightPlan* fp = flightplanGhost(me);
|
||||
if (!fp) {
|
||||
naRuntimeError(c, "flightplan.clearWPType called on non-flightplan object");
|
||||
}
|
||||
|
||||
if (argc < 1) {
|
||||
naRuntimeError(c, "insufficent args to flightplan.clearWPType");
|
||||
}
|
||||
|
||||
WayptFlag flag = wayptFlagFromString(naStr_data(args[0]));
|
||||
fp->clearWayptsWithFlag(flag);
|
||||
return naNil();
|
||||
}
|
||||
|
||||
static naRef f_flightplan_clone(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FlightPlan* fp = flightplanGhost(me);
|
||||
if (!fp) {
|
||||
naRuntimeError(c, "flightplan.clone called on non-flightplan object");
|
||||
}
|
||||
|
||||
return ghostForFlightPlan(c, fp->clone());
|
||||
}
|
||||
|
||||
static naRef f_leg_setSpeed(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FlightPlan::Leg* leg = fpLegGhost(me);
|
||||
if (!leg) {
|
||||
naRuntimeError(c, "leg.setSpeed called on non-flightplan-leg object");
|
||||
}
|
||||
|
||||
if (argc < 2) {
|
||||
naRuntimeError(c, "bad arguments to leg.setSpeed");
|
||||
}
|
||||
|
||||
RouteRestriction rr = routeRestrictionFromString(naStr_data(args[1]));
|
||||
leg->setSpeed(rr, args[0].num);
|
||||
return naNil();
|
||||
}
|
||||
|
||||
static naRef f_leg_setAltitude(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FlightPlan::Leg* leg = fpLegGhost(me);
|
||||
if (!leg) {
|
||||
naRuntimeError(c, "leg.setAltitude called on non-flightplan-leg object");
|
||||
}
|
||||
|
||||
if (argc < 2) {
|
||||
naRuntimeError(c, "bad arguments to leg.setAltitude");
|
||||
}
|
||||
|
||||
RouteRestriction rr = routeRestrictionFromString(naStr_data(args[1]));
|
||||
leg->setAltitude(rr, args[0].num);
|
||||
return naNil();
|
||||
}
|
||||
|
||||
static naRef f_waypoint_navaid(naContext c, naRef me, int argc, naRef* args)
|
||||
|
@ -1147,6 +1774,23 @@ static naRef f_waypoint_runway(naContext c, naRef me, int argc, naRef* args)
|
|||
return ghostForRunway(c, (FGRunway*) pos);
|
||||
}
|
||||
|
||||
static naRef f_procedure_transition(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
Procedure* proc = procedureGhost(me);
|
||||
if (!proc) {
|
||||
naRuntimeError(c, "procedure.transition called on non-procedure object");
|
||||
}
|
||||
|
||||
if ((proc->type() != PROCEDURE_SID) && (proc->type() != PROCEDURE_STAR)) {
|
||||
naRuntimeError(c, "procedure.transition called on non-SID or -STAR");
|
||||
}
|
||||
|
||||
ArrivalDeparture* ad = (ArrivalDeparture*) proc;
|
||||
Transition* trans = ad->findTransitionByName(naStr_data(args[0]));
|
||||
|
||||
return ghostForProcedure(c, trans);
|
||||
}
|
||||
|
||||
// Table of extension functions. Terminate with zeros.
|
||||
static struct { const char* name; naCFunction func; } funcs[] = {
|
||||
{ "carttogeod", f_carttogeod },
|
||||
|
@ -1160,7 +1804,7 @@ static struct { const char* name; naCFunction func; } funcs[] = {
|
|||
{ "findNavaidByFrequency", f_findNavaidByFrequency },
|
||||
{ "findNavaidsByFrequency", f_findNavaidsByFrequency },
|
||||
{ "findNavaidsByID", f_findNavaidsByIdent },
|
||||
{ "route", f_route },
|
||||
{ "flightplan", f_route },
|
||||
{ "magvar", f_magvar },
|
||||
{ "courseAndDistance", f_courseAndDistance },
|
||||
{ "greatCircleMove", f_greatCircleMove },
|
||||
|
@ -1180,17 +1824,27 @@ naRef initNasalPositioned(naRef globals, naContext c, naRef gcSave)
|
|||
hashset(c, airportPrototype, "comms", naNewFunc(c, naNewCCode(c, f_airport_comms)));
|
||||
hashset(c, airportPrototype, "sids", naNewFunc(c, naNewCCode(c, f_airport_sids)));
|
||||
hashset(c, airportPrototype, "stars", naNewFunc(c, naNewCCode(c, f_airport_stars)));
|
||||
hashset(c, airportPrototype, "getApproachList", naNewFunc(c, naNewCCode(c, f_airport_approaches)));
|
||||
hashset(c, airportPrototype, "parking", naNewFunc(c, naNewCCode(c, f_airport_parking)));
|
||||
hashset(c, airportPrototype, "getSid", naNewFunc(c, naNewCCode(c, f_airport_getSid)));
|
||||
hashset(c, airportPrototype, "getStar", naNewFunc(c, naNewCCode(c, f_airport_getStar)));
|
||||
hashset(c, airportPrototype, "getIAP", naNewFunc(c, naNewCCode(c, f_airport_getApproach)));
|
||||
|
||||
routePrototype = naNewHash(c);
|
||||
hashset(c, gcSave, "routeProto", routePrototype);
|
||||
flightplanPrototype = naNewHash(c);
|
||||
hashset(c, gcSave, "flightplanProto", flightplanPrototype);
|
||||
|
||||
hashset(c, routePrototype, "getWP", naNewFunc(c, naNewCCode(c, f_route_getWP)));
|
||||
hashset(c, routePrototype, "currentWP", naNewFunc(c, naNewCCode(c, f_route_currentWP)));
|
||||
hashset(c, routePrototype, "nextWP", naNewFunc(c, naNewCCode(c, f_route_nextWP)));
|
||||
hashset(c, routePrototype, "currentIndex", naNewFunc(c, naNewCCode(c, f_route_currentIndex)));
|
||||
hashset(c, routePrototype, "getPlanSize", naNewFunc(c, naNewCCode(c, f_route_numWaypoints)));
|
||||
|
||||
hashset(c, flightplanPrototype, "getWP", naNewFunc(c, naNewCCode(c, f_flightplan_getWP)));
|
||||
hashset(c, flightplanPrototype, "currentWP", naNewFunc(c, naNewCCode(c, f_flightplan_currentWP)));
|
||||
hashset(c, flightplanPrototype, "nextWP", naNewFunc(c, naNewCCode(c, f_flightplan_nextWP)));
|
||||
hashset(c, flightplanPrototype, "getPlanSize", naNewFunc(c, naNewCCode(c, f_flightplan_numWaypoints)));
|
||||
hashset(c, flightplanPrototype, "appendWP", naNewFunc(c, naNewCCode(c, f_flightplan_appendWP)));
|
||||
hashset(c, flightplanPrototype, "insertWP", naNewFunc(c, naNewCCode(c, f_flightplan_insertWP)));
|
||||
hashset(c, flightplanPrototype, "insertWPAfter", naNewFunc(c, naNewCCode(c, f_flightplan_insertWPAfter)));
|
||||
hashset(c, flightplanPrototype, "insertWaypoints", naNewFunc(c, naNewCCode(c, f_flightplan_insertWaypoints)));
|
||||
hashset(c, flightplanPrototype, "cleanPlan", naNewFunc(c, naNewCCode(c, f_flightplan_clearPlan)));
|
||||
hashset(c, flightplanPrototype, "clearWPType", naNewFunc(c, naNewCCode(c, f_flightplan_clearWPType)));
|
||||
hashset(c, flightplanPrototype, "clone", naNewFunc(c, naNewCCode(c, f_flightplan_clone)));
|
||||
|
||||
waypointPrototype = naNewHash(c);
|
||||
hashset(c, gcSave, "wayptProto", waypointPrototype);
|
||||
|
||||
|
@ -1198,6 +1852,17 @@ naRef initNasalPositioned(naRef globals, naContext c, naRef gcSave)
|
|||
hashset(c, waypointPrototype, "runway", naNewFunc(c, naNewCCode(c, f_waypoint_runway)));
|
||||
hashset(c, waypointPrototype, "airport", naNewFunc(c, naNewCCode(c, f_waypoint_airport)));
|
||||
|
||||
procedurePrototype = naNewHash(c);
|
||||
hashset(c, gcSave, "procedureProto", procedurePrototype);
|
||||
// hashset(c, procedurePrototype, "runwayTransition", naNewFunc(c, naNewCCode(c, f_procedure_runwayTransition)));
|
||||
hashset(c, procedurePrototype, "transition", naNewFunc(c, naNewCCode(c, f_procedure_transition)));
|
||||
// hashset(c, procedurePrototype, "buildPath", naNewFunc(c, naNewCCode(c, f_procedure_build)));
|
||||
|
||||
fpLegPrototype = naNewHash(c);
|
||||
hashset(c, gcSave, "fpLegProto", fpLegPrototype);
|
||||
hashset(c, fpLegPrototype, "setSpeed", naNewFunc(c, naNewCCode(c, f_leg_setSpeed)));
|
||||
hashset(c, fpLegPrototype, "setAltitude", naNewFunc(c, naNewCCode(c, f_leg_setAltitude)));
|
||||
|
||||
for(int i=0; funcs[i].name; i++) {
|
||||
hashset(c, globals, funcs[i].name,
|
||||
naNewFunc(c, naNewCCode(c, funcs[i].func)));
|
||||
|
|
Loading…
Reference in a new issue