X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FNavaids%2Fnavrecord.cxx;h=2029d2b7d3e004a2aa10c6b4c0de1432251f6741;hb=a6db6d89ff41a619569e6433409e8bf62ff98499;hp=c2ab0e9a7706df98c2b24cae498f69ffa10ca41a;hpb=030742fa4ae7d99facb517381da71fa404c4ee2b;p=flightgear.git diff --git a/src/Navaids/navrecord.cxx b/src/Navaids/navrecord.cxx index c2ab0e9a7..2029d2b7d 100644 --- a/src/Navaids/navrecord.cxx +++ b/src/Navaids/navrecord.cxx @@ -27,13 +27,20 @@ #include #include +#include #include #include +#include +#include +#include -#include "Navaids/navrecord.hxx" -#include "Navaids/navdb.hxx" -#include "Airports/runways.hxx" -#include "Main/fg_props.hxx" +#include +#include +#include +#include +#include + +#include
FGNavRecord::FGNavRecord(Type aTy, const std::string& aIdent, const std::string& aName, const SGGeod& aPos, @@ -43,6 +50,7 @@ FGNavRecord::FGNavRecord(Type aTy, const std::string& aIdent, range(aRange), multiuse(aMultiuse), _name(aName), + mRunway(NULL), serviceable(true), trans_ident(aIdent) { @@ -82,10 +90,19 @@ void FGNavRecord::initAirportRelation() return; // not airport-located } - FGRunway* runway = getRunwayFromName(_name); + mRunway = getRunwayFromName(_name); + + if (type() != GS) { + readAirportSceneryData(); + } + // fudge elevation to the runway elevation if it's not specified if (fabs(elevation()) < 0.01) { - mPosition.setElevationFt(runway->elevation()); + mPosition.setElevationFt(mRunway->elevation()); + } + + if (type() == ILS) { + mRunway->setILS(this); } // align localizers with their runway @@ -96,35 +113,68 @@ void FGNavRecord::initAirportRelation() double threshold = fgGetDouble( "/sim/navdb/localizers/auto-align-threshold-deg", 5.0 ); - alignLocaliserWithRunway(runway, threshold); + alignLocaliserWithRunway(threshold); + } +} + +void FGNavRecord::readAirportSceneryData() +{ + // 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")) { + return; } + + SGPath path; + SGPropertyNode_ptr rootNode = new SGPropertyNode; + if (!XMLLoader::findAirportData(mRunway->airport()->ident(), "ils", path)) { + return; + } + + readProperties(path.str(), rootNode); + SGPropertyNode* runwayNode, *ilsNode; + for (int i=0; (runwayNode = rootNode->getChild("runway", i)) != NULL; ++i) { + for (int j=0; (ilsNode = runwayNode->getChild("ils", j)) != NULL; ++j) { + // must match on both nav-ident and runway ident, to support the following: + // - runways with multiple distinct ILS installations (KEWD, for example) + // - runways where both ends share the same nav ident (LFAT, for example) + if ((ilsNode->getStringValue("nav-id") == ident()) && + (ilsNode->getStringValue("rwy") == mRunway->ident())) { + processSceneryILS(ilsNode); + return; + } + } // of ILS iteration + } // of runway iteration } -void FGNavRecord::alignLocaliserWithRunway(FGRunway* aRunway, double aThreshold) +void FGNavRecord::processSceneryILS(SGPropertyNode* aILSNode) +{ + double hdgDeg = aILSNode->getDoubleValue("hdg-deg"), + lon = aILSNode->getDoubleValue("lon"), + lat = aILSNode->getDoubleValue("lat"), + elevM = aILSNode->getDoubleValue("elev-m"); + + mPosition = SGGeod::fromDegM(lon, lat, elevM); + multiuse = hdgDeg; +} + +void FGNavRecord::alignLocaliserWithRunway(double aThreshold) { // find the distance from the threshold to the localizer - SGGeod runwayThreshold(aRunway->threshold()); - double dist, az1, az2; - SGGeodesy::inverse(mPosition, runwayThreshold, az1, az2, dist); + double dist = SGGeodesy::distanceM(mPosition, mRunway->threshold()); // back project that distance along the runway center line - SGGeod newPos = aRunway->pointOnCenterline(dist); + SGGeod newPos = mRunway->pointOnCenterline(dist); - double hdg_diff = get_multiuse() - aRunway->headingDeg(); - - // clamp to [-180.0 ... 180.0] - if ( hdg_diff < -180.0 ) { - hdg_diff += 360.0; - } else if ( hdg_diff > 180.0 ) { - hdg_diff -= 360.0; - } + double hdg_diff = get_multiuse() - mRunway->headingDeg(); + SG_NORMALIZE_RANGE(hdg_diff, -180.0, 180.0); if ( fabs(hdg_diff) <= aThreshold ) { - mPosition = newPos; - set_multiuse( aRunway->headingDeg() ); + mPosition = SGGeod::fromGeodFt(newPos, mPosition.getElevationFt()); + set_multiuse( mRunway->headingDeg() ); } else { SG_LOG(SG_GENERAL, SG_WARN, "localizer:" << ident() << ", aligning with runway " - << aRunway->ident() << " exceeded heading threshold"); + << mRunway->ident() << " exceeded heading threshold"); } }