#include <Main/fg_props.hxx>
#include <Airports/runways.hxx>
#include <Airports/pavement.hxx>
-#include <Airports/dynamics.hxx>
#include <Airports/xmlloader.hxx>
+#include <Airports/dynamics.hxx>
+#include <Airports/airportdynamicsmanager.hxx>
#include <Navaids/procedure.hxx>
#include <Navaids/waypoint.hxx>
#include <ATC/CommStation.hxx>
#include <Navaids/NavDataCache.hxx>
+#include <Navaids/navrecord.hxx>
using std::vector;
using std::pair;
FGPositioned(aGuid, aType, id, location),
_name(name),
_has_metar(has_metar),
- _dynamics(0),
mTowerDataLoaded(false),
+ mHasTower(false),
mRunwaysLoaded(false),
mHelipadsLoaded(false),
mTaxiwaysLoaded(false),
mProceduresLoaded(false),
+ mThresholdDataLoaded(false),
mILSDataLoaded(false)
{
+ mIsClosed = (name.find("[x]") != std::string::npos);
}
FGAirport::~FGAirport()
{
- delete _dynamics;
}
bool FGAirport::isAirport() const
return (pos->type() >= AIRPORT) && (pos->type() <= SEAPORT);
}
-FGAirportDynamics * FGAirport::getDynamics()
-{
- if (_dynamics) {
- return _dynamics;
- }
-
- _dynamics = new FGAirportDynamics(this);
- XMLLoader::load(_dynamics);
- _dynamics->init();
-
- FGRunwayPreference rwyPrefs(this);
- XMLLoader::load(&rwyPrefs);
- _dynamics->setRwyUse(rwyPrefs);
-
- return _dynamics;
-}
-
//------------------------------------------------------------------------------
unsigned int FGAirport::numRunways() const
{
return false;
}
+FGRunwayRef FGAirport::longestRunway() const
+{
+ FGRunwayRef r;
+ loadRunways();
+
+ BOOST_FOREACH(FGRunwayRef rwy, mRunways) {
+ if (!r || (r->lengthFt() < rwy->lengthFt())) {
+ r = rwy;
+ }
+ } // of runways iteration
+
+ return r;
+}
+
+//------------------------------------------------------------------------------
+FGRunwayList FGAirport::getRunways() const
+{
+ loadRunways();
+
+ return mRunways;
+}
+
//------------------------------------------------------------------------------
FGRunwayList FGAirport::getRunwaysWithoutReciprocals() const
{
return; // already loaded, great
}
- loadSceneryDefinitions();
-
mHelipadsLoaded = true;
mHelipads = itemsOfType(FGPositioned::HELIPAD);
}
void FGAirport::loadSceneryDefinitions() const
{
+ if (mThresholdDataLoaded) {
+ return;
+ }
+
+ mThresholdDataLoaded = true;
+
SGPath path;
if (!XMLLoader::findAirportData(ident(), "threshold", path)) {
return; // no XML threshold data
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());
+ mHasTower = false;
mTowerPosition = geod(); // use airport position
+
+ // offset the tower position away from the runway centerline, if
+ // airport has a single runway. Offset by eight times the runway width,
+ // an entirely guessed figure.
+ int runwayCount = numRunways();
+ if ((runwayCount > 0) && (runwayCount <= 2)) {
+ FGRunway* runway = getRunwayByIndex(0);
+ double hdg = runway->headingDeg() + 90;
+ mTowerPosition = SGGeodesy::direct(geod(), hdg, runway->widthM() * 8);
+ }
+
// 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();
+ mHasTower = true;
}
SGPath path;
SGPropertyNode_ptr rootNode = new SGPropertyNode;
readProperties(path.str(), rootNode);
const_cast<FGAirport*>(this)->readTowerData(rootNode);
+ mHasTower = true;
} catch (sg_exception& e){
SG_LOG(SG_NAVAID, SG_WARN, ident() << "loading twr XML failed:" << e.getFormattedMessage());
}
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();
- if (cache->isReadOnly()) {
- return false;
- }
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());
}
-
- try {
- 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;
- } catch (sg_exception& e){
- SG_LOG(SG_NAVAID, SG_WARN, ident() << "loading ils XML failed:" << e.getFormattedMessage());
- }
-
- return false;
+bool FGAirport::hasTower() const
+{
+ validateTowerData();
+ return mHasTower;
}
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
}
}
}
+FGAirportDynamicsRef FGAirport::getDynamics() const
+{
+ return flightgear::AirportDynamicsManager::find(const_cast<FGAirport*>(this));
+}
+
// get airport elevation
double fgGetAirportElev( const std::string& id )
{