#include "airport.hxx"
+#include <algorithm>
#include <cassert>
#include <boost/foreach.hpp>
#include <Navaids/waypoint.hxx>
#include <ATC/CommStation.hxx>
#include <Navaids/NavDataCache.hxx>
+#include <Navaids/navrecord.hxx>
using std::vector;
using std::pair;
using namespace flightgear;
-
/***************************************************************************
* FGAirport
***************************************************************************/
AirportCache FGAirport::airportCache;
-FGAirport::FGAirport(PositionedID aGuid, const string &id, const SGGeod& location,
- const string &name, bool has_metar, Type aType) :
+FGAirport::FGAirport( PositionedID aGuid,
+ const std::string &id,
+ const SGGeod& location,
+ const std::string &name,
+ bool has_metar,
+ Type aType ):
FGPositioned(aGuid, aType, id, location),
_name(name),
_has_metar(has_metar),
_dynamics(0),
mTowerDataLoaded(false),
mRunwaysLoaded(false),
+ mHelipadsLoaded(false),
mTaxiwaysLoaded(false),
mProceduresLoaded(false),
+ mThresholdDataLoaded(false),
mILSDataLoaded(false)
{
}
return _dynamics;
}
+//------------------------------------------------------------------------------
unsigned int FGAirport::numRunways() const
{
loadRunways();
return mRunways.size();
}
+//------------------------------------------------------------------------------
unsigned int FGAirport::numHelipads() const
{
loadHelipads();
return mHelipads.size();
}
-FGRunway* FGAirport::getRunwayByIndex(unsigned int aIndex) const
+//------------------------------------------------------------------------------
+FGRunwayRef FGAirport::getRunwayByIndex(unsigned int aIndex) const
{
loadRunways();
-
- assert(aIndex >= 0 && aIndex < mRunways.size());
- return (FGRunway*) flightgear::NavDataCache::instance()->loadById(mRunways[aIndex]);
+ return mRunways.at(aIndex);
}
-FGHelipad* FGAirport::getHelipadByIndex(unsigned int aIndex) const
+//------------------------------------------------------------------------------
+FGHelipadRef FGAirport::getHelipadByIndex(unsigned int aIndex) const
{
loadHelipads();
+ return loadById<FGHelipad>(mHelipads, aIndex);
+}
+
+//------------------------------------------------------------------------------
+FGRunwayMap FGAirport::getRunwayMap() const
+{
+ loadRunways();
+ FGRunwayMap map;
- assert(aIndex >= 0 && aIndex < mHelipads.size());
- return (FGHelipad*) flightgear::NavDataCache::instance()->loadById(mHelipads[aIndex]);
+ double minLengthFt = fgGetDouble("/sim/navdb/min-runway-length-ft");
+
+ BOOST_FOREACH(FGRunwayRef rwy, mRunways)
+ {
+ // ignore unusably short runways
+ // TODO other methods don't check this...
+ if( rwy->lengthFt() >= minLengthFt )
+ map[ rwy->ident() ] = rwy;
+ }
+
+ return map;
}
-bool FGAirport::hasRunwayWithIdent(const string& aIdent) const
+//------------------------------------------------------------------------------
+FGHelipadMap FGAirport::getHelipadMap() const
{
- return flightgear::NavDataCache::instance()->airportItemWithIdent(guid(), FGPositioned::RUNWAY, aIdent) != 0;
+ loadHelipads();
+ FGHelipadMap map;
+
+ BOOST_FOREACH(PositionedID id, mHelipads)
+ {
+ FGHelipad* rwy = loadById<FGHelipad>(id);
+ map[ rwy->ident() ] = rwy;
+ }
+
+ return map;
}
-bool FGAirport::hasHelipadWithIdent(const string& aIdent) const
+//------------------------------------------------------------------------------
+bool FGAirport::hasRunwayWithIdent(const std::string& aIdent) const
{
- return flightgear::NavDataCache::instance()->airportItemWithIdent(guid(), FGPositioned::HELIPAD, aIdent) != 0;
+ loadRunways();
+ BOOST_FOREACH(FGRunwayRef rwy, mRunways) {
+ if (rwy->ident() == aIdent) {
+ return true;
+ }
+ }
+
+ return false;
}
-FGRunway* FGAirport::getRunwayByIdent(const string& aIdent) const
+//------------------------------------------------------------------------------
+bool FGAirport::hasHelipadWithIdent(const std::string& aIdent) const
{
- PositionedID id = flightgear::NavDataCache::instance()->airportItemWithIdent(guid(), FGPositioned::RUNWAY, aIdent);
- if (id == 0) {
- SG_LOG(SG_GENERAL, SG_ALERT, "no such runway '" << aIdent << "' at airport " << ident());
- throw sg_range_exception("unknown runway " + aIdent + " at airport:" + ident(), "FGAirport::getRunwayByIdent");
+ return flightgear::NavDataCache::instance()
+ ->airportItemWithIdent(guid(), FGPositioned::HELIPAD, aIdent) != 0;
+}
+
+//------------------------------------------------------------------------------
+FGRunwayRef FGAirport::getRunwayByIdent(const std::string& aIdent) const
+{
+ loadRunways();
+ BOOST_FOREACH(FGRunwayRef rwy, mRunways) {
+ if (rwy->ident() == aIdent) {
+ return rwy;
+ }
}
- return (FGRunway*) flightgear::NavDataCache::instance()->loadById(id);
+ SG_LOG(SG_GENERAL, SG_ALERT, "no such runway '" << aIdent << "' at airport " << ident());
+ throw sg_range_exception("unknown runway " + aIdent + " at airport:" + ident(), "FGAirport::getRunwayByIdent");
}
-FGHelipad* FGAirport::getHelipadByIdent(const string& aIdent) const
+//------------------------------------------------------------------------------
+FGHelipadRef FGAirport::getHelipadByIdent(const std::string& aIdent) const
{
PositionedID id = flightgear::NavDataCache::instance()->airportItemWithIdent(guid(), FGPositioned::HELIPAD, aIdent);
if (id == 0) {
throw sg_range_exception("unknown helipad " + aIdent + " at airport:" + ident(), "FGAirport::getRunwayByIdent");
}
- return (FGHelipad*) flightgear::NavDataCache::instance()->loadById(id);
+ return loadById<FGHelipad>(id);
}
-
-FGRunway* FGAirport::findBestRunwayForHeading(double aHeading) const
+//------------------------------------------------------------------------------
+FGRunwayRef FGAirport::findBestRunwayForHeading(double aHeading, struct FindBestRunwayForHeadingParams * parms ) const
{
loadRunways();
FGRunway* result = NULL;
double currentBestQuality = 0.0;
- SGPropertyNode *param = fgGetNode("/sim/airport/runways/search", true);
- double lengthWeight = param->getDoubleValue("length-weight", 0.01);
- double widthWeight = param->getDoubleValue("width-weight", 0.01);
- double surfaceWeight = param->getDoubleValue("surface-weight", 10);
- double deviationWeight = param->getDoubleValue("deviation-weight", 1);
+ struct FindBestRunwayForHeadingParams fbrfhp;
+ if( NULL != parms ) fbrfhp = *parms;
+
+ SGPropertyNode_ptr searchNode = fgGetNode("/sim/airport/runways/search");
+ if( searchNode.valid() ) {
+ fbrfhp.lengthWeight = searchNode->getDoubleValue("length-weight", fbrfhp.lengthWeight );
+ fbrfhp.widthWeight = searchNode->getDoubleValue("width-weight", fbrfhp.widthWeight );
+ fbrfhp.surfaceWeight = searchNode->getDoubleValue("surface-weight", fbrfhp.surfaceWeight );
+ fbrfhp.deviationWeight = searchNode->getDoubleValue("deviation-weight", fbrfhp.deviationWeight );
+ fbrfhp.ilsWeight = searchNode->getDoubleValue("ils-weight", fbrfhp.ilsWeight );
+ }
- BOOST_FOREACH(PositionedID id, mRunways) {
- FGRunway* rwy = (FGRunway*) flightgear::NavDataCache::instance()->loadById(id);
- double good = rwy->score(lengthWeight, widthWeight, surfaceWeight);
+ BOOST_FOREACH(FGRunwayRef rwy, mRunways) {
+ double good = rwy->score( fbrfhp.lengthWeight, fbrfhp.widthWeight, fbrfhp.surfaceWeight, fbrfhp.ilsWeight );
double dev = aHeading - rwy->headingDeg();
SG_NORMALIZE_RANGE(dev, -180.0, 180.0);
- double bad = fabs(deviationWeight * dev) + 1e-20;
+ double bad = fabs( fbrfhp.deviationWeight * dev) + 1e-20;
double quality = good / bad;
if (quality > currentBestQuality) {
return result;
}
-FGRunway* FGAirport::findBestRunwayForPos(const SGGeod& aPos) const
+//------------------------------------------------------------------------------
+FGRunwayRef FGAirport::findBestRunwayForPos(const SGGeod& aPos) const
{
loadRunways();
FGRunway* result = NULL;
double currentLowestDev = 180.0;
- BOOST_FOREACH(PositionedID id, mRunways) {
- FGRunway* rwy = (FGRunway*) flightgear::NavDataCache::instance()->loadById(id);
-
+ BOOST_FOREACH(FGRunwayRef rwy, mRunways) {
double inboundCourse = SGGeodesy::courseDeg(aPos, rwy->end());
double dev = inboundCourse - rwy->headingDeg();
SG_NORMALIZE_RANGE(dev, -180.0, 180.0);
}
+//------------------------------------------------------------------------------
bool FGAirport::hasHardRunwayOfLengthFt(double aLengthFt) const
{
loadRunways();
- BOOST_FOREACH(PositionedID id, mRunways) {
- FGRunway* rwy = (FGRunway*) flightgear::NavDataCache::instance()->loadById(id);
-
- if (rwy->isReciprocal()) {
- continue; // we only care about lengths, so don't do work twice
- }
-
+ BOOST_FOREACH(FGRunwayRef rwy, mRunways) {
if (rwy->isHardSurface() && (rwy->lengthFt() >= aLengthFt)) {
return true; // we're done!
}
return false;
}
+//------------------------------------------------------------------------------
+FGRunwayList FGAirport::getRunwaysWithoutReciprocals() const
+{
+ loadRunways();
+
+ FGRunwayList r;
+
+ BOOST_FOREACH(FGRunwayRef rwy, mRunways) {
+ FGRunway* recip = rwy->reciprocalRunway();
+ if (recip) {
+ FGRunwayList::iterator it = std::find(r.begin(), r.end(), recip);
+ if (it != r.end()) {
+ continue; // reciprocal already in result set, don't include us
+ }
+ }
+
+ r.push_back(rwy);
+ }
+
+ return r;
+}
+
+//------------------------------------------------------------------------------
unsigned int FGAirport::numTaxiways() const
{
loadTaxiways();
return mTaxiways.size();
}
-FGTaxiway* FGAirport::getTaxiwayByIndex(unsigned int aIndex) const
+//------------------------------------------------------------------------------
+FGTaxiwayRef FGAirport::getTaxiwayByIndex(unsigned int aIndex) const
{
loadTaxiways();
-
- assert(aIndex >= 0 && aIndex < mTaxiways.size());
- return (FGTaxiway*) flightgear::NavDataCache::instance()->loadById(mTaxiways[aIndex]);
+ return loadById<FGTaxiway>(mTaxiways, aIndex);
}
+//------------------------------------------------------------------------------
+FGTaxiwayList FGAirport::getTaxiways() const
+{
+ loadTaxiways();
+ return loadAllById<FGTaxiway>(mTaxiways);
+}
+
+//------------------------------------------------------------------------------
unsigned int FGAirport::numPavements() const
{
loadTaxiways();
return mPavements.size();
}
-FGPavement* FGAirport::getPavementByIndex(unsigned int aIndex) const
+//------------------------------------------------------------------------------
+FGPavementRef FGAirport::getPavementByIndex(unsigned int aIndex) const
{
loadTaxiways();
- assert(aIndex >= 0 && aIndex < mPavements.size());
- return (FGPavement*) flightgear::NavDataCache::instance()->loadById(mPavements[aIndex]);
+ return loadById<FGPavement>(mPavements, aIndex);
}
-FGRunway* FGAirport::getActiveRunwayForUsage() const
+//------------------------------------------------------------------------------
+FGPavementList FGAirport::getPavements() const
+{
+ loadTaxiways();
+ return loadAllById<FGPavement>(mPavements);
+}
+
+//------------------------------------------------------------------------------
+FGRunwayRef FGAirport::getActiveRunwayForUsage() const
{
FGEnvironmentMgr* envMgr = (FGEnvironmentMgr *) globals->get_subsystem("environment");
double hdg = 270;
if (envMgr) {
- FGEnvironment stationWeather(envMgr->getEnvironment(mPosition));
+ FGEnvironment stationWeather(envMgr->getEnvironment(geod()));
double windSpeed = stationWeather.get_wind_speed_kt();
if (windSpeed > 0.0) {
return findBestRunwayForHeading(hdg);
}
-FGAirport* FGAirport::findClosest(const SGGeod& aPos, double aCuttofNm, Filter* filter)
+//------------------------------------------------------------------------------
+FGAirportRef FGAirport::findClosest( const SGGeod& aPos,
+ double aCuttofNm,
+ Filter* filter )
{
AirportFilter aptFilter;
- if (filter == NULL) {
+ if( !filter )
filter = &aptFilter;
- }
- FGPositionedRef r = FGPositioned::findClosest(aPos, aCuttofNm, filter);
- if (!r) {
- return NULL;
- }
-
- return static_cast<FGAirport*>(r.ptr());
+ return static_pointer_cast<FGAirport>
+ (
+ FGPositioned::findClosest(aPos, aCuttofNm, filter)
+ );
}
FGAirport::HardSurfaceFilter::HardSurfaceFilter(double minLengthFt) :
mMinLengthFt = fgGetDouble("/sim/navdb/min-runway-length-ft", 0.0);
}
}
-
+
bool FGAirport::HardSurfaceFilter::passAirport(FGAirport* aApt) const
{
return aApt->hasHardRunwayOfLengthFt(mMinLengthFt);
}
-FGAirport* FGAirport::findByIdent(const std::string& aIdent)
+//------------------------------------------------------------------------------
+FGAirport::TypeRunwayFilter::TypeRunwayFilter():
+ _type(FGPositioned::AIRPORT),
+ _min_runway_length_ft( fgGetDouble("/sim/navdb/min-runway-length-ft", 0.0) )
+{
+
+}
+
+//------------------------------------------------------------------------------
+bool FGAirport::TypeRunwayFilter::fromTypeString(const std::string& type)
+{
+ if( type == "heliport" ) _type = FGPositioned::HELIPORT;
+ else if( type == "seaport" ) _type = FGPositioned::SEAPORT;
+ else if( type == "airport" ) _type = FGPositioned::AIRPORT;
+ else return false;
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool FGAirport::TypeRunwayFilter::pass(FGPositioned* pos) const
+{
+ FGAirport* apt = static_cast<FGAirport*>(pos);
+ if( (apt->type() == FGPositioned::AIRPORT)
+ && !apt->hasHardRunwayOfLengthFt(_min_runway_length_ft)
+ )
+ return false;
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+FGAirportRef FGAirport::findByIdent(const std::string& aIdent)
{
AirportCache::iterator it = airportCache.find(aIdent);
if (it != airportCache.end())
return it->second;
PortsFilter filter;
- FGAirport* r = static_cast<FGAirport*> (FGPositioned::findFirstWithIdent(aIdent, &filter).get());
+ FGAirportRef r = static_pointer_cast<FGAirport>
+ (
+ FGPositioned::findFirstWithIdent(aIdent, &filter)
+ );
// add airport to the cache (even when it's NULL, so we don't need to search in vain again)
airportCache[aIdent] = r;
return r;
}
-FGAirport* FGAirport::getByIdent(const std::string& aIdent)
+//------------------------------------------------------------------------------
+FGAirportRef FGAirport::getByIdent(const std::string& aIdent)
{
- FGAirport* r = findByIdent(aIdent);
+ FGAirportRef r = findByIdent(aIdent);
if (!r)
throw sg_range_exception("No such airport with ident: " + aIdent);
return r;
}
// find basic airport location info from airport database
-const FGAirport *fgFindAirportID( const string& id)
+const FGAirport *fgFindAirportID( const std::string& id)
{
if ( id.empty() ) {
return NULL;
return FGAirport::findByIdent(id);
}
+PositionedIDVec FGAirport::itemsOfType(FGPositioned::Type ty) const
+{
+ flightgear::NavDataCache* cache = flightgear::NavDataCache::instance();
+ return cache->airportItemsOfType(guid(), ty);
+}
+
void FGAirport::loadRunways() const
{
if (mRunwaysLoaded) {
loadSceneryDefinitions();
mRunwaysLoaded = true;
- mRunways = flightgear::NavDataCache::instance()->airportItemsOfType(guid(), FGPositioned::RUNWAY);
+ PositionedIDVec rwys(itemsOfType(FGPositioned::RUNWAY));
+ BOOST_FOREACH(PositionedID id, rwys) {
+ mRunways.push_back(loadById<FGRunway>(id));
+ }
}
void FGAirport::loadHelipads() const
return; // already loaded, great
}
- loadSceneryDefinitions();
-
mHelipadsLoaded = true;
- mHelipads = flightgear::NavDataCache::instance()->airportItemsOfType(guid(), FGPositioned::HELIPAD);
+ mHelipads = itemsOfType(FGPositioned::HELIPAD);
}
void FGAirport::loadTaxiways() const
}
mTaxiwaysLoaded = true;
- mTaxiways = flightgear::NavDataCache::instance()->airportItemsOfType(guid(), FGPositioned::TAXIWAY);
+ mTaxiways = itemsOfType(FGPositioned::TAXIWAY);
}
void FGAirport::loadProcedures() const
void FGAirport::loadSceneryDefinitions() const
{
- NavDataCache* cache = NavDataCache::instance();
+ if (mThresholdDataLoaded) {
+ return;
+ }
+
+ mThresholdDataLoaded = true;
+
SGPath path;
if (!XMLLoader::findAirportData(ident(), "threshold", path)) {
return; // no XML threshold data
}
- if (!cache->isCachedFileModified(path)) {
- // cached values are correct, we're all done
- return;
- }
-
- flightgear::NavDataCache::Transaction txn(cache);
+ try {
SGPropertyNode_ptr rootNode = new SGPropertyNode;
readProperties(path.str(), rootNode);
const_cast<FGAirport*>(this)->readThresholdData(rootNode);
- cache->stampCacheFile(path);
- txn.commit();
+ } catch (sg_exception& e) {
+ SG_LOG(SG_NAVAID, SG_WARN, ident() << "loading threshold XML failed:" << e.getFormattedMessage());
+ }
}
void FGAirport::readThresholdData(SGPropertyNode* aRoot)
void FGAirport::processThreshold(SGPropertyNode* aThreshold)
{
// first, let's identify the current runway
- string rwyIdent(aThreshold->getStringValue("rwy"));
+ std::string rwyIdent(aThreshold->getStringValue("rwy"));
NavDataCache* cache = NavDataCache::instance();
PositionedID id = cache->airportItemWithIdent(guid(), FGPositioned::RUNWAY, rwyIdent);
- if (id == 0) {
- SG_LOG(SG_GENERAL, SG_DEBUG, "FGAirport::processThreshold: "
- "found runway not defined in the global data:" << ident() << "/" << rwyIdent);
- return;
- }
double lon = aThreshold->getDoubleValue("lon"),
lat = aThreshold->getDoubleValue("lat");
- SGGeod newThreshold(SGGeod::fromDegM(lon, lat, mPosition.getElevationM()));
+ SGGeod newThreshold(SGGeod::fromDegM(lon, lat, elevationM()));
double newHeading = aThreshold->getDoubleValue("hdg-deg");
- double newDisplacedThreshold = aThreshold->getDoubleValue("displ-m") * SG_METER_TO_FEET;
- double newStopway = aThreshold->getDoubleValue("stopw-m") * SG_METER_TO_FEET;
+ double newDisplacedThreshold = aThreshold->getDoubleValue("displ-m");
+ double newStopway = aThreshold->getDoubleValue("stopw-m");
- cache->updateRunwayThreshold(id, newThreshold,
- newHeading, newDisplacedThreshold, newStopway);
+ if (id == 0) {
+ SG_LOG(SG_GENERAL, SG_DEBUG, "FGAirport::processThreshold: "
+ "found runway not defined in the global data:" << ident() << "/" << rwyIdent);
+ // enable this code when threshold.xml contains sufficient data to
+ // fully specify a new runway, *and* we figure out how to assign runtime
+ // Positioned IDs and insert temporary items into the spatial map.
+#if 0
+ double newLength = 0.0, newWidth = 0.0;
+ int surfaceCode = 0;
+ FGRunway* rwy = new FGRunway(id, guid(), rwyIdent, newThreshold,
+ newHeading,
+ newLength, newWidth,
+ newDisplacedThreshold, newStopway,
+ surfaceCode);
+ // insert into the spatial map too
+ mRunways.push_back(rwy);
+#endif
+ } else {
+ FGRunway* rwy = loadById<FGRunway>(id);
+ rwy->updateThreshold(newThreshold, newHeading,
+ newDisplacedThreshold, newStopway);
+
+ }
}
SGGeod FGAirport::getTowerLocation() const
{
validateTowerData();
-
- NavDataCache* cache = NavDataCache::instance();
- PositionedIDVec towers = cache->airportItemsOfType(guid(), FGPositioned::TOWER);
- if (towers.empty()) {
- SG_LOG(SG_GENERAL, SG_ALERT, "No towers defined for:" <<ident());
- return SGGeod();
- }
-
- FGPositionedRef tower = cache->loadById(towers.front());
- return tower->geod();
+ return mTowerPosition;
}
void FGAirport::validateTowerData() const
if (mTowerDataLoaded) {
return;
}
-
+
mTowerDataLoaded = true;
+
+// first, load data from the cache (apt.dat)
NavDataCache* cache = NavDataCache::instance();
+ PositionedIDVec towers = cache->airportItemsOfType(guid(), FGPositioned::TOWER);
+ if (towers.empty()) {
+ SG_LOG(SG_GENERAL, SG_ALERT, "No towers defined for:" <<ident());
+ mTowerPosition = geod(); // use airport position
+ // increase tower elevation by 20 metres above the field elevation
+ mTowerPosition.setElevationM(geod().getElevationM() + 20.0);
+ } else {
+ FGPositionedRef tower = cache->loadById(towers.front());
+ mTowerPosition = tower->geod();
+ }
+
SGPath path;
if (!XMLLoader::findAirportData(ident(), "twr", path)) {
- return; // no XML tower data
+ return; // no XML tower data, base position is fine
}
- if (!cache->isCachedFileModified(path)) {
- // cached values are correct, we're all done
- return;
+ try {
+ SGPropertyNode_ptr rootNode = new SGPropertyNode;
+ readProperties(path.str(), rootNode);
+ const_cast<FGAirport*>(this)->readTowerData(rootNode);
+ } catch (sg_exception& e){
+ SG_LOG(SG_NAVAID, SG_WARN, ident() << "loading twr XML failed:" << e.getFormattedMessage());
}
-
- flightgear::NavDataCache::Transaction txn(cache);
- SGPropertyNode_ptr rootNode = new SGPropertyNode;
- readProperties(path.str(), rootNode);
- const_cast<FGAirport*>(this)->readTowerData(rootNode);
- cache->stampCacheFile(path);
- txn.commit();
}
void FGAirport::readTowerData(SGPropertyNode* aRoot)
// scenery for a precise terrain elevation, we use the field elevation
// (this is also what the apt.dat code does)
double fieldElevationM = geod().getElevationM();
- SGGeod towerLocation(SGGeod::fromDegM(lon, lat, fieldElevationM + elevM));
-
- NavDataCache* cache = NavDataCache::instance();
- PositionedIDVec towers = cache->airportItemsOfType(guid(), FGPositioned::TOWER);
- if (towers.empty()) {
- cache->insertTower(guid(), towerLocation);
- } else {
- // update the position
- cache->updatePosition(towers.front(), towerLocation);
- }
+ mTowerPosition = SGGeod::fromDegM(lon, lat, fieldElevationM + elevM);
}
-bool FGAirport::validateILSData()
+void FGAirport::validateILSData()
{
if (mILSDataLoaded) {
- return false;
+ return;
}
+ // to avoid re-entrancy on this code-path, ensure we set loaded
+ // immediately.
mILSDataLoaded = true;
- NavDataCache* cache = NavDataCache::instance();
+
SGPath path;
if (!XMLLoader::findAirportData(ident(), "ils", path)) {
- return false; // no XML tower data
+ return; // no XML tower data
}
- if (!cache->isCachedFileModified(path)) {
- // cached values are correct, we're all done
- return false;
+ try {
+ SGPropertyNode_ptr rootNode = new SGPropertyNode;
+ readProperties(path.str(), rootNode);
+ readILSData(rootNode);
+ } catch (sg_exception& e){
+ SG_LOG(SG_NAVAID, SG_WARN, ident() << "loading ils XML failed:" << e.getFormattedMessage());
}
-
- SGPropertyNode_ptr rootNode = new SGPropertyNode;
- readProperties(path.str(), rootNode);
-
- flightgear::NavDataCache::Transaction txn(cache);
- readILSData(rootNode);
- cache->stampCacheFile(path);
- txn.commit();
-
-// we loaded data, tell the caller it might need to reload things
- return true;
}
void FGAirport::readILSData(SGPropertyNode* aRoot)
-{
+{
NavDataCache* cache = NavDataCache::instance();
-
// find the entry matching the runway
SGPropertyNode* runwayNode, *ilsNode;
for (int i=0; (runwayNode = aRoot->getChild("runway", i)) != NULL; ++i) {
ilsNode->getStringValue("nav-id"));
if (ils == 0) {
SG_LOG(SG_GENERAL, SG_INFO, "reading ILS data for " << ident() <<
- ", couldn;t find runway/navaid for:" <<
+ ", couldn't find runway/navaid for:" <<
ilsNode->getStringValue("rwy") << "/" <<
ilsNode->getStringValue("nav-id"));
continue;
lat = ilsNode->getDoubleValue("lat"),
elevM = ilsNode->getDoubleValue("elev-m");
- cache->updateILS(ils, SGGeod::fromDegM(lon, lat, elevM), hdgDeg);
+ FGNavRecordRef nav(FGPositioned::loadById<FGNavRecord>(ils));
+ assert(nav.valid());
+ nav->updateFromXML(SGGeod::fromDegM(lon, lat, elevM), hdgDeg);
} // of ILS iteration
} // of runway iteration
}
mApproaches.push_back(aApp);
}
+//------------------------------------------------------------------------------
unsigned int FGAirport::numSIDs() const
{
loadProcedures();
return mSIDs.size();
}
+//------------------------------------------------------------------------------
flightgear::SID* FGAirport::getSIDByIndex(unsigned int aIndex) const
{
loadProcedures();
return mSIDs[aIndex];
}
+//------------------------------------------------------------------------------
flightgear::SID* FGAirport::findSIDWithIdent(const std::string& aIdent) const
{
loadProcedures();
return NULL;
}
+//------------------------------------------------------------------------------
+flightgear::SIDList FGAirport::getSIDs() const
+{
+ loadProcedures();
+ return flightgear::SIDList(mSIDs.begin(), mSIDs.end());
+}
+
+//------------------------------------------------------------------------------
unsigned int FGAirport::numSTARs() const
{
loadProcedures();
return mSTARs.size();
}
+//------------------------------------------------------------------------------
STAR* FGAirport::getSTARByIndex(unsigned int aIndex) const
{
loadProcedures();
return mSTARs[aIndex];
}
+//------------------------------------------------------------------------------
STAR* FGAirport::findSTARWithIdent(const std::string& aIdent) const
{
loadProcedures();
return NULL;
}
+//------------------------------------------------------------------------------
+STARList FGAirport::getSTARs() const
+{
+ loadProcedures();
+ return STARList(mSTARs.begin(), mSTARs.end());
+}
+
unsigned int FGAirport::numApproaches() const
{
loadProcedures();
return mApproaches.size();
}
+//------------------------------------------------------------------------------
Approach* FGAirport::getApproachByIndex(unsigned int aIndex) const
{
loadProcedures();
return mApproaches[aIndex];
}
+//------------------------------------------------------------------------------
Approach* FGAirport::findApproachWithIdent(const std::string& aIdent) const
{
loadProcedures();
return NULL;
}
+//------------------------------------------------------------------------------
+ApproachList FGAirport::getApproaches(ProcedureType type) const
+{
+ loadProcedures();
+ if( type == PROCEDURE_INVALID )
+ return ApproachList(mApproaches.begin(), mApproaches.end());
+
+ ApproachList ret;
+ for(size_t i = 0; i < mApproaches.size(); ++i)
+ {
+ if( mApproaches[i]->type() == type )
+ ret.push_back(mApproaches[i]);
+ }
+ return ret;
+}
+
CommStationList
FGAirport::commStations() const
{
FGPositioned::FREQ_GROUND,
FGPositioned::FREQ_UNICOM))
{
- result.push_back((CommStation*) cache->loadById(pos));
+ result.push_back( loadById<CommStation>(pos) );
}
return result;
NavDataCache* cache = NavDataCache::instance();
CommStationList result;
BOOST_FOREACH(PositionedID pos, cache->airportItemsOfType(guid(), aTy)) {
- result.push_back((CommStation*) cache->loadById(pos));
+ result.push_back( loadById<CommStation>(pos) );
}
return result;
}
+class AirportWithSize
+{
+public:
+ AirportWithSize(FGPositionedRef pos) :
+ _pos(pos),
+ _sizeMetric(0)
+ {
+ assert(pos->type() == FGPositioned::AIRPORT);
+ FGAirport* apt = static_cast<FGAirport*>(pos.get());
+ BOOST_FOREACH(FGRunway* rwy, apt->getRunwaysWithoutReciprocals()) {
+ _sizeMetric += static_cast<int>(rwy->lengthFt());
+ }
+ }
+
+ bool operator<(const AirportWithSize& other) const
+ {
+ return _sizeMetric < other._sizeMetric;
+ }
+
+ FGPositionedRef pos() const
+ { return _pos; }
+private:
+ FGPositionedRef _pos;
+ unsigned int _sizeMetric;
+
+};
+
+void FGAirport::sortBySize(FGPositionedList& airportList)
+{
+ std::vector<AirportWithSize> annotated;
+ BOOST_FOREACH(FGPositionedRef p, airportList) {
+ annotated.push_back(AirportWithSize(p));
+ }
+ std::sort(annotated.begin(), annotated.end());
+
+ for (unsigned int i=0; i<annotated.size(); ++i) {
+ airportList[i] = annotated[i].pos();
+ }
+}
+
// get airport elevation
-double fgGetAirportElev( const string& id )
+double fgGetAirportElev( const std::string& id )
{
const FGAirport *a=fgFindAirportID( id);
if (a) {
// get airport position
-SGGeod fgGetAirportPos( const string& id )
+SGGeod fgGetAirportPos( const std::string& id )
{
const FGAirport *a = fgFindAirportID( id);