Initial framing for reading in-scenery airport data.
This commit is contained in:
parent
a1a610f7d5
commit
1c015387ba
6 changed files with 168 additions and 18 deletions
|
@ -136,3 +136,7 @@ SGGeod FGRunway::threshold() const
|
||||||
return pointOnCenterline(_displ_thresh * SG_FEET_TO_METER);
|
return pointOnCenterline(_displ_thresh * SG_FEET_TO_METER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FGRunway::processThreshold(SGPropertyNode* aThreshold)
|
||||||
|
{
|
||||||
|
assert(ident() == aThreshold->getStringValue("rwy"));
|
||||||
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
// forward decls
|
// forward decls
|
||||||
class FGAirport;
|
class FGAirport;
|
||||||
class FGNavRecord;
|
class FGNavRecord;
|
||||||
|
class SGPropertyNode;
|
||||||
|
|
||||||
class FGRunway : public FGRunwayBase
|
class FGRunway : public FGRunwayBase
|
||||||
{
|
{
|
||||||
|
@ -104,6 +105,11 @@ public:
|
||||||
|
|
||||||
FGNavRecord* ILS() const { return _ils; }
|
FGNavRecord* ILS() const { return _ils; }
|
||||||
void setILS(FGNavRecord* nav) { _ils = nav; }
|
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
|
#endif // _FG_RUNWAYS_HXX
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
#include <simgear/props/props.hxx>
|
#include <simgear/props/props.hxx>
|
||||||
|
#include <simgear/props/props_io.hxx>
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
#include <simgear/sg_inlines.h>
|
#include <simgear/sg_inlines.h>
|
||||||
|
|
||||||
|
@ -56,7 +57,8 @@ FGAirport::FGAirport(const string &id, const SGGeod& location, const SGGeod& tow
|
||||||
_tower_location(tower_location),
|
_tower_location(tower_location),
|
||||||
_name(name),
|
_name(name),
|
||||||
_has_metar(has_metar),
|
_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<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
|
// get airport elevation
|
||||||
double fgGetAirportElev( const string& id )
|
double fgGetAirportElev( const string& id )
|
||||||
{
|
{
|
||||||
SG_LOG( SG_GENERAL, SG_BULK,
|
|
||||||
"Finding elevation for airport: " << id );
|
|
||||||
|
|
||||||
const FGAirport *a=fgFindAirportID( id);
|
const FGAirport *a=fgFindAirportID( id);
|
||||||
if (a) {
|
if (a) {
|
||||||
return a->getElevation();
|
return a->getElevation();
|
||||||
|
@ -329,9 +392,6 @@ double fgGetAirportElev( const string& id )
|
||||||
// get airport position
|
// get airport position
|
||||||
SGGeod fgGetAirportPos( const string& id )
|
SGGeod fgGetAirportPos( const string& id )
|
||||||
{
|
{
|
||||||
SG_LOG( SG_ATC, SG_BULK,
|
|
||||||
"Finding position for airport: " << id );
|
|
||||||
|
|
||||||
const FGAirport *a = fgFindAirportID( id);
|
const FGAirport *a = fgFindAirportID( id);
|
||||||
|
|
||||||
if (a) {
|
if (a) {
|
||||||
|
|
|
@ -39,6 +39,7 @@ class FGAirportDynamics;
|
||||||
class FGRunway;
|
class FGRunway;
|
||||||
class FGTaxiway;
|
class FGTaxiway;
|
||||||
class FGPavement;
|
class FGPavement;
|
||||||
|
class SGPropertyNode;
|
||||||
|
|
||||||
typedef SGSharedPtr<FGRunway> FGRunwayPtr;
|
typedef SGSharedPtr<FGRunway> FGRunwayPtr;
|
||||||
typedef SGSharedPtr<FGTaxiway> FGTaxiwayPtr;
|
typedef SGSharedPtr<FGTaxiway> FGTaxiwayPtr;
|
||||||
|
@ -49,12 +50,6 @@ typedef SGSharedPtr<FGPavement> FGPavementPtr;
|
||||||
**************************************************************************************/
|
**************************************************************************************/
|
||||||
class FGAirport : public FGPositioned
|
class FGAirport : public FGPositioned
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
SGGeod _tower_location;
|
|
||||||
std::string _name;
|
|
||||||
bool _has_metar;
|
|
||||||
FGAirportDynamics *_dynamics;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FGAirport(const std::string& id, const SGGeod& location, const SGGeod& tower,
|
FGAirport(const std::string& id, const SGGeod& location, const SGGeod& tower,
|
||||||
const std::string& name, bool has_metar, Type aType);
|
const std::string& name, bool has_metar, Type aType);
|
||||||
|
@ -173,8 +168,36 @@ private:
|
||||||
*/
|
*/
|
||||||
Runway_iterator getIteratorForRunwayIdent(const std::string& aIdent) const;
|
Runway_iterator getIteratorForRunwayIdent(const std::string& aIdent) const;
|
||||||
|
|
||||||
|
// disable these
|
||||||
FGAirport operator=(FGAirport &other);
|
FGAirport operator=(FGAirport &other);
|
||||||
FGAirport(const FGAirport&);
|
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<FGRunwayPtr> mRunways;
|
||||||
std::vector<FGTaxiwayPtr> mTaxiways;
|
std::vector<FGTaxiwayPtr> mTaxiways;
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
|
|
||||||
|
#include <simgear/xml/easyxml.hxx>
|
||||||
|
|
||||||
#include <Main/globals.hxx>
|
#include <Main/globals.hxx>
|
||||||
#include <Main/fg_props.hxx>
|
#include <Main/fg_props.hxx>
|
||||||
|
|
||||||
|
@ -25,10 +27,12 @@
|
||||||
#include "dynamics.hxx"
|
#include "dynamics.hxx"
|
||||||
#include "runwayprefs.hxx"
|
#include "runwayprefs.hxx"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
XMLLoader::XMLLoader() {}
|
XMLLoader::XMLLoader() {}
|
||||||
XMLLoader::~XMLLoader() {}
|
XMLLoader::~XMLLoader() {}
|
||||||
|
|
||||||
string XMLLoader::expandICAODirs(const string in){
|
string XMLLoader::expandICAODirs(const string& in){
|
||||||
//cerr << "Expanding " << in << endl;
|
//cerr << "Expanding " << in << endl;
|
||||||
if (in.size() == 4) {
|
if (in.size() == 4) {
|
||||||
char buffer[11];
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,23 +16,40 @@
|
||||||
#ifndef _XML_LOADER_HXX_
|
#ifndef _XML_LOADER_HXX_
|
||||||
#define _XML_LOADER_HXX_
|
#define _XML_LOADER_HXX_
|
||||||
|
|
||||||
#include <simgear/xml/easyxml.hxx>
|
|
||||||
|
|
||||||
class FGAirportDynamics;
|
class FGAirportDynamics;
|
||||||
class FGRunwayPreference;
|
class FGRunwayPreference;
|
||||||
class FGSidStar;
|
class FGSidStar;
|
||||||
|
|
||||||
|
class XMLVisitor; // ffrom easyxml.hxx
|
||||||
|
|
||||||
class XMLLoader {
|
class XMLLoader {
|
||||||
public:
|
public:
|
||||||
XMLLoader();
|
XMLLoader();
|
||||||
~XMLLoader();
|
~XMLLoader();
|
||||||
static string expandICAODirs(const string in);
|
static string expandICAODirs(const std::string& in);
|
||||||
|
|
||||||
static void load(FGRunwayPreference* p);
|
static void load(FGRunwayPreference* p);
|
||||||
static void load(FGAirportDynamics* d);
|
static void load(FGAirportDynamics* d);
|
||||||
static void load(FGSidStar* s);
|
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
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue