return pointOnCenterline(_displ_thresh * SG_FEET_TO_METER);
}
+void FGRunway::processThreshold(SGPropertyNode* aThreshold)
+{
+ assert(ident() == aThreshold->getStringValue("rwy"));
+}
// forward decls
class FGAirport;
class FGNavRecord;
+class SGPropertyNode;
class FGRunway : public FGRunwayBase
{
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
#include <simgear/misc/sg_path.hxx>
#include <simgear/props/props.hxx>
+#include <simgear/props/props_io.hxx>
#include <simgear/debug/logstream.hxx>
#include <simgear/sg_inlines.h>
_tower_location(tower_location),
_name(name),
_has_metar(has_metar),
- _dynamics(0)
+ _dynamics(0),
+ mLoadedXML(false)
{
}
}
+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<FGAirport*>(this)->readThresholdData(rootNode);
+ }
+
+ // repeat for the tower data
+ rootNode = new SGPropertyNode;
+ if (XMLLoader::findAirportData(ident(), "twr", path)) {
+ readProperties(path.str(), rootNode);
+ const_cast<FGAirport*>(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();
// 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) {
class FGRunway;
class FGTaxiway;
class FGPavement;
+class SGPropertyNode;
typedef SGSharedPtr<FGRunway> FGRunwayPtr;
typedef SGSharedPtr<FGTaxiway> FGTaxiwayPtr;
**************************************************************************************/
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);
*/
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<FGRunwayPtr> mRunways;
std::vector<FGTaxiwayPtr> mTaxiways;
#include <simgear/misc/sg_path.hxx>
+#include <simgear/xml/easyxml.hxx>
+
#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
#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];
}
}
}
+
+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;
+}
+
#ifndef _XML_LOADER_HXX_
#define _XML_LOADER_HXX_
-#include <simgear/xml/easyxml.hxx>
-
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