NavData: don't load XML extension files from unsuitable scenery paths
Add a 'scenery_path' field to the 'airport' table of the SQLite NavDataCache database. For each airport, this field indicates the scenery realpath() that contributed the apt.dat file for the airport (as an exception, for airports whose apt.dat file is $FG_ROOT/Airports/apt.dat.gz, the path thus stored is for now $FG_ROOT, which is technically not a scenery path). This path is then made available via FGAirport::sceneryPath(), which allows us to implement the following change (in this commit): A) The lookup of *.procedures.xml is unchanged. B) For other XML extension files (groundnet, ils, runway_rename, threshold, twr): - The search performed by XMLLoader::findAirportData() through globals->get_fg_scenery() stops immediately after the scenery path p that contributed the apt.dat file for the airport. - Paths that come earlier than p in globals->get_fg_scenery() order may contain XML extension files that will *override* sibling files that might exist in p (as was already the case before this commit). The rationale behind this change is that we don't want a custom scenery with good data in its NavData folder regarding airport FOO to get "ruined" by files such as FOO.threshold.xml present in the TerraSync directory---which is assumed to come later in globals->get_fg_scenery() order. *.procedures.xml files are excluded from the change because there is a widespread use of a huge set of procedure files for the whole world; if airport FOO in a custom scenery has no procedure files, we do want to let FlightGear find FOO.procedures.xml inside the scenery path containing the huge dataset (which should come *after* custom sceneries in globals->get_fg_scenery() order so as to give these custom sceneries the option to provide better *.procedures.xml files and have them take precedence over less specialized sources such as the huge dataset). Reference discussion: https://sourceforge.net/p/flightgear/mailman/flightgear-devel/thread/CAKor_THrQCiS1ES_ENSrmn1j3s39dX0qQXSbYBUz6yuokse_pQ%40mail.gmail.com/#msg37860751
This commit is contained in:
parent
a207cdd207
commit
351ca111ad
14 changed files with 134 additions and 60 deletions
|
@ -73,7 +73,8 @@ osgDB::ReaderWriter::ReadResult AirportBuilder::readNode(const std::string& file
|
|||
const std::string airportId = aptFile.file_base();
|
||||
APTLoader aptLoader;
|
||||
|
||||
const FGAirport* airport = aptLoader.loadAirportFromFile(airportId, aptFile);
|
||||
const FGAirport* airport = aptLoader.loadAirportFromFile(
|
||||
airportId, {aptFile, SGPath()}); // maybe provide a path if this is used
|
||||
if (! airport) return ReadResult::FILE_NOT_HANDLED;
|
||||
|
||||
SG_LOG( SG_TERRAIN, SG_DEBUG, "Building airport : " << airportId << " " << airport->getName());
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
|
||||
#include <simgear/debug/ErrorReportingCallback.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
@ -54,10 +55,12 @@ FGAirport::FGAirport( PositionedID aGuid,
|
|||
const SGGeod& location,
|
||||
const std::string &name,
|
||||
bool has_metar,
|
||||
Type aType ):
|
||||
Type aType,
|
||||
SGPath sceneryPath):
|
||||
FGPositioned(aGuid, aType, id, location),
|
||||
_name(name),
|
||||
_has_metar(has_metar),
|
||||
_sceneryPath(std::move(sceneryPath)),
|
||||
mTowerDataLoaded(false),
|
||||
mHasTower(false),
|
||||
mRunwaysLoaded(false),
|
||||
|
@ -90,6 +93,11 @@ bool FGAirport::isHeliport() const
|
|||
return type() == HELIPORT;
|
||||
}
|
||||
|
||||
SGPath FGAirport::sceneryPath() const
|
||||
{
|
||||
return _sceneryPath;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned int FGAirport::numRunways() const
|
||||
{
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
#include <Navaids/positioned.hxx>
|
||||
#include <Navaids/procedure.hxx>
|
||||
|
@ -30,8 +31,15 @@ class FGGroundNetwork;
|
|||
class FGAirport : public FGPositioned
|
||||
{
|
||||
public:
|
||||
// 'sceneryPath' is the scenery path that provided the apt.dat file for
|
||||
// the airport (except for the “default dat file” under $FG_ROOT and the
|
||||
// null SGPath special case, 'sceneryPath' should be an element of
|
||||
// globals->get_fg_scenery()). Knowing this allows one to stop looking for
|
||||
// files such as ils.xml or threshold.xml in scenery paths that come later
|
||||
// in globals->get_fg_scenery() order (cf. XMLLoader::findAirportData()).
|
||||
FGAirport(PositionedID aGuid, const std::string& id, const SGGeod& location,
|
||||
const std::string& name, bool has_metar, Type aType);
|
||||
const std::string& name, bool has_metar, Type aType,
|
||||
SGPath sceneryPath = SGPath());
|
||||
~FGAirport();
|
||||
|
||||
static bool isType(FGPositioned::Type ty)
|
||||
|
@ -39,6 +47,9 @@ public:
|
|||
return (ty >= FGPositioned::AIRPORT) && (ty <= FGPositioned::SEAPORT);
|
||||
}
|
||||
|
||||
// Return the realpath() of the scenery folder under which we found the
|
||||
// apt.dat file for this airport.
|
||||
SGPath sceneryPath() const;
|
||||
const std::string& getId() const { return ident(); }
|
||||
const std::string& getName() const { return _name; }
|
||||
std::string toString() const { return "an airport " + ident(); }
|
||||
|
@ -350,6 +361,7 @@ private:
|
|||
|
||||
std::string _name;
|
||||
bool _has_metar = false;
|
||||
const SGPath _sceneryPath;
|
||||
|
||||
void loadRunways() const;
|
||||
void loadHelipads() const;
|
||||
|
|
|
@ -68,10 +68,11 @@ APTLoader::APTLoader()
|
|||
|
||||
APTLoader::~APTLoader() {}
|
||||
|
||||
void APTLoader::readAptDatFile(const SGPath& aptdb_file,
|
||||
void APTLoader::readAptDatFile(const NavDataCache::SceneryLocation& sceneryLocation,
|
||||
std::size_t bytesReadSoFar,
|
||||
std::size_t totalSizeOfAllAptDatFiles)
|
||||
{
|
||||
const SGPath aptdb_file = sceneryLocation.datPath;
|
||||
string apt_dat = aptdb_file.utf8Str(); // full path to the file being parsed
|
||||
sg_gzifstream in(aptdb_file, std::ios_base::in | std::ios_base::binary, true);
|
||||
|
||||
|
@ -175,6 +176,7 @@ void APTLoader::readAptDatFile(const SGPath& aptdb_file,
|
|||
// We haven't seen this airport yet in any apt.dat file
|
||||
RawAirportInfo& airportInfo = insertRetval.first->second;
|
||||
airportInfo.file = aptdb_file;
|
||||
airportInfo.sceneryPath = sceneryLocation.sceneryPath;
|
||||
airportInfo.rowCode = rowCode;
|
||||
airportInfo.firstLineNum = line_num;
|
||||
airportInfo.firstLineTokens = std::move(tokens);
|
||||
|
@ -203,7 +205,7 @@ void APTLoader::loadAirports()
|
|||
for (AirportInfoMapType::const_iterator it = airportInfoMap.begin();
|
||||
it != airportInfoMap.end(); ++it) {
|
||||
// Full path to the apt.dat file this airport info comes from
|
||||
const string aptDat = it->second.file.utf8Str();
|
||||
const SGPath aptDat = it->second.file;
|
||||
|
||||
// this is just the current airport identifier
|
||||
last_apt_id = it->first;
|
||||
|
@ -225,15 +227,15 @@ void APTLoader::loadAirports()
|
|||
}
|
||||
|
||||
// Parse and return specific apt.dat file containing a single airport.
|
||||
const FGAirport* APTLoader::loadAirportFromFile(const std::string& id, const SGPath& aptdb_file)
|
||||
const FGAirport* APTLoader::loadAirportFromFile(const std::string& id, const NavDataCache::SceneryLocation& sceneryLocation)
|
||||
{
|
||||
std::size_t bytesReadSoFar = 10;
|
||||
std::size_t totalSizeOfAllAptDatFiles = 100;
|
||||
|
||||
readAptDatFile(aptdb_file.str(), bytesReadSoFar, totalSizeOfAllAptDatFiles);
|
||||
readAptDatFile(sceneryLocation, bytesReadSoFar, totalSizeOfAllAptDatFiles);
|
||||
|
||||
RawAirportInfo rawInfo = airportInfoMap[id];
|
||||
return loadAirport(aptdb_file.c_str(), id, &rawInfo, true);
|
||||
return loadAirport(sceneryLocation.datPath, id, &rawInfo, true);
|
||||
}
|
||||
|
||||
static bool isCommLine(const int code)
|
||||
|
@ -241,13 +243,15 @@ static bool isCommLine(const int code)
|
|||
return ((code >= 50) && (code <= 56)) || ((code >= 1050) && (code <= 1056));
|
||||
}
|
||||
|
||||
const FGAirport* APTLoader::loadAirport(const string& aptDat, const std::string& airportID, RawAirportInfo* airport_info, bool createFGAirport)
|
||||
const FGAirport* APTLoader::loadAirport(const SGPath& aptDatFile, const std::string& airportID, RawAirportInfo* airport_info, bool createFGAirport)
|
||||
{
|
||||
// The first line for this airport was already split over whitespace, but
|
||||
// remains to be parsed for the most part.
|
||||
parseAirportLine(airport_info->rowCode, airport_info->firstLineTokens);
|
||||
parseAirportLine(airport_info->rowCode, airport_info->firstLineTokens,
|
||||
airport_info->sceneryPath);
|
||||
const LinesList& lines = airport_info->otherLines;
|
||||
|
||||
const string aptDat = aptDatFile.utf8Str();
|
||||
NodeBlock current_block = None;
|
||||
|
||||
// Loop over the second and subsequent lines
|
||||
|
@ -422,7 +426,8 @@ void APTLoader::finishAirport(const string& aptDat)
|
|||
// 'rowCode' is passed to avoid decoding it twice, since that work was already
|
||||
// done in order to detect the start of the new airport.
|
||||
void APTLoader::parseAirportLine(unsigned int rowCode,
|
||||
const vector<string>& token)
|
||||
const vector<string>& token,
|
||||
const SGPath& sceneryPath)
|
||||
{
|
||||
// The algorithm in APTLoader::readAptDatFile() ensures this is at least 5.
|
||||
vector<string>::size_type lastIndex = token.size() - 1;
|
||||
|
@ -443,7 +448,7 @@ void APTLoader::parseAirportLine(unsigned int rowCode,
|
|||
rwy_count = 0;
|
||||
|
||||
currentAirportPosID = cache->insertAirport(fptypeFromRobinType(rowCode),
|
||||
id, name);
|
||||
id, name, sceneryPath);
|
||||
}
|
||||
|
||||
void APTLoader::parseRunwayLine810(const string& aptDat, unsigned int lineNum,
|
||||
|
|
|
@ -9,9 +9,11 @@
|
|||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <Navaids/positioned.hxx>
|
||||
#include <Navaids/NavDataCache.hxx>
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/math/SGGeod.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
@ -20,7 +22,6 @@
|
|||
#include "airport.hxx"
|
||||
|
||||
|
||||
class NavDataCache;
|
||||
class sg_gzifstream;
|
||||
class FGPavement;
|
||||
|
||||
|
@ -36,7 +37,8 @@ public:
|
|||
// Read the specified apt.dat file into 'airportInfoMap'.
|
||||
// 'bytesReadSoFar' and 'totalSizeOfAllAptDatFiles' are used for progress
|
||||
// information.
|
||||
void readAptDatFile(const SGPath& aptdb_file, std::size_t bytesReadSoFar,
|
||||
void readAptDatFile(const NavDataCache::SceneryLocation& sceneryLocation,
|
||||
std::size_t bytesReadSoFar,
|
||||
std::size_t totalSizeOfAllAptDatFiles);
|
||||
// Read all airports gathered in 'airportInfoMap' and load them into the
|
||||
// navdata cache (even in case of overlapping apt.dat files,
|
||||
|
@ -45,7 +47,7 @@ public:
|
|||
|
||||
// Load a specific airport defined in aptdb_file, and return a "rich" view
|
||||
// of the airport including taxiways, pavement and line features.
|
||||
const FGAirport* loadAirportFromFile(const std::string& id, const SGPath& aptdb_file);
|
||||
const FGAirport* loadAirportFromFile(const std::string& id, const NavDataCache::SceneryLocation& sceneryLocation);
|
||||
|
||||
private:
|
||||
struct Line {
|
||||
|
@ -62,6 +64,8 @@ private:
|
|||
struct RawAirportInfo {
|
||||
// apt.dat file where the airport was defined
|
||||
SGPath file;
|
||||
// Base path of the corresponding scenery
|
||||
SGPath sceneryPath;
|
||||
// Row code for the airport (1, 16 or 17)
|
||||
unsigned int rowCode;
|
||||
// Line number in the apt.dat file where the airport definition starts
|
||||
|
@ -80,7 +84,7 @@ private:
|
|||
APTLoader(const APTLoader&); // disable copy constructor
|
||||
APTLoader& operator=(const APTLoader&); // disable copy-assignment operator
|
||||
|
||||
const FGAirport* loadAirport(const std::string& aptDat, const std::string& airportID, RawAirportInfo* airport_info, bool createFGAirport = false);
|
||||
const FGAirport* loadAirport(const SGPath& aptDat, const std::string& airportID, RawAirportInfo* airport_info, bool createFGAirport = false);
|
||||
|
||||
// Tell whether an apt.dat line is blank or a comment line
|
||||
bool isBlankOrCommentLine(const std::string& line);
|
||||
|
@ -89,7 +93,8 @@ private:
|
|||
void throwExceptionIfStreamError(const sg_gzifstream& input_stream,
|
||||
const SGPath& path);
|
||||
void parseAirportLine(unsigned int rowCode,
|
||||
const std::vector<std::string>& token);
|
||||
const std::vector<std::string>& token,
|
||||
const SGPath& sceneryPath);
|
||||
void finishAirport(const std::string& aptDat);
|
||||
void parseRunwayLine810(const std::string& aptDat, unsigned int lineNum,
|
||||
const std::vector<std::string>& token);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <utility>
|
||||
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/xml/easyxml.hxx>
|
||||
|
@ -105,11 +106,19 @@ void XMLLoader::load(FGRunwayPreference* p) {
|
|||
bool XMLLoader::findAirportData(const std::string& aICAO,
|
||||
const std::string& aFileName, SGPath& aPath)
|
||||
{
|
||||
FGAirportRef airport = FGAirport::findByIdent(aICAO);
|
||||
if (!airport) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string fileName(aFileName);
|
||||
if (!simgear::strutils::ends_with(aFileName, ".xml")) {
|
||||
fileName.append(".xml");
|
||||
}
|
||||
|
||||
|
||||
const bool performFullTraversal = airport->sceneryPath().isNull() ||
|
||||
!fileName.compare("procedures.xml");
|
||||
|
||||
PathList sc = globals->get_fg_scenery();
|
||||
char buffer[128];
|
||||
::snprintf(buffer, 128, "%c/%c/%c/%s.%s",
|
||||
|
@ -119,13 +128,18 @@ bool XMLLoader::findAirportData(const std::string& aICAO,
|
|||
for (PathList::const_iterator it = sc.begin(); it != sc.end(); ++it) {
|
||||
// fg_senery contains empty strings as "markers" (see FGGlobals::set_fg_scenery)
|
||||
if (!it->isNull()) {
|
||||
SGPath path(*it);
|
||||
path.append("Airports");
|
||||
path.append(string(buffer));
|
||||
const SGPath path = *it / "Airports" / buffer;
|
||||
if (path.exists()) {
|
||||
aPath = path;
|
||||
aPath = std::move(path);
|
||||
return true;
|
||||
} // of path exists
|
||||
|
||||
// Unless we are in “full traversal mode”, don't look in scenery paths
|
||||
// that come after the one which contributed the apt.dat file for the
|
||||
// airport.
|
||||
if (!performFullTraversal && *it == airport->sceneryPath()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // of scenery path iteration
|
||||
return false;
|
||||
|
|
|
@ -3110,7 +3110,15 @@ void Options::printJSONReport() const
|
|||
// For this method, it doesn't matter if the cache is out-of-date
|
||||
const NavDataCache::DatFilesGroupInfo& datFilesInfo =
|
||||
cache->getDatFilesInfo(datType);
|
||||
cJSON *datPathsNode = p->createJSONArrayFromPathList(datFilesInfo.paths);
|
||||
|
||||
// Create a list of SGPath instances (for the .dat files) from the list of
|
||||
// NavDataCache::SceneryLocation structs that datFilesInfo.paths is.
|
||||
PathList datFiles(datFilesInfo.paths.size());
|
||||
const auto map = [](const auto& e) { return e.datPath; };
|
||||
std::transform(std::cbegin(datFilesInfo.paths),
|
||||
std::cend(datFilesInfo.paths), std::begin(datFiles), map);
|
||||
|
||||
cJSON *datPathsNode = p->createJSONArrayFromPathList(datFiles);
|
||||
string key = NavDataCache::datTypeStr[datType] + ".dat files";
|
||||
cJSON_AddItemToObject(navDataNode, key.c_str(), datPathsNode);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
const int SCHEMA_VERSION = 21;
|
||||
const int SCHEMA_VERSION = 22;
|
||||
|
||||
#define SCHEMA_SQL \
|
||||
"CREATE TABLE properties (key VARCHAR, value VARCHAR);" \
|
||||
|
@ -15,7 +15,7 @@ const int SCHEMA_VERSION = 21;
|
|||
"CREATE INDEX pos_name ON positioned(name collate nocase);" \
|
||||
"CREATE INDEX pos_apt_type ON positioned(airport, type);" \
|
||||
\
|
||||
"CREATE TABLE airport (has_metar BOOL);" \
|
||||
"CREATE TABLE airport (scenery_path VARCHAR, has_metar BOOL);" \
|
||||
"CREATE TABLE comm (freq_khz INT,range_nm INT);" \
|
||||
"CREATE INDEX comm_freq ON comm(freq_khz);" \
|
||||
\
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <stdint.h> // for int64_t
|
||||
#include <sstream> // for std::ostringstream
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
#ifdef SYSTEM_SQLITE
|
||||
// the standard sqlite3.h doesn't give a way to set SQLITE_UINT64_TYPE,
|
||||
|
@ -563,7 +564,7 @@ public:
|
|||
"(path, stamp, sha) VALUES (?,?, ?)");
|
||||
|
||||
loadPositioned = prepare("SELECT " POSITIONED_COLS " FROM positioned WHERE rowid=?");
|
||||
loadAirportStmt = prepare("SELECT has_metar FROM airport WHERE rowid=?");
|
||||
loadAirportStmt = prepare("SELECT scenery_path, has_metar FROM airport WHERE rowid=?");
|
||||
loadNavaid = prepare("SELECT range_nm, freq, multiuse, runway, colocated FROM navaid WHERE rowid=?");
|
||||
loadCommStation = prepare("SELECT freq_khz, range_nm FROM comm WHERE rowid=?");
|
||||
loadRunwayStmt = prepare("SELECT heading, length_ft, width_m, surface, displaced_threshold,"
|
||||
|
@ -588,7 +589,7 @@ public:
|
|||
|
||||
setAirportPos = prepare("UPDATE positioned SET lon=?2, lat=?3, elev_m=?4, octree_node=?5, "
|
||||
"cart_x=?6, cart_y=?7, cart_z=?8 WHERE rowid=?1");
|
||||
insertAirport = prepare("INSERT INTO airport (rowid, has_metar) VALUES (?, ?)");
|
||||
insertAirport = prepare("INSERT INTO airport (rowid, scenery_path, has_metar) VALUES (?, ?, ?)");
|
||||
insertNavaid = prepare("INSERT INTO navaid (rowid, freq, range_nm, multiuse, runway, colocated)"
|
||||
" VALUES (?1, ?2, ?3, ?4, ?5, ?6)");
|
||||
|
||||
|
@ -704,10 +705,12 @@ public:
|
|||
{
|
||||
sqlite3_bind_int64(loadAirportStmt, 1, rowId);
|
||||
execSelect1(loadAirportStmt);
|
||||
bool hasMetar = (sqlite3_column_int(loadAirportStmt, 0) > 0);
|
||||
SGPath sceneryPath{(char *) sqlite3_column_text(loadAirportStmt, 0)};
|
||||
bool hasMetar = (sqlite3_column_int(loadAirportStmt, 1) > 0);
|
||||
reset(loadAirportStmt);
|
||||
|
||||
return new FGAirport(rowId, id, pos, name, hasMetar, ty);
|
||||
return new FGAirport(rowId, id, pos, name, hasMetar, ty,
|
||||
std::move(sceneryPath));
|
||||
}
|
||||
|
||||
FGRunwayBase* loadRunway(sqlite3_int64 rowId, FGPositioned::Type ty,
|
||||
|
@ -1156,7 +1159,7 @@ void NavDataCache::NavDataCachePrivate::findDatFiles(
|
|||
const std::string name = f.file();
|
||||
if (simgear::strutils::ends_with(name, ".dat") ||
|
||||
simgear::strutils::ends_with(name, ".dat.gz")) {
|
||||
result.paths.push_back(f);
|
||||
result.paths.push_back({f, path});
|
||||
result.totalSize += f.sizeInBytes();
|
||||
}
|
||||
}
|
||||
|
@ -1167,9 +1170,9 @@ void NavDataCache::NavDataCachePrivate::findDatFiles(
|
|||
// now
|
||||
SGPath defaultDatFile(globals->get_fg_root());
|
||||
defaultDatFile.append(NavDataCache::defaultDatFile[datFileType]);
|
||||
if ((result.paths.empty() || result.paths.back() != defaultDatFile) &&
|
||||
if ((result.paths.empty() || result.paths.back().datPath != defaultDatFile) &&
|
||||
defaultDatFile.isFile()) {
|
||||
result.paths.push_back(defaultDatFile);
|
||||
result.paths.push_back({defaultDatFile, globals->get_fg_root()});
|
||||
result.totalSize += defaultDatFile.sizeInBytes();
|
||||
}
|
||||
|
||||
|
@ -1195,8 +1198,8 @@ bool NavDataCache::NavDataCachePrivate::areDatFilesModified(
|
|||
NavDataCache::datTypeStr[datFileType];
|
||||
const string_list cachedFiles = outer->readOrderedStringListProperty(
|
||||
datTypeStr + ".dat files", SGPath::pathListSep);
|
||||
const PathList& datFiles = datFilesGroupInfo.paths;
|
||||
PathList::const_iterator datFilesIt = datFiles.begin();
|
||||
const auto& datFiles = datFilesGroupInfo.paths;
|
||||
auto datFilesIt = datFiles.cbegin();
|
||||
string_list::const_iterator cachedFilesIt = cachedFiles.begin();
|
||||
// Same logic as in NavDataCachePrivate::isCachedFileModified()
|
||||
sgDebugPriority logLevel = verbose ? SG_WARN : SG_DEBUG;
|
||||
|
@ -1210,7 +1213,7 @@ bool NavDataCache::NavDataCachePrivate::areDatFilesModified(
|
|||
}
|
||||
|
||||
while (datFilesIt != datFiles.end()) {
|
||||
const SGPath& path = *(datFilesIt++);
|
||||
const SGPath& path = (datFilesIt++)->datPath;
|
||||
|
||||
if (!path.exists()) {
|
||||
throw sg_exception(
|
||||
|
@ -1643,25 +1646,24 @@ void NavDataCache::setRebuildPhaseProgress(RebuildPhase ph, unsigned int percent
|
|||
|
||||
void NavDataCache::loadDatFiles(
|
||||
DatFileType type,
|
||||
std::function<void(const SGPath&, std::size_t, std::size_t)> loader)
|
||||
std::function<void(const SceneryLocation&, std::size_t, std::size_t)> loader)
|
||||
{
|
||||
SGTimeStamp st;
|
||||
string typeStr = datTypeStr[type];
|
||||
const string typeStr = datTypeStr[type];
|
||||
string_list datFiles;
|
||||
NavDataCache::DatFilesGroupInfo datFilesInfo = getDatFilesInfo(type);
|
||||
const PathList datPaths = datFilesInfo.paths;
|
||||
const NavDataCache::DatFilesGroupInfo datFilesInfo = getDatFilesInfo(type);
|
||||
const SceneryLocationList sceneryLocations = 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();
|
||||
for (const auto& scLoc : sceneryLocations) {
|
||||
const string path = scLoc.datPath.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
|
||||
"Loading " + typeStr + ".dat file: '" << std::move(path) << "'");
|
||||
loader(scLoc, bytesReadSoFar, datFilesInfo.totalSize);
|
||||
bytesReadSoFar += scLoc.datPath.sizeInBytes();
|
||||
stampCacheFile(scLoc.datPath); // this uses the realpath() of the file
|
||||
}
|
||||
|
||||
// Store the list of .dat files we have loaded
|
||||
|
@ -2032,8 +2034,10 @@ FGPositionedRef NavDataCache::loadById(PositionedID rowid)
|
|||
}
|
||||
|
||||
PositionedID NavDataCache::insertAirport(FGPositioned::Type ty, const string& ident,
|
||||
const string& name)
|
||||
const string& name,
|
||||
const SGPath& sceneryPath)
|
||||
{
|
||||
const string sceneryPath_str = sceneryPath.utf8Str();
|
||||
// airports have their pos computed based on the avergae runway centres
|
||||
// so the pos isn't available immediately. Pass a dummy pos and avoid
|
||||
// doing spatial indexing until later
|
||||
|
@ -2042,6 +2046,7 @@ PositionedID NavDataCache::insertAirport(FGPositioned::Type ty, const string& id
|
|||
false /* spatial index */);
|
||||
|
||||
sqlite3_bind_int64(d->insertAirport, 1, rowId);
|
||||
sqlite_bind_stdstring(d->insertAirport, 2, sceneryPath_str);
|
||||
d->execInsert(d->insertAirport);
|
||||
|
||||
return rowId;
|
||||
|
|
|
@ -10,9 +10,10 @@
|
|||
#include <cstddef> // for std::size_t
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <Main/globals.hxx> // for PathList
|
||||
#include <Navaids/positioned.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/misc/strutils.hxx> // for string_list
|
||||
|
||||
|
||||
|
@ -66,9 +67,16 @@ public:
|
|||
DATFILETYPE_LAST
|
||||
};
|
||||
|
||||
struct SceneryLocation {
|
||||
SGPath datPath;
|
||||
SGPath sceneryPath; // scenery realpath() the dat file belongs to
|
||||
};
|
||||
|
||||
using SceneryLocationList = std::vector<SceneryLocation>;
|
||||
|
||||
struct DatFilesGroupInfo {
|
||||
DatFileType datFileType; // for instance, DATFILETYPE_APT
|
||||
PathList paths; // SGPath instances
|
||||
SceneryLocationList paths;
|
||||
std::size_t totalSize; // total size of all these files, in bytes
|
||||
};
|
||||
|
||||
|
@ -144,7 +152,8 @@ public:
|
|||
FGPositionedRef loadById(PositionedID guid);
|
||||
|
||||
PositionedID insertAirport(FGPositioned::Type ty, const std::string& ident,
|
||||
const std::string& name);
|
||||
const std::string& name,
|
||||
const SGPath& sceneryPath);
|
||||
void insertTower(PositionedID airportId, const SGGeod& pos);
|
||||
|
||||
|
||||
|
@ -335,7 +344,7 @@ private:
|
|||
// 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);
|
||||
std::function<void(const SceneryLocation&, std::size_t, std::size_t)> loader);
|
||||
|
||||
void doRebuild();
|
||||
|
||||
|
|
|
@ -65,9 +65,11 @@ FixesLoader::~FixesLoader()
|
|||
{ }
|
||||
|
||||
// Load fixes from the specified fix.dat (or fix.dat.gz) file
|
||||
void FixesLoader::loadFixes(const SGPath& path, std::size_t bytesReadSoFar,
|
||||
void FixesLoader::loadFixes(const NavDataCache::SceneryLocation& sceneryLocation,
|
||||
std::size_t bytesReadSoFar,
|
||||
std::size_t totalSizeOfAllDatFiles)
|
||||
{
|
||||
const SGPath path = sceneryLocation.datPath;
|
||||
sg_gzifstream in( path );
|
||||
const std::string utf8path = path.utf8Str();
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#define _FG_FIXLIST_HXX
|
||||
|
||||
|
||||
#include <Navaids/NavDataCache.hxx>
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/math/SGGeod.hxx>
|
||||
#include <unordered_map>
|
||||
|
@ -35,8 +36,6 @@ class sg_gzifstream;
|
|||
|
||||
namespace flightgear
|
||||
{
|
||||
class NavDataCache; // forward declaration
|
||||
|
||||
class FixesLoader
|
||||
{
|
||||
public:
|
||||
|
@ -44,7 +43,8 @@ namespace flightgear
|
|||
~FixesLoader();
|
||||
|
||||
// Load fixes from the specified fix.dat (or fix.dat.gz) file
|
||||
void loadFixes(const SGPath& path, std::size_t bytesReadSoFar,
|
||||
void loadFixes(const NavDataCache::SceneryLocation& sceneryLocation,
|
||||
std::size_t bytesReadSoFar,
|
||||
std::size_t totalSizeOfAllDatFiles);
|
||||
|
||||
private:
|
||||
|
|
|
@ -426,10 +426,12 @@ PositionedID NavLoader::processNavLine(
|
|||
}
|
||||
|
||||
// load and initialize the navigational databases
|
||||
void NavLoader::loadNav(const SGPath& path, std::size_t bytesReadSoFar,
|
||||
void NavLoader::loadNav(const NavDataCache::SceneryLocation& sceneryLocation,
|
||||
std::size_t bytesReadSoFar,
|
||||
std::size_t totalSizeOfAllDatFiles)
|
||||
{
|
||||
NavDataCache* cache = NavDataCache::instance();
|
||||
const SGPath path = sceneryLocation.datPath;
|
||||
const string utf8Path = path.utf8Str();
|
||||
sg_gzifstream in(path);
|
||||
|
||||
|
|
|
@ -27,11 +27,13 @@
|
|||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/math/SGGeod.hxx>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
#include <Navaids/NavDataCache.hxx>
|
||||
#include <Navaids/positioned.hxx>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
// forward decls
|
||||
class FGTACANList;
|
||||
class SGPath;
|
||||
|
@ -42,7 +44,8 @@ namespace flightgear
|
|||
class NavLoader {
|
||||
public:
|
||||
// load and initialize the navigational databases
|
||||
void loadNav(const SGPath& path, std::size_t bytesReadSoFar,
|
||||
void loadNav(const NavDataCache::SceneryLocation& sceneryLocation,
|
||||
std::size_t bytesReadSoFar,
|
||||
std::size_t totalSizeOfAllDatFiles);
|
||||
|
||||
void loadCarrierNav(const SGPath& path);
|
||||
|
|
Loading…
Reference in a new issue