1
0
Fork 0

Support multiple nav.dat and fix.dat files

This commit is contained in:
Szymon Acedański 2017-02-25 17:38:00 +01:00
parent b9dbe9c9e7
commit 4403f22a8b
8 changed files with 144 additions and 113 deletions

View file

@ -99,7 +99,6 @@ void APTLoader::readAptDatFile(const SGPath &aptdb_file,
sg_location(aptdb_file)); sg_location(aptdb_file));
} }
SG_LOG( SG_GENERAL, SG_INFO, "Opened apt.dat file: '" << apt_dat << "'" );
string line; string line;
unsigned int rowCode = 0; // terminology used in the apt.dat format spec unsigned int rowCode = 0; // terminology used in the apt.dat format spec

View file

@ -649,7 +649,7 @@ fgInitNav ()
SGPath path(globals->get_fg_root()); SGPath path(globals->get_fg_root());
path.append( "Navaids/TACAN_freq.dat" ); path.append( "Navaids/TACAN_freq.dat" );
flightgear::loadTacan(path, channellist); flightgear::NavLoader().loadTacan(path, channellist);
return true; return true;
} }

View file

@ -351,10 +351,9 @@ public:
} }
bool isCachedFileModified(const SGPath& path, bool verbose); bool isCachedFileModified(const SGPath& path, bool verbose);
NavDataCache::DatFilesGroupInfo findDatFiles( void findDatFiles(NavDataCache::DatFileType datFileType);
NavDataCache::DatFileType datFileType) const;
bool areDatFilesModified( bool areDatFilesModified(
const NavDataCache::DatFilesGroupInfo& datFilesGroupInfo, NavDataCache::DatFileType datFileType,
bool verbose); bool verbose);
void callSqlite(int result, const string& sql) void callSqlite(int result, const string& sql)
@ -872,8 +871,8 @@ public:
bool transactionAborted; bool transactionAborted;
sqlite3_stmt_ptr beginTransactionStmt, commitTransactionStmt, rollbackTransactionStmt; sqlite3_stmt_ptr beginTransactionStmt, commitTransactionStmt, rollbackTransactionStmt;
NavDataCache::DatFilesGroupInfo aptDatFilesInfo; std::map<DatFileType, NavDataCache::DatFilesGroupInfo> datFilesInfo;
SGPath metarDatPath, navDatPath, fixDatPath, poiDatPath, SGPath metarDatPath, poiDatPath,
carrierDatPath, airwayDatPath; carrierDatPath, airwayDatPath;
sqlite3_stmt_ptr readPropertyQuery, writePropertyQuery, sqlite3_stmt_ptr readPropertyQuery, writePropertyQuery,
@ -1039,8 +1038,9 @@ bool NavDataCache::NavDataCachePrivate::isCachedFileModified(const SGPath& path,
// $FG_ROOT/Airports/apt.dat.gz for the 'apt' type). // $FG_ROOT/Airports/apt.dat.gz for the 'apt' type).
// Also compute the total size of all these files (in bytes), which is useful // Also compute the total size of all these files (in bytes), which is useful
// for progress information. // for progress information.
NavDataCache::DatFilesGroupInfo NavDataCache::NavDataCachePrivate::findDatFiles( // The result is stored in the datFilesInfo field.
NavDataCache::DatFileType datFileType) const void NavDataCache::NavDataCachePrivate::findDatFiles(
NavDataCache::DatFileType datFileType)
{ {
NavDataCache::DatFilesGroupInfo result; NavDataCache::DatFilesGroupInfo result;
SGPath visitedPath; // to avoid duplicates and time wasting SGPath visitedPath; // to avoid duplicates and time wasting
@ -1093,7 +1093,7 @@ NavDataCache::DatFilesGroupInfo NavDataCache::NavDataCachePrivate::findDatFiles(
result.totalSize += defaultDatFile.sizeInBytes(); result.totalSize += defaultDatFile.sizeInBytes();
} }
return result; datFilesInfo[datFileType] = result;
} }
// Compare: // Compare:
@ -1105,12 +1105,14 @@ NavDataCache::DatFilesGroupInfo NavDataCache::NavDataCachePrivate::findDatFiles(
// This comparison is sensitive to the number and order of the files, // This comparison is sensitive to the number and order of the files,
// their respective SGPath::realpath() and SGPath::modTime(). // their respective SGPath::realpath() and SGPath::modTime().
bool NavDataCache::NavDataCachePrivate::areDatFilesModified( bool NavDataCache::NavDataCachePrivate::areDatFilesModified(
const NavDataCache::DatFilesGroupInfo& datFilesGroupInfo, NavDataCache::DatFileType datFileType,
bool verbose) bool verbose)
{ {
// 'apt' or 'metar' or 'fix' or... // 'apt' or 'metar' or 'fix' or...
const NavDataCache::DatFilesGroupInfo& datFilesGroupInfo =
datFilesInfo[datFileType];
const string datTypeStr = const string datTypeStr =
NavDataCache::datTypeStr[datFilesGroupInfo.datFileType]; NavDataCache::datTypeStr[datFileType];
const string_list cachedFiles = outer->readOrderedStringListProperty( const string_list cachedFiles = outer->readOrderedStringListProperty(
datTypeStr + ".dat files", &SGPath::pathListSep); datTypeStr + ".dat files", &SGPath::pathListSep);
const PathList& datFiles = datFilesGroupInfo.paths; const PathList& datFiles = datFilesGroupInfo.paths;
@ -1279,23 +1281,18 @@ NavDataCache* NavDataCache::instance()
void NavDataCache::updateListsOfDatFiles() { void NavDataCache::updateListsOfDatFiles() {
// All $scenery_path/NavData/apt/*.dat[.gz] files found inside scenery // All $scenery_path/NavData/apt/*.dat[.gz] files found inside scenery
// paths, plus $FG_ROOT/Airports/apt.dat.gz (order matters). // paths, plus $FG_ROOT/Airports/apt.dat.gz (order matters).
d->aptDatFilesInfo = d->findDatFiles(DATFILETYPE_APT); d->findDatFiles(DATFILETYPE_APT);
// Trivial extension to the other types of dat files:
// d->navDatFilesInfo = d->findDatFiles(DATFILETYPE_NAV); // All $scenery_path/NavData/{nav,fix}/*.dat[.gz] files found inside scenery
// d->fixDatFilesInfo = d->findDatFiles(DATFILETYPE_FIX); // paths, plus $FG_ROOT/Navaids/{nav,fix}.dat.gz (order matters).
// etc. d->findDatFiles(DATFILETYPE_NAV);
// d->findDatFiles(DATFILETYPE_FIX);
// These ones are still managed the "old" way (no search through scenery // These ones are still managed the "old" way (no search through scenery
// paths). // paths).
d->metarDatPath = SGPath(globals->get_fg_root()); d->metarDatPath = SGPath(globals->get_fg_root());
d->metarDatPath.append("Airports/metar.dat.gz"); d->metarDatPath.append("Airports/metar.dat.gz");
d->navDatPath = SGPath(globals->get_fg_root());
d->navDatPath.append("Navaids/nav.dat.gz");
d->fixDatPath = SGPath(globals->get_fg_root());
d->fixDatPath.append("Navaids/fix.dat.gz");
d->poiDatPath = SGPath(globals->get_fg_root()); d->poiDatPath = SGPath(globals->get_fg_root());
d->poiDatPath.append("Navaids/poi.dat.gz"); d->poiDatPath.append("Navaids/poi.dat.gz");
@ -1306,20 +1303,16 @@ void NavDataCache::updateListsOfDatFiles() {
d->airwayDatPath.append("Navaids/awy.dat.gz"); d->airwayDatPath.append("Navaids/awy.dat.gz");
} }
NavDataCache::DatFilesGroupInfo const NavDataCache::DatFilesGroupInfo&
NavDataCache::getDatFilesInfo(DatFileType datFileType) const NavDataCache::getDatFilesInfo(DatFileType datFileType) const
{ {
switch (datFileType) { auto iter = d->datFilesInfo.find(datFileType);
case DATFILETYPE_APT: if (iter == d->datFilesInfo.end()) {
return d->aptDatFilesInfo; throw sg_error("NavCache: requesting info about the list of " +
default: datTypeStr[datFileType] + " dat files, however this is not "
SG_LOG(SG_NAVCACHE, SG_ALERT, "implemented yet!");
"NavCache: requesting info about the list of " <<
datTypeStr[datFileType] << " dat files, however this is not "
"implemented yet!");
assert(false);
return DatFilesGroupInfo();
} }
return iter->second;
} }
bool NavDataCache::isRebuildRequired() bool NavDataCache::isRebuildRequired()
@ -1333,10 +1326,10 @@ bool NavDataCache::isRebuildRequired()
return true; return true;
} }
if (d->areDatFilesModified(d->aptDatFilesInfo, true) || if (d->areDatFilesModified(DATFILETYPE_APT, true) ||
d->isCachedFileModified(d->metarDatPath, true) || d->isCachedFileModified(d->metarDatPath, true) ||
d->isCachedFileModified(d->navDatPath, true) || d->areDatFilesModified(DATFILETYPE_NAV, true) ||
d->isCachedFileModified(d->fixDatPath, true) || d->areDatFilesModified(DATFILETYPE_FIX, true) ||
d->isCachedFileModified(d->carrierDatPath, true) || d->isCachedFileModified(d->carrierDatPath, true) ||
// since POI loading is disabled on Windows, don't check for it // since POI loading is disabled on Windows, don't check for it
// this caused: https://code.google.com/p/flightgear-bugs/issues/detail?id=1227 // this caused: https://code.google.com/p/flightgear-bugs/issues/detail?id=1227
@ -1386,6 +1379,37 @@ void NavDataCache::setRebuildPhaseProgress(RebuildPhase ph, unsigned int percent
d->rebuilder->setProgress(ph, percent); d->rebuilder->setProgress(ph, percent);
} }
void NavDataCache::loadDatFiles(
DatFileType type,
std::function<void(const SGPath&, std::size_t, std::size_t)> loader)
{
SGTimeStamp st;
string typeStr = datTypeStr[type];
string_list datFiles;
NavDataCache::DatFilesGroupInfo datFilesInfo = getDatFilesInfo(type);
const PathList datPaths = datFilesInfo.paths;
std::size_t bytesReadSoFar = 0;
st.stamp();
for (PathList::const_iterator it = datPaths.begin();
it != datPaths.end(); it++) {
string path = it->realpath().utf8Str();
datFiles.push_back(path);
SG_LOG(SG_GENERAL, SG_INFO,
"Loading " + typeStr + ".dat file: '" << path << "'");
loader(*it, bytesReadSoFar, datFilesInfo.totalSize);
bytesReadSoFar += it->sizeInBytes();
stampCacheFile(*it); // this uses the realpath() of the file
}
// Store the list of .dat files we have loaded
writeOrderedStringListProperty(typeStr + ".dat files", datFiles,
&SGPath::pathListSep);
SG_LOG(SG_NAVCACHE, SG_INFO,
typeStr + ".dat files load took: " <<
st.elapsedMSec());
}
void NavDataCache::doRebuild() void NavDataCache::doRebuild()
{ {
try { try {
@ -1400,45 +1424,30 @@ void NavDataCache::doRebuild()
{ {
Transaction txn(this); Transaction txn(this);
APTLoader aptLoader; APTLoader aptLoader;
string_list aptDatFiles; FixesLoader fixesLoader;
const PathList aptDatPaths = d->aptDatFilesInfo.paths; NavLoader navLoader;
std::size_t bytesReadSoFar = 0;
using namespace std::placeholders; // for _1, _2, _3...
loadDatFiles(DATFILETYPE_APT,
std::bind(&APTLoader::readAptDatFile, &aptLoader, _1, _2, _3));
st.stamp(); st.stamp();
for (PathList::const_iterator it = aptDatPaths.begin();
it != aptDatPaths.end(); it++) {
aptDatFiles.push_back(it->realpath().utf8Str());
aptLoader.readAptDatFile(*it, bytesReadSoFar,
d->aptDatFilesInfo.totalSize);
bytesReadSoFar += it->sizeInBytes();
stampCacheFile(*it); // this uses the realpath() of the file
}
setRebuildPhaseProgress(REBUILD_UNKNOWN); setRebuildPhaseProgress(REBUILD_UNKNOWN);
SG_LOG(SG_NAVCACHE, SG_DEBUG, "Loading airports"); SG_LOG(SG_NAVCACHE, SG_DEBUG, "Processing airports");
aptLoader.loadAirports(); // load airport data into the NavCache aptLoader.loadAirports(); // load airport data into the NavCache
// Store the list of apt.dat files we have loaded
writeOrderedStringListProperty(
datTypeStr[DATFILETYPE_APT] + ".dat files", aptDatFiles,
&SGPath::pathListSep);
SG_LOG(SG_NAVCACHE, SG_INFO, SG_LOG(SG_NAVCACHE, SG_INFO,
datTypeStr[DATFILETYPE_APT] + ".dat files load took:" << "processing airports took:" <<
st.elapsedMSec()); st.elapsedMSec());
setRebuildPhaseProgress(REBUILD_UNKNOWN); setRebuildPhaseProgress(REBUILD_UNKNOWN);
metarDataLoad(d->metarDatPath); metarDataLoad(d->metarDatPath);
stampCacheFile(d->metarDatPath); stampCacheFile(d->metarDatPath);
st.stamp(); loadDatFiles(DATFILETYPE_FIX,
FixesLoader().loadFixes(d->fixDatPath); std::bind(&FixesLoader::loadFixes, &fixesLoader, _1, _2, _3));
stampCacheFile(d->fixDatPath); loadDatFiles(DATFILETYPE_NAV,
SG_LOG(SG_NAVCACHE, SG_INFO, "fix.dat load took:" << st.elapsedMSec()); std::bind(&NavLoader::loadNav, &navLoader, _1, _2, _3));
st.stamp();
navDBInit(d->navDatPath);
stampCacheFile(d->navDatPath);
SG_LOG(SG_NAVCACHE, SG_INFO, "nav.dat load took:" << st.elapsedMSec());
setRebuildPhaseProgress(REBUILD_UNKNOWN); setRebuildPhaseProgress(REBUILD_UNKNOWN);
st.stamp(); st.stamp();
@ -1466,7 +1475,8 @@ void NavDataCache::doRebuild()
{ {
Transaction txn(this); Transaction txn(this);
loadCarrierNav(d->carrierDatPath); NavLoader navLoader;
navLoader.loadCarrierNav(d->carrierDatPath);
stampCacheFile(d->carrierDatPath); stampCacheFile(d->carrierDatPath);
st.stamp(); st.stamp();

View file

@ -26,6 +26,7 @@
#include <memory> #include <memory>
#include <cstddef> // for std::size_t #include <cstddef> // for std::size_t
#include <functional>
#include <simgear/misc/strutils.hxx> // for string_list #include <simgear/misc/strutils.hxx> // for string_list
#include <Navaids/positioned.hxx> #include <Navaids/positioned.hxx>
@ -73,7 +74,8 @@ public:
DATFILETYPE_FIX, DATFILETYPE_FIX,
DATFILETYPE_POI, DATFILETYPE_POI,
DATFILETYPE_CARRIER, DATFILETYPE_CARRIER,
DATFILETYPE_TACAN_FREQ DATFILETYPE_TACAN_FREQ,
DATFILETYPE_LAST
}; };
struct DatFilesGroupInfo { struct DatFilesGroupInfo {
@ -82,12 +84,11 @@ public:
std::size_t totalSize; // total size of all these files, in bytes std::size_t totalSize; // total size of all these files, in bytes
}; };
// Update d->aptDatFilesInfo, d->metarDatPath, d->navDatPath, // Update d->datFilesInfo and legacy d->metarDatPath, d->poiDatPath,
// d->fixDatPath, d->poiDatPath, etc. by looking into // etc. by looking into $scenery_path/NavData for each scenery path.
// $scenery_path/NavData for each scenery path.
void updateListsOfDatFiles(); void updateListsOfDatFiles();
// Return d->aptDatFilesInfo if datFileType == DATFILETYPE_APT, etc. // Returns datFilesInfo for the given type.
DatFilesGroupInfo getDatFilesInfo(DatFileType datFileType) const; const DatFilesGroupInfo& getDatFilesInfo(DatFileType datFileType) const;
/** /**
* predicate - check if the cache needs to be rebuilt. * predicate - check if the cache needs to be rebuilt.
@ -313,6 +314,12 @@ private:
NavDataCache(); NavDataCache();
friend class RebuildThread; friend class RebuildThread;
// A generic function for loading all navigation data files of the
// specified type (apt/fix/nav etc.) using the passed type-specific loader.
void loadDatFiles(DatFileType type,
std::function<void(const SGPath&, std::size_t, std::size_t)> loader);
void doRebuild(); void doRebuild();
friend class Transaction; friend class Transaction;

View file

@ -58,8 +58,6 @@ FGFix::FGFix(PositionedID aGuid, const std::string& aIdent, const SGGeod& aPos)
namespace flightgear namespace flightgear
{ {
const unsigned int LINES_IN_FIX_DAT = 119724;
FixesLoader::FixesLoader() : _cache(NavDataCache::instance()) FixesLoader::FixesLoader() : _cache(NavDataCache::instance())
{ } { }
@ -67,7 +65,8 @@ FixesLoader::~FixesLoader()
{ } { }
// Load fixes from the specified fix.dat (or fix.dat.gz) file // Load fixes from the specified fix.dat (or fix.dat.gz) file
void FixesLoader::loadFixes(const SGPath& path) void FixesLoader::loadFixes(const SGPath& path, std::size_t bytesReadSoFar,
std::size_t totalSizeOfAllDatFiles)
{ {
sg_gzifstream in( path ); sg_gzifstream in( path );
const std::string utf8path = path.utf8Str(); const std::string utf8path = path.utf8Str();
@ -150,7 +149,8 @@ void FixesLoader::loadFixes(const SGPath& path)
if ((lineNumber % 100) == 0) { if ((lineNumber % 100) == 0) {
// every 100 lines // every 100 lines
unsigned int percent = (lineNumber * 100) / LINES_IN_FIX_DAT; unsigned int percent = ((bytesReadSoFar + in.approxOffset()) * 100)
/ totalSizeOfAllDatFiles;
_cache->setRebuildPhaseProgress(NavDataCache::REBUILD_FIXES, percent); _cache->setRebuildPhaseProgress(NavDataCache::REBUILD_FIXES, percent);
} }
} }

View file

@ -44,7 +44,8 @@ namespace flightgear
~FixesLoader(); ~FixesLoader();
// Load fixes from the specified fix.dat (or fix.dat.gz) file // Load fixes from the specified fix.dat (or fix.dat.gz) file
void loadFixes(const SGPath& path); void loadFixes(const SGPath& path, std::size_t bytesReadSoFar,
std::size_t totalSizeOfAllDatFiles);
private: private:
void throwExceptionIfStreamError(const sg_gzifstream& input_stream, void throwExceptionIfStreamError(const sg_gzifstream& input_stream,

View file

@ -31,7 +31,6 @@
#include <cstddef> // std::size_t #include <cstddef> // std::size_t
#include <cerrno> #include <cerrno>
#include <limits> #include <limits>
#include <map>
#include "navdb.hxx" #include "navdb.hxx"
@ -116,10 +115,10 @@ void alignLocaliserWithRunway(FGRunway* rwy, const string& ident, SGGeod& pos, d
// back project that distance along the runway center line // back project that distance along the runway center line
SGGeod newPos = rwy->pointOnCenterline(dist); SGGeod newPos = rwy->pointOnCenterline(dist);
double hdg_diff = heading - rwy->headingDeg(); double hdg_diff = heading - rwy->headingDeg();
SG_NORMALIZE_RANGE(hdg_diff, -180.0, 180.0); SG_NORMALIZE_RANGE(hdg_diff, -180.0, 180.0);
if ( fabs(hdg_diff) <= autoAlignThreshold ) { if ( fabs(hdg_diff) <= autoAlignThreshold ) {
pos = SGGeod::fromGeodFt(newPos, pos.getElevationFt()); pos = SGGeod::fromGeodFt(newPos, pos.getElevationFt());
heading = rwy->headingDeg(); heading = rwy->headingDeg();
@ -139,12 +138,12 @@ static double defaultNavRange(const string& ident, FGPositioned::Type type)
case FGPositioned::NDB: case FGPositioned::NDB:
case FGPositioned::VOR: case FGPositioned::VOR:
return FG_NAV_DEFAULT_RANGE; return FG_NAV_DEFAULT_RANGE;
case FGPositioned::LOC: case FGPositioned::LOC:
case FGPositioned::ILS: case FGPositioned::ILS:
case FGPositioned::GS: case FGPositioned::GS:
return FG_LOC_DEFAULT_RANGE; return FG_LOC_DEFAULT_RANGE;
case FGPositioned::DME: case FGPositioned::DME:
return FG_DME_DEFAULT_RANGE; return FG_DME_DEFAULT_RANGE;
@ -186,9 +185,9 @@ static bool canBeDuplicate(FGPositionedRef ref, FGPositioned::Type type,
// Parse a line from a file such as nav.dat or carrier_nav.dat. Load the // Parse a line from a file such as nav.dat or carrier_nav.dat. Load the
// corresponding data into the NavDataCache. // corresponding data into the NavDataCache.
static PositionedID processNavLine( PositionedID NavLoader::processNavLine(
const string& line, const string& utf8Path, unsigned int lineNum, const string& line, const string& utf8Path, unsigned int lineNum,
FGPositioned::Type type = FGPositioned::INVALID, unsigned long version = 810) FGPositioned::Type type, unsigned long version)
{ {
NavDataCache* cache = NavDataCache::instance(); NavDataCache* cache = NavDataCache::instance();
int rowCode, elev_ft, freq, range; int rowCode, elev_ft, freq, range;
@ -325,11 +324,8 @@ static PositionedID processNavLine(
// //
// First, eliminate nearby with the same name, type and ident. // First, eliminate nearby with the same name, type and ident.
static std::multimap<std::tuple<FGPositioned::Type, std::string,
std::string>, SGGeod> loadedNavs; // Maps (type, ident, name) tuples
// already loaded to their locations.
auto loadedNavsKey = std::make_tuple(type, ident, name); auto loadedNavsKey = std::make_tuple(type, ident, name);
auto matchingNavs = loadedNavs.equal_range(loadedNavsKey); auto matchingNavs = _loadedNavs.equal_range(loadedNavsKey);
for (auto it = matchingNavs.first; it != matchingNavs.second; ++it) { for (auto it = matchingNavs.first; it != matchingNavs.second; ++it) {
if (isNearby(pos, it->second)) { if (isNearby(pos, it->second)) {
SG_LOG(SG_NAVAID, SG_INFO, SG_LOG(SG_NAVAID, SG_INFO,
@ -338,7 +334,7 @@ static PositionedID processNavLine(
return 0; return 0;
} }
} }
loadedNavs.emplace(loadedNavsKey, pos); _loadedNavs.emplace(loadedNavsKey, pos);
// Then, eliminate nearby with the same type and ident. // Then, eliminate nearby with the same type and ident.
FGPositioned::TypeFilter dupTypeFilter(type); FGPositioned::TypeFilter dupTypeFilter(type);
@ -374,11 +370,11 @@ static PositionedID processNavLine(
return cache->insertNavaid(type, string(), name, pos, 0, 0, 0, return cache->insertNavaid(type, string(), name, pos, 0, 0, 0,
arp.first, arp.second); arp.first, arp.second);
} }
if (range < 1) { if (range < 1) {
range = defaultNavRange(ident, type); range = defaultNavRange(ident, type);
} }
AirportRunwayPair arp; AirportRunwayPair arp;
FGRunwayRef runway; FGRunwayRef runway;
PositionedID navaid_dme = 0; PositionedID navaid_dme = 0;
@ -444,7 +440,7 @@ static PositionedID processNavLine(
#endif #endif
} // of found runway in the DB } // of found runway in the DB
} // of type is runway-related } // of type is runway-related
bool isLoc = (type == FGPositioned::ILS) || (type == FGPositioned::LOC); bool isLoc = (type == FGPositioned::ILS) || (type == FGPositioned::LOC);
if (runway && autoAlignLocalizers && isLoc) { if (runway && autoAlignLocalizers && isLoc) {
alignLocaliserWithRunway(runway, ident, pos, multiuse); alignLocaliserWithRunway(runway, ident, pos, multiuse);
@ -452,7 +448,7 @@ static PositionedID processNavLine(
PositionedID r = cache->insertNavaid(type, ident, name, pos, freq, range, multiuse, PositionedID r = cache->insertNavaid(type, ident, name, pos, freq, range, multiuse,
arp.first, arp.second); arp.first, arp.second);
if (isLoc) { if (isLoc) {
cache->setRunwayILS(arp.second, r); cache->setRunwayILS(arp.second, r);
} }
@ -460,16 +456,16 @@ static PositionedID processNavLine(
if (navaid_dme) { if (navaid_dme) {
cache->setNavaidColocated(navaid_dme, r); cache->setNavaidColocated(navaid_dme, r);
} }
return r; return r;
} }
// load and initialize the navigational databases // load and initialize the navigational databases
void navDBInit(const SGPath& path) void NavLoader::loadNav(const SGPath& path, std::size_t bytesReadSoFar,
std::size_t totalSizeOfAllDatFiles)
{ {
NavDataCache* cache = NavDataCache::instance(); NavDataCache* cache = NavDataCache::instance();
const string utf8Path = path.utf8Str(); const string utf8Path = path.utf8Str();
const std::size_t fileSize = path.sizeInBytes();
sg_gzifstream in(path); sg_gzifstream in(path);
if ( !in.is_open() ) { if ( !in.is_open() ) {
@ -507,7 +503,8 @@ void navDBInit(const SGPath& path)
if ((lineNumber % 100) == 0) { if ((lineNumber % 100) == 0) {
// every 100 lines // every 100 lines
unsigned int percent = (in.approxOffset() * 100) / fileSize; unsigned int percent = ((bytesReadSoFar + in.approxOffset()) * 100)
/ totalSizeOfAllDatFiles;
cache->setRebuildPhaseProgress(NavDataCache::REBUILD_NAVAIDS, percent); cache->setRebuildPhaseProgress(NavDataCache::REBUILD_NAVAIDS, percent);
} }
@ -516,7 +513,7 @@ void navDBInit(const SGPath& path)
throwExceptionIfStreamError(in, path); throwExceptionIfStreamError(in, path);
} }
void loadCarrierNav(const SGPath& path) void NavLoader::loadCarrierNav(const SGPath& path)
{ {
SG_LOG( SG_NAVAID, SG_DEBUG, "Opening file: " << path ); SG_LOG( SG_NAVAID, SG_DEBUG, "Opening file: " << path );
const string utf8Path = path.utf8Str(); const string utf8Path = path.utf8Str();
@ -539,26 +536,26 @@ void loadCarrierNav(const SGPath& path)
throwExceptionIfStreamError(in, path); throwExceptionIfStreamError(in, path);
} }
bool loadTacan(const SGPath& path, FGTACANList *channellist) bool NavLoader::loadTacan(const SGPath& path, FGTACANList *channellist)
{ {
SG_LOG( SG_NAVAID, SG_DEBUG, "opening file: " << path ); SG_LOG( SG_NAVAID, SG_DEBUG, "opening file: " << path );
sg_gzifstream inchannel( path ); sg_gzifstream inchannel( path );
if ( !inchannel.is_open() ) { if ( !inchannel.is_open() ) {
SG_LOG( SG_NAVAID, SG_ALERT, "Cannot open file: " << path ); SG_LOG( SG_NAVAID, SG_ALERT, "Cannot open file: " << path );
return false; return false;
} }
// skip first line // skip first line
inchannel >> skipeol; inchannel >> skipeol;
while ( ! inchannel.eof() ) { while ( ! inchannel.eof() ) {
FGTACANRecord *r = new FGTACANRecord; FGTACANRecord *r = new FGTACANRecord;
inchannel >> (*r); inchannel >> (*r);
channellist->add ( r ); channellist->add ( r );
} // end while } // end while
return true; return true;
} }
} // of namespace flightgear } // of namespace flightgear

View file

@ -26,23 +26,40 @@
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <simgear/math/SGGeod.hxx>
#include <string> #include <string>
#include <map>
#include <tuple>
#include <Navaids/positioned.hxx>
// forward decls // forward decls
class FGTACANList; class FGTACANList;
class SGPath; class SGPath;
class SGPropertyNode;
class FGRunway;
namespace flightgear namespace flightgear
{ {
// load and initialize the navigational databases class NavLoader {
void navDBInit(const SGPath& path); public:
// load and initialize the navigational databases
void loadCarrierNav(const SGPath& path); void loadNav(const SGPath& path, std::size_t bytesReadSoFar,
std::size_t totalSizeOfAllDatFiles);
bool loadTacan(const SGPath& path, FGTACANList *channellist);
void loadCarrierNav(const SGPath& path);
bool loadTacan(const SGPath& path, FGTACANList *channellist);
private:
// Maps (type, ident, name) tuples already loaded to their locations.
std::multimap<std::tuple<FGPositioned::Type, std::string, std::string>,
SGGeod> _loadedNavs;
PositionedID processNavLine(const std::string& line,
const std::string& utf8Path,
unsigned int lineNum,
FGPositioned::Type type = FGPositioned::INVALID,
unsigned long version = 810);
};
} // of namespace flightgear } // of namespace flightgear