From 1c015387baa3b65344024623fc1bc10e11f3866b Mon Sep 17 00:00:00 2001 From: jmt Date: Sat, 29 Aug 2009 10:21:21 +0000 Subject: [PATCH] Initial framing for reading in-scenery airport data. --- src/Airports/runways.cxx | 4 +++ src/Airports/runways.hxx | 6 ++++ src/Airports/simple.cxx | 74 ++++++++++++++++++++++++++++++++++---- src/Airports/simple.hxx | 35 ++++++++++++++---- src/Airports/xmlloader.cxx | 42 +++++++++++++++++++++- src/Airports/xmlloader.hxx | 25 ++++++++++--- 6 files changed, 168 insertions(+), 18 deletions(-) diff --git a/src/Airports/runways.cxx b/src/Airports/runways.cxx index e6f62d88b..346dc35bd 100644 --- a/src/Airports/runways.cxx +++ b/src/Airports/runways.cxx @@ -136,3 +136,7 @@ SGGeod FGRunway::threshold() const return pointOnCenterline(_displ_thresh * SG_FEET_TO_METER); } +void FGRunway::processThreshold(SGPropertyNode* aThreshold) +{ + assert(ident() == aThreshold->getStringValue("rwy")); +} diff --git a/src/Airports/runways.hxx b/src/Airports/runways.hxx index 595c77b8b..15d39c2af 100644 --- a/src/Airports/runways.hxx +++ b/src/Airports/runways.hxx @@ -31,6 +31,7 @@ // forward decls class FGAirport; class FGNavRecord; +class SGPropertyNode; class FGRunway : public FGRunwayBase { @@ -104,6 +105,11 @@ public: FGNavRecord* ILS() const { return _ils; } void setILS(FGNavRecord* nav) { _ils = nav; } + + /** + * Helper to process property data loaded from an ICAO.threshold.xml file + */ + void processThreshold(SGPropertyNode* aThreshold); }; #endif // _FG_RUNWAYS_HXX diff --git a/src/Airports/simple.cxx b/src/Airports/simple.cxx index 04dec38b8..95ce25af4 100644 --- a/src/Airports/simple.cxx +++ b/src/Airports/simple.cxx @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -56,7 +57,8 @@ FGAirport::FGAirport(const string &id, const SGGeod& location, const SGGeod& tow _tower_location(tower_location), _name(name), _has_metar(has_metar), - _dynamics(0) + _dynamics(0), + mLoadedXML(false) { } @@ -311,12 +313,73 @@ const FGAirport *fgFindAirportID( const string& id) } +void FGAirport::loadSceneryDefintions() const +{ + mLoadedXML = true; + + // allow users to disable the scenery data in the short-term + // longer term, this option can probably disappear + if (fgGetBool("/sim/use-scenery-airport-data") == false) { + return; + } + + SGPath path; + SGPropertyNode_ptr rootNode = new SGPropertyNode; + if (XMLLoader::findAirportData(ident(), "threshold", path)) { + readProperties(path.str(), rootNode); + const_cast(this)->readThresholdData(rootNode); + } + + // repeat for the tower data + rootNode = new SGPropertyNode; + if (XMLLoader::findAirportData(ident(), "twr", path)) { + readProperties(path.str(), rootNode); + const_cast(this)->readTowerData(rootNode); + } +} + +void FGAirport::readThresholdData(SGPropertyNode* aRoot) +{ + SGPropertyNode* runway; + int runwayIndex = 0; + for (; (runway = aRoot->getChild("runway", runwayIndex)) != NULL; ++runwayIndex) { + SGPropertyNode* t0 = runway->getChild("threshold", 0), + *t1 = runway->getChild("threshold", 1); + assert(t0); + assert(t1); // too strict? mayeb we should finally allow single-ended runways + + processThreshold(t0); + processThreshold(t1); + } // of runways iteration +} + +void FGAirport::processThreshold(SGPropertyNode* aThreshold) +{ + // first, let's identify the current runway + string id(aThreshold->getStringValue("rwy")); + if (!hasRunwayWithIdent(id)) { + SG_LOG(SG_GENERAL, SG_WARN, "FGAirport::processThreshold: " + "found runway not defined in the global data:" << ident() << "/" << id); + return; + } + + FGRunway* rwy = getRunwayByIdent(id); + rwy->processThreshold(aThreshold); +} + +void FGAirport::readTowerData(SGPropertyNode* aRoot) +{ + SGPropertyNode* twrNode = aRoot->getChild("twr"); + double lat = twrNode->getDoubleValue("lat"), + lon = twrNode->getDoubleValue("lon"), + elevM = twrNode->getDoubleValue("elev-m"); + + _tower_location = SGGeod::fromDegM(lon, lat, elevM); +} + // get airport elevation double fgGetAirportElev( const string& id ) { - SG_LOG( SG_GENERAL, SG_BULK, - "Finding elevation for airport: " << id ); - const FGAirport *a=fgFindAirportID( id); if (a) { return a->getElevation(); @@ -329,9 +392,6 @@ double fgGetAirportElev( const string& id ) // get airport position SGGeod fgGetAirportPos( const string& id ) { - SG_LOG( SG_ATC, SG_BULK, - "Finding position for airport: " << id ); - const FGAirport *a = fgFindAirportID( id); if (a) { diff --git a/src/Airports/simple.hxx b/src/Airports/simple.hxx index 71fb97fb8..60b54d0ff 100644 --- a/src/Airports/simple.hxx +++ b/src/Airports/simple.hxx @@ -39,6 +39,7 @@ class FGAirportDynamics; class FGRunway; class FGTaxiway; class FGPavement; +class SGPropertyNode; typedef SGSharedPtr FGRunwayPtr; typedef SGSharedPtr FGTaxiwayPtr; @@ -49,12 +50,6 @@ typedef SGSharedPtr FGPavementPtr; **************************************************************************************/ class FGAirport : public FGPositioned { -private: - SGGeod _tower_location; - std::string _name; - bool _has_metar; - FGAirportDynamics *_dynamics; - public: FGAirport(const std::string& id, const SGGeod& location, const SGGeod& tower, const std::string& name, bool has_metar, Type aType); @@ -173,8 +168,36 @@ private: */ Runway_iterator getIteratorForRunwayIdent(const std::string& aIdent) const; + // disable these FGAirport operator=(FGAirport &other); FGAirport(const FGAirport&); + + /** + * helper to read airport data from the scenery XML files. + */ + void loadSceneryDefintions() const; + + /** + * Helpers to process property data loaded from an ICAO.threshold.xml file + */ + void readThresholdData(SGPropertyNode* aRoot); + void processThreshold(SGPropertyNode* aThreshold); + + /** + * Helper to parse property data loaded from an ICAO.twr.xml filke + */ + void readTowerData(SGPropertyNode* aRoot); + + SGGeod _tower_location; + std::string _name; + bool _has_metar; + FGAirportDynamics *_dynamics; + + /** + * This flag indicates if we have attempted to load data from the scenery + * storage to supplement the Apt.Dat information. + */ + mutable bool mLoadedXML; std::vector mRunways; std::vector mTaxiways; diff --git a/src/Airports/xmlloader.cxx b/src/Airports/xmlloader.cxx index de35f4d13..f2f81daf9 100644 --- a/src/Airports/xmlloader.cxx +++ b/src/Airports/xmlloader.cxx @@ -15,6 +15,8 @@ #include +#include + #include
#include
@@ -25,10 +27,12 @@ #include "dynamics.hxx" #include "runwayprefs.hxx" +using std::string; + XMLLoader::XMLLoader() {} XMLLoader::~XMLLoader() {} -string XMLLoader::expandICAODirs(const string in){ +string XMLLoader::expandICAODirs(const string& in){ //cerr << "Expanding " << in << endl; if (in.size() == 4) { char buffer[11]; @@ -143,3 +147,39 @@ void XMLLoader::load(FGSidStar* p) { } } } + +bool XMLLoader::findAirportData(const std::string& aICAO, + const std::string& aFileName, SGPath& aPath) +{ + string_list sc = globals->get_fg_scenery(); + char buffer[128]; + ::snprintf(buffer, 128, "%c/%c/%c/%s.%s.xml", + aICAO[0], aICAO[1], aICAO[2], + aICAO.c_str(), aFileName.c_str()); + + for (string_list_iterator it = sc.begin(); it != sc.end(); ++it) { + SGPath path(*it); + path.append("Airports"); + path.append(string(buffer)); + if (path.exists()) { + aPath = path; + return true; + } // of path exists + } // of scenery path iteration + + + return false; +} + +bool XMLLoader::loadAirportXMLDataIntoVisitor(const string& aICAO, + const string& aFileName, XMLVisitor& aVisitor) +{ + SGPath path; + if (!findAirportData(aICAO, aFileName, path)) { + return false; + } + + readXML(path.str(), aVisitor); + return true; +} + diff --git a/src/Airports/xmlloader.hxx b/src/Airports/xmlloader.hxx index eb066495f..88ab5af81 100644 --- a/src/Airports/xmlloader.hxx +++ b/src/Airports/xmlloader.hxx @@ -16,23 +16,40 @@ #ifndef _XML_LOADER_HXX_ #define _XML_LOADER_HXX_ -#include - class FGAirportDynamics; class FGRunwayPreference; class FGSidStar; - +class XMLVisitor; // ffrom easyxml.hxx class XMLLoader { public: XMLLoader(); ~XMLLoader(); - static string expandICAODirs(const string in); + static string expandICAODirs(const std::string& in); + static void load(FGRunwayPreference* p); static void load(FGAirportDynamics* d); static void load(FGSidStar* s); + /** + * Search the scenery for a file name of the form: + * I/C/A/ICAO.filename.xml + * and parse it as an XML property list, passing the data to the supplied + * visitor. If no such file could be found, returns false, otherwise returns + * true. Other failures (malformed XML, etc) with throw an exception. + */ + static bool loadAirportXMLDataIntoVisitor(const std::string& aICAO, + const std::string& aFileName, XMLVisitor& aVisitor); + + /** + * Search the scenery for a file name of the form: + * I/C/A/ICAO.filename.xml + * and return the corresponding SGPath if found (and true), + * or false and invalid path if no matching data could be found + */ + static bool findAirportData(const std::string& aICAO, + const std::string& aFileName, SGPath& aPath); }; #endif -- 2.39.5