ICAO.threshold.xml works read-only.
This commit is contained in:
parent
5f9c17bd69
commit
ffa7854ed9
4 changed files with 68 additions and 81 deletions
|
@ -148,7 +148,7 @@ unsigned int FGAirport::numHelipads() const
|
||||||
FGRunwayRef FGAirport::getRunwayByIndex(unsigned int aIndex) const
|
FGRunwayRef FGAirport::getRunwayByIndex(unsigned int aIndex) const
|
||||||
{
|
{
|
||||||
loadRunways();
|
loadRunways();
|
||||||
return loadById<FGRunway>(mRunways, aIndex);
|
return mRunways.at(aIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -166,10 +166,8 @@ FGRunwayMap FGAirport::getRunwayMap() const
|
||||||
|
|
||||||
double minLengthFt = fgGetDouble("/sim/navdb/min-runway-length-ft");
|
double minLengthFt = fgGetDouble("/sim/navdb/min-runway-length-ft");
|
||||||
|
|
||||||
BOOST_FOREACH(PositionedID id, mRunways)
|
BOOST_FOREACH(FGRunwayRef rwy, mRunways)
|
||||||
{
|
{
|
||||||
FGRunway* rwy = loadById<FGRunway>(id);
|
|
||||||
|
|
||||||
// ignore unusably short runways
|
// ignore unusably short runways
|
||||||
// TODO other methods don't check this...
|
// TODO other methods don't check this...
|
||||||
if( rwy->lengthFt() >= minLengthFt )
|
if( rwy->lengthFt() >= minLengthFt )
|
||||||
|
@ -197,8 +195,14 @@ FGHelipadMap FGAirport::getHelipadMap() const
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
bool FGAirport::hasRunwayWithIdent(const std::string& aIdent) const
|
bool FGAirport::hasRunwayWithIdent(const std::string& aIdent) const
|
||||||
{
|
{
|
||||||
return flightgear::NavDataCache::instance()
|
loadRunways();
|
||||||
->airportItemWithIdent(guid(), FGPositioned::RUNWAY, aIdent) != 0;
|
BOOST_FOREACH(FGRunwayRef rwy, mRunways) {
|
||||||
|
if (rwy->ident() == aIdent) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -211,16 +215,15 @@ bool FGAirport::hasHelipadWithIdent(const std::string& aIdent) const
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
FGRunwayRef FGAirport::getRunwayByIdent(const std::string& aIdent) const
|
FGRunwayRef FGAirport::getRunwayByIdent(const std::string& aIdent) const
|
||||||
{
|
{
|
||||||
PositionedID id =
|
loadRunways();
|
||||||
flightgear::NavDataCache::instance()
|
BOOST_FOREACH(FGRunwayRef rwy, mRunways) {
|
||||||
->airportItemWithIdent(guid(), FGPositioned::RUNWAY, aIdent);
|
if (rwy->ident() == aIdent) {
|
||||||
|
return rwy;
|
||||||
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 loadById<FGRunway>(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");
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -255,14 +258,7 @@ FGRunwayRef FGAirport::findBestRunwayForHeading(double aHeading, struct FindBest
|
||||||
fbrfhp.ilsWeight = searchNode->getDoubleValue("ils-weight", fbrfhp.ilsWeight );
|
fbrfhp.ilsWeight = searchNode->getDoubleValue("ils-weight", fbrfhp.ilsWeight );
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(PositionedID id, mRunways) {
|
BOOST_FOREACH(FGRunwayRef rwy, mRunways) {
|
||||||
FGRunway* rwy = loadById<FGRunway>(id);
|
|
||||||
// bug http://code.google.com/p/flightgear-bugs/issues/detail?id=1149
|
|
||||||
// (and probably some other issues besides).
|
|
||||||
if (rwy->type() == FGPositioned::HELIPAD) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
double good = rwy->score( fbrfhp.lengthWeight, fbrfhp.widthWeight, fbrfhp.surfaceWeight, fbrfhp.ilsWeight );
|
double good = rwy->score( fbrfhp.lengthWeight, fbrfhp.widthWeight, fbrfhp.surfaceWeight, fbrfhp.ilsWeight );
|
||||||
double dev = aHeading - rwy->headingDeg();
|
double dev = aHeading - rwy->headingDeg();
|
||||||
SG_NORMALIZE_RANGE(dev, -180.0, 180.0);
|
SG_NORMALIZE_RANGE(dev, -180.0, 180.0);
|
||||||
|
@ -286,9 +282,7 @@ FGRunwayRef FGAirport::findBestRunwayForPos(const SGGeod& aPos) const
|
||||||
FGRunway* result = NULL;
|
FGRunway* result = NULL;
|
||||||
double currentLowestDev = 180.0;
|
double currentLowestDev = 180.0;
|
||||||
|
|
||||||
BOOST_FOREACH(PositionedID id, mRunways) {
|
BOOST_FOREACH(FGRunwayRef rwy, mRunways) {
|
||||||
FGRunway* rwy = loadById<FGRunway>(id);
|
|
||||||
|
|
||||||
double inboundCourse = SGGeodesy::courseDeg(aPos, rwy->end());
|
double inboundCourse = SGGeodesy::courseDeg(aPos, rwy->end());
|
||||||
double dev = inboundCourse - rwy->headingDeg();
|
double dev = inboundCourse - rwy->headingDeg();
|
||||||
SG_NORMALIZE_RANGE(dev, -180.0, 180.0);
|
SG_NORMALIZE_RANGE(dev, -180.0, 180.0);
|
||||||
|
@ -309,8 +303,7 @@ bool FGAirport::hasHardRunwayOfLengthFt(double aLengthFt) const
|
||||||
{
|
{
|
||||||
loadRunways();
|
loadRunways();
|
||||||
|
|
||||||
BOOST_FOREACH(PositionedID id, mRunways) {
|
BOOST_FOREACH(FGRunwayRef rwy, mRunways) {
|
||||||
FGRunway* rwy = loadById<FGRunway>(id);
|
|
||||||
if (rwy->isHardSurface() && (rwy->lengthFt() >= aLengthFt)) {
|
if (rwy->isHardSurface() && (rwy->lengthFt() >= aLengthFt)) {
|
||||||
return true; // we're done!
|
return true; // we're done!
|
||||||
}
|
}
|
||||||
|
@ -326,8 +319,7 @@ FGRunwayList FGAirport::getRunwaysWithoutReciprocals() const
|
||||||
|
|
||||||
FGRunwayList r;
|
FGRunwayList r;
|
||||||
|
|
||||||
BOOST_FOREACH(PositionedID id, mRunways) {
|
BOOST_FOREACH(FGRunwayRef rwy, mRunways) {
|
||||||
FGRunway* rwy = loadById<FGRunway>(id);
|
|
||||||
FGRunway* recip = rwy->reciprocalRunway();
|
FGRunway* recip = rwy->reciprocalRunway();
|
||||||
if (recip) {
|
if (recip) {
|
||||||
FGRunwayList::iterator it = std::find(r.begin(), r.end(), recip);
|
FGRunwayList::iterator it = std::find(r.begin(), r.end(), recip);
|
||||||
|
@ -508,6 +500,12 @@ const FGAirport *fgFindAirportID( const std::string& id)
|
||||||
return FGAirport::findByIdent(id);
|
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
|
void FGAirport::loadRunways() const
|
||||||
{
|
{
|
||||||
if (mRunwaysLoaded) {
|
if (mRunwaysLoaded) {
|
||||||
|
@ -517,7 +515,10 @@ void FGAirport::loadRunways() const
|
||||||
loadSceneryDefinitions();
|
loadSceneryDefinitions();
|
||||||
|
|
||||||
mRunwaysLoaded = true;
|
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
|
void FGAirport::loadHelipads() const
|
||||||
|
@ -529,7 +530,7 @@ void FGAirport::loadHelipads() const
|
||||||
loadSceneryDefinitions();
|
loadSceneryDefinitions();
|
||||||
|
|
||||||
mHelipadsLoaded = true;
|
mHelipadsLoaded = true;
|
||||||
mHelipads = flightgear::NavDataCache::instance()->airportItemsOfType(guid(), FGPositioned::HELIPAD);
|
mHelipads = itemsOfType(FGPositioned::HELIPAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGAirport::loadTaxiways() const
|
void FGAirport::loadTaxiways() const
|
||||||
|
@ -539,7 +540,7 @@ void FGAirport::loadTaxiways() const
|
||||||
}
|
}
|
||||||
|
|
||||||
mTaxiwaysLoaded = true;
|
mTaxiwaysLoaded = true;
|
||||||
mTaxiways = flightgear::NavDataCache::instance()->airportItemsOfType(guid(), FGPositioned::TAXIWAY);
|
mTaxiways = itemsOfType(FGPositioned::TAXIWAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGAirport::loadProcedures() const
|
void FGAirport::loadProcedures() const
|
||||||
|
@ -561,31 +562,18 @@ void FGAirport::loadProcedures() const
|
||||||
|
|
||||||
void FGAirport::loadSceneryDefinitions() const
|
void FGAirport::loadSceneryDefinitions() const
|
||||||
{
|
{
|
||||||
NavDataCache* cache = NavDataCache::instance();
|
|
||||||
if (cache->isReadOnly()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SGPath path;
|
SGPath path;
|
||||||
if (!XMLLoader::findAirportData(ident(), "threshold", path)) {
|
if (!XMLLoader::findAirportData(ident(), "threshold", path)) {
|
||||||
return; // no XML threshold data
|
return; // no XML threshold data
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cache->isCachedFileModified(path)) {
|
try {
|
||||||
// cached values are correct, we're all done
|
SGPropertyNode_ptr rootNode = new SGPropertyNode;
|
||||||
return;
|
readProperties(path.str(), rootNode);
|
||||||
|
const_cast<FGAirport*>(this)->readThresholdData(rootNode);
|
||||||
|
} catch (sg_exception& e) {
|
||||||
|
SG_LOG(SG_NAVAID, SG_WARN, ident() << "loading threshold XML failed:" << e.getFormattedMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
flightgear::NavDataCache::Transaction txn(cache);
|
|
||||||
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::readThresholdData(SGPropertyNode* aRoot)
|
||||||
|
@ -609,11 +597,6 @@ void FGAirport::processThreshold(SGPropertyNode* aThreshold)
|
||||||
std::string rwyIdent(aThreshold->getStringValue("rwy"));
|
std::string rwyIdent(aThreshold->getStringValue("rwy"));
|
||||||
NavDataCache* cache = NavDataCache::instance();
|
NavDataCache* cache = NavDataCache::instance();
|
||||||
PositionedID id = cache->airportItemWithIdent(guid(), FGPositioned::RUNWAY, rwyIdent);
|
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"),
|
double lon = aThreshold->getDoubleValue("lon"),
|
||||||
lat = aThreshold->getDoubleValue("lat");
|
lat = aThreshold->getDoubleValue("lat");
|
||||||
|
@ -623,8 +606,29 @@ void FGAirport::processThreshold(SGPropertyNode* aThreshold)
|
||||||
double newDisplacedThreshold = aThreshold->getDoubleValue("displ-m");
|
double newDisplacedThreshold = aThreshold->getDoubleValue("displ-m");
|
||||||
double newStopway = aThreshold->getDoubleValue("stopw-m");
|
double newStopway = aThreshold->getDoubleValue("stopw-m");
|
||||||
|
|
||||||
cache->updateRunwayThreshold(id, newThreshold,
|
if (id == 0) {
|
||||||
newHeading, newDisplacedThreshold, newStopway);
|
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
|
SGGeod FGAirport::getTowerLocation() const
|
||||||
|
|
|
@ -303,7 +303,9 @@ private:
|
||||||
* Helper to parse property data loaded from an ICAO.twr.xml file
|
* Helper to parse property data loaded from an ICAO.twr.xml file
|
||||||
*/
|
*/
|
||||||
void readTowerData(SGPropertyNode* aRoot);
|
void readTowerData(SGPropertyNode* aRoot);
|
||||||
|
|
||||||
|
PositionedIDVec itemsOfType(FGPositioned::Type ty) const;
|
||||||
|
|
||||||
std::string _name;
|
std::string _name;
|
||||||
bool _has_metar;
|
bool _has_metar;
|
||||||
FGAirportDynamics *_dynamics;
|
FGAirportDynamics *_dynamics;
|
||||||
|
@ -321,8 +323,9 @@ private:
|
||||||
mutable bool mTaxiwaysLoaded;
|
mutable bool mTaxiwaysLoaded;
|
||||||
mutable bool mProceduresLoaded;
|
mutable bool mProceduresLoaded;
|
||||||
bool mILSDataLoaded;
|
bool mILSDataLoaded;
|
||||||
|
|
||||||
|
mutable std::vector<FGRunwayRef> mRunways;
|
||||||
|
|
||||||
mutable PositionedIDVec mRunways;
|
|
||||||
mutable PositionedIDVec mHelipads;
|
mutable PositionedIDVec mHelipads;
|
||||||
mutable PositionedIDVec mTaxiways;
|
mutable PositionedIDVec mTaxiways;
|
||||||
PositionedIDVec mPavements;
|
PositionedIDVec mPavements;
|
||||||
|
|
|
@ -474,7 +474,6 @@ public:
|
||||||
setRunwayReciprocal = prepare("UPDATE runway SET reciprocal=?2 WHERE rowid=?1");
|
setRunwayReciprocal = prepare("UPDATE runway SET reciprocal=?2 WHERE rowid=?1");
|
||||||
setRunwayILS = prepare("UPDATE runway SET ils=?2 WHERE rowid=?1");
|
setRunwayILS = prepare("UPDATE runway SET ils=?2 WHERE rowid=?1");
|
||||||
setNavaidColocated = prepare("UPDATE navaid SET colocated=?2 WHERE rowid=?1");
|
setNavaidColocated = prepare("UPDATE navaid SET colocated=?2 WHERE rowid=?1");
|
||||||
updateRunwayThreshold = prepare("UPDATE runway SET heading=?2, displaced_threshold=?3, stopway=?4 WHERE rowid=?1");
|
|
||||||
|
|
||||||
insertPositionedQuery = prepare("INSERT INTO positioned "
|
insertPositionedQuery = prepare("INSERT INTO positioned "
|
||||||
"(type, ident, name, airport, lon, lat, elev_m, octree_node, "
|
"(type, ident, name, airport, lon, lat, elev_m, octree_node, "
|
||||||
|
@ -899,7 +898,7 @@ public:
|
||||||
sqlite3_stmt_ptr insertPositionedQuery, insertAirport, insertTower, insertRunway,
|
sqlite3_stmt_ptr insertPositionedQuery, insertAirport, insertTower, insertRunway,
|
||||||
insertCommStation, insertNavaid;
|
insertCommStation, insertNavaid;
|
||||||
sqlite3_stmt_ptr setAirportMetar, setRunwayReciprocal, setRunwayILS, setNavaidColocated,
|
sqlite3_stmt_ptr setAirportMetar, setRunwayReciprocal, setRunwayILS, setNavaidColocated,
|
||||||
setAirportPos, updateRunwayThreshold, updateILS;
|
setAirportPos, updateILS;
|
||||||
sqlite3_stmt_ptr removePOIQuery;
|
sqlite3_stmt_ptr removePOIQuery;
|
||||||
|
|
||||||
sqlite3_stmt_ptr findClosestWithIdent;
|
sqlite3_stmt_ptr findClosestWithIdent;
|
||||||
|
@ -1566,21 +1565,6 @@ void NavDataCache::setRunwayILS(PositionedID runway, PositionedID ils)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavDataCache::updateRunwayThreshold(PositionedID runwayID, const SGGeod &aThreshold,
|
|
||||||
double aHeading, double aDisplacedThreshold,
|
|
||||||
double aStopway)
|
|
||||||
{
|
|
||||||
// update the runway information
|
|
||||||
sqlite3_bind_int64(d->updateRunwayThreshold, 1, runwayID);
|
|
||||||
sqlite3_bind_double(d->updateRunwayThreshold, 2, aHeading);
|
|
||||||
sqlite3_bind_double(d->updateRunwayThreshold, 3, aDisplacedThreshold);
|
|
||||||
sqlite3_bind_double(d->updateRunwayThreshold, 4, aStopway);
|
|
||||||
d->execUpdate(d->updateRunwayThreshold);
|
|
||||||
|
|
||||||
// now update the positional data
|
|
||||||
updatePosition(runwayID, aThreshold);
|
|
||||||
}
|
|
||||||
|
|
||||||
PositionedID
|
PositionedID
|
||||||
NavDataCache::insertNavaid(FGPositioned::Type ty, const string& ident,
|
NavDataCache::insertNavaid(FGPositioned::Type ty, const string& ident,
|
||||||
const string& name, const SGGeod& pos,
|
const string& name, const SGGeod& pos,
|
||||||
|
|
|
@ -102,10 +102,6 @@ public:
|
||||||
void setRunwayReciprocal(PositionedID runway, PositionedID recip);
|
void setRunwayReciprocal(PositionedID runway, PositionedID recip);
|
||||||
void setRunwayILS(PositionedID runway, PositionedID ils);
|
void setRunwayILS(PositionedID runway, PositionedID ils);
|
||||||
|
|
||||||
void updateRunwayThreshold(PositionedID runwayID, const SGGeod &aThreshold,
|
|
||||||
double aHeading, double aDisplacedThreshold,
|
|
||||||
double aStopway);
|
|
||||||
|
|
||||||
PositionedID insertNavaid(FGPositioned::Type ty, const std::string& ident,
|
PositionedID insertNavaid(FGPositioned::Type ty, const std::string& ident,
|
||||||
const std::string& name, const SGGeod& pos, int freq, int range, double multiuse,
|
const std::string& name, const SGGeod& pos, int freq, int range, double multiuse,
|
||||||
PositionedID apt, PositionedID runway);
|
PositionedID apt, PositionedID runway);
|
||||||
|
|
Loading…
Add table
Reference in a new issue