mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-12 22:39:09 -05:00
- Enable caching of TileProviders at startup time
- Enable path tokens in filename for temporal tile providers - Add support for relative paths in temporal tile providers - Set the GDAL temp dir to the BASE_PATH -
This commit is contained in:
@@ -54,13 +54,16 @@ std::ostream& operator<<(std::ostream& os, const PixelRegion& pr) {
|
||||
", " << pr.numPixels.y;
|
||||
}
|
||||
|
||||
GdalRawTileDataReader::GdalRawTileDataReader(
|
||||
const std::string& filePath, const Configuration& config)
|
||||
GdalRawTileDataReader::GdalRawTileDataReader(const std::string& filePath,
|
||||
const Configuration& config,
|
||||
const std::string& baseDirectory)
|
||||
: RawTileDataReader(config)
|
||||
, _dataset(nullptr)
|
||||
{
|
||||
_initData = { "", filePath, config.tilePixelSize, config.dataType };
|
||||
_initData.initDirectory = CPLGetCurrentDir();
|
||||
|
||||
std::string initDir = baseDirectory.empty() ? CPLGetCurrentDir() : baseDirectory;
|
||||
|
||||
_initData = { initDir, filePath, config.tilePixelSize, config.dataType };
|
||||
ensureInitialized();
|
||||
}
|
||||
|
||||
@@ -303,6 +306,7 @@ GDALDataset* GdalRawTileDataReader::openGdalDataset(const std::string& filePath)
|
||||
std::string correctedPath = FileSystem::ref().pathByAppendingComponent(
|
||||
_initData.initDirectory, filePath
|
||||
);
|
||||
|
||||
dataset = (GDALDataset *)GDALOpen(correctedPath.c_str(), GA_ReadOnly);
|
||||
if (!dataset) {
|
||||
throw ghoul::RuntimeError("Failed to load dataset:\n" + filePath);
|
||||
|
||||
@@ -60,8 +60,10 @@ public:
|
||||
*
|
||||
* \param filePath, a path to a specific file GDAL can read
|
||||
* \param config, Configuration used for initialization
|
||||
* \param baseDirectory, the base directory to use in future loading operations
|
||||
*/
|
||||
GdalRawTileDataReader(const std::string& filePath, const Configuration& config);
|
||||
GdalRawTileDataReader(const std::string& filePath, const Configuration& config,
|
||||
const std::string& baseDirectory = "");
|
||||
|
||||
virtual ~GdalRawTileDataReader() override;
|
||||
|
||||
|
||||
@@ -105,6 +105,10 @@ GdalWrapper::GdalWrapper(size_t maximumCacheSize,
|
||||
"GDAL_DATA",
|
||||
absPath("${MODULE_GLOBEBROWSING}/gdal_data").c_str()
|
||||
);
|
||||
CPLSetConfigOption(
|
||||
"CPL_TMPDIR",
|
||||
absPath("${BASE_PATH}").c_str()
|
||||
);
|
||||
setGdalProxyConfiguration();
|
||||
CPLSetErrorHandler(gdalErrorHandler);
|
||||
|
||||
|
||||
@@ -40,7 +40,9 @@ namespace {
|
||||
const char* KeyDoPreProcessing = "DoPreProcessing";
|
||||
const char* KeyTilePixelSize = "TilePixelSize";
|
||||
const char* KeyFilePath = "FilePath";
|
||||
const char* KeyBasePath = "BasePath";
|
||||
const char* KeyFlushInterval = "FlushInterval";
|
||||
const char* KeyPreCacheLevel = "PreCacheLevel";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
@@ -84,9 +86,12 @@ CachingTileProvider::CachingTileProvider(const ghoul::Dictionary& dictionary)
|
||||
framesUntilRequestFlush);
|
||||
}
|
||||
|
||||
std::string basePath;
|
||||
dictionary.getValue(KeyBasePath, basePath);
|
||||
|
||||
// Initialize instance variables
|
||||
#ifdef GLOBEBROWSING_USE_GDAL
|
||||
auto tileDataset = std::make_shared<GdalRawTileDataReader>(filePath, config);
|
||||
auto tileDataset = std::make_shared<GdalRawTileDataReader>(filePath, config, basePath);
|
||||
#else // GLOBEBROWSING_USE_GDAL
|
||||
auto tileDataset = std::make_shared<SimpleRawTileDataReader>(filePath, config);
|
||||
#endif // GLOBEBROWSING_USE_GDAL
|
||||
@@ -99,6 +104,18 @@ CachingTileProvider::CachingTileProvider(const ghoul::Dictionary& dictionary)
|
||||
_asyncTextureDataProvider = std::make_shared<AsyncTileDataProvider>(
|
||||
tileDataset, threadPool);
|
||||
_framesUntilRequestFlush = framesUntilRequestFlush;
|
||||
|
||||
if (dictionary.hasKeyAndValue<double>(KeyPreCacheLevel)) {
|
||||
int preCacheLevel = static_cast<int>(dictionary.value<double>(KeyPreCacheLevel));
|
||||
LDEBUG("Precaching '" << filePath << "' with level '" << preCacheLevel << "'");
|
||||
for (int level = 0; level <= preCacheLevel; ++level) {
|
||||
for (int x = 0; x <= level * 2; ++x) {
|
||||
for (int y = 0; y <= level; ++y) {
|
||||
_asyncTextureDataProvider->enqueueTileIO({ x, y, level });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CachingTileProvider::CachingTileProvider(
|
||||
|
||||
@@ -41,8 +41,11 @@ namespace {
|
||||
const char* KeyDoPreProcessing = "DoPreProcessing";
|
||||
const char* KeyMinimumPixelSize = "MinimumPixelSize";
|
||||
const char* KeyFilePath = "FilePath";
|
||||
const char* KeyBasePath = "BasePath";
|
||||
const char* KeyCacheSize = "CacheSize";
|
||||
const char* KeyFlushInterval = "FlushInterval";
|
||||
const char* KeyPreCacheStartTime = "PreCacheStartTime";
|
||||
const char* KeyPreCacheEndTime = "PreCacheEndTime";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
@@ -64,6 +67,8 @@ TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary)
|
||||
throw std::runtime_error(std::string("Must define key '") + KeyFilePath + "'");
|
||||
}
|
||||
|
||||
_datasetFile = absPath(_datasetFile);
|
||||
|
||||
std::ifstream in(_datasetFile.c_str());
|
||||
if (!in.is_open()) {
|
||||
throw ghoul::FileNotFoundError(_datasetFile);
|
||||
@@ -74,7 +79,29 @@ TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary)
|
||||
std::istreambuf_iterator<char>(in),
|
||||
(std::istreambuf_iterator<char>())
|
||||
);
|
||||
|
||||
_initDict.setValue<std::string>(
|
||||
KeyBasePath,
|
||||
ghoul::filesystem::File(_datasetFile).directoryName()
|
||||
);
|
||||
|
||||
_gdalXmlTemplate = consumeTemporalMetaData(xml);
|
||||
|
||||
const bool hasStart = dictionary.hasKeyAndValue<std::string>(KeyPreCacheStartTime);
|
||||
const bool hasEnd = dictionary.hasKeyAndValue<std::string>(KeyPreCacheEndTime);
|
||||
if (hasStart && hasEnd) {
|
||||
const std::string start = dictionary.value<std::string>(KeyPreCacheStartTime);
|
||||
const std::string end = dictionary.value<std::string>(KeyPreCacheEndTime);
|
||||
std::vector<Time> preCacheTimes = _timeQuantizer.quantized(
|
||||
Time(Time::convertTime(start)),
|
||||
Time(Time::convertTime(end))
|
||||
);
|
||||
|
||||
LINFO("Preloading: " << _datasetFile);
|
||||
for (Time& t : preCacheTimes) {
|
||||
getTileProvider(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string TemporalTileProvider::consumeTemporalMetaData(const std::string& xml) {
|
||||
@@ -378,6 +405,28 @@ bool TimeQuantizer::quantize(Time& t, bool clamp) const {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Time> TimeQuantizer::quantized(const Time& start, const Time& end) const {
|
||||
Time s = start;
|
||||
quantize(s, true);
|
||||
|
||||
Time e = end;
|
||||
quantize(e, true);
|
||||
|
||||
const double startSeconds = s.j2000Seconds();
|
||||
const double endSeconds = e.j2000Seconds();
|
||||
const double delta = endSeconds - startSeconds;
|
||||
|
||||
ghoul_assert(int(delta) % int(_resolution) == 0, "Quantization error");
|
||||
const int nSteps = delta / _resolution;
|
||||
|
||||
std::vector<Time> result(nSteps + 1);
|
||||
for (int i = 0; i <= nSteps; ++i) {
|
||||
result[i].setTime(startSeconds + i * _resolution, false);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace tileprovider
|
||||
} // namespace globebrowsing
|
||||
} // namespace openspace
|
||||
|
||||
@@ -151,6 +151,15 @@ struct TimeQuantizer {
|
||||
*/
|
||||
bool quantize(Time& t, bool clamp) const;
|
||||
|
||||
/**
|
||||
* Returns a list of quantized Time objects that represent all the valid quantized
|
||||
* Time%s between \p start and \p end.
|
||||
* \param start The start time for the time range quantization
|
||||
* \param end The end time for the time range quantization
|
||||
* \return A list of quantized times between \p start and \end
|
||||
*/
|
||||
std::vector<Time> quantized(const Time& start, const Time& end) const;
|
||||
|
||||
private:
|
||||
TimeRange _timerange;
|
||||
double _resolution;
|
||||
|
||||
Reference in New Issue
Block a user