mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-01 08:19:51 -05:00
extracting functions moved and task.cpp ready to be tested
This commit is contained in:
@@ -29,6 +29,7 @@ set(HEADER_FILES
|
||||
util/fieldlinesstate.h
|
||||
util/commons.h
|
||||
util/kameleonfieldlinehelper.h
|
||||
tasks/kameleonvolumetofieldlinestask.h
|
||||
)
|
||||
source_group("Header Files" FILES ${HEADER_FILES})
|
||||
|
||||
@@ -37,6 +38,7 @@ set(SOURCE_FILES
|
||||
util/fieldlinesstate.cpp
|
||||
util/commons.cpp
|
||||
util/kameleonfieldlinehelper.cpp
|
||||
tasks/kameleonvolumetofieldlinestask.cpp
|
||||
)
|
||||
source_group("Source Files" FILES ${SOURCE_FILES})
|
||||
|
||||
|
||||
@@ -261,10 +261,6 @@ namespace {
|
||||
|
||||
namespace openspace {
|
||||
fls::Model stringToModel(std::string str);
|
||||
std::unordered_map<std::string, std::vector<glm::vec3>>
|
||||
extractSeedPointsFromFiles(std::filesystem::path);
|
||||
std::vector<std::string>
|
||||
extractMagnitudeVarsFromStrings(std::vector<std::string> extrVars);
|
||||
|
||||
documentation::Documentation RenderableFieldlinesSequence::Documentation() {
|
||||
return codegen::doc<Parameters>("fieldlinessequence_renderablefieldlinessequence");
|
||||
@@ -577,7 +573,7 @@ bool RenderableFieldlinesSequence::prepareForOsflsStreaming() {
|
||||
_states.push_back(newState);
|
||||
_nStates = _startTimes.size();
|
||||
if (_nStates == 1) {
|
||||
// loading dynamicaly is not nessesary if only having one set in the sequence
|
||||
// loading dynamicaly is not nessesary if only having one set in the sequence
|
||||
_loadingStatesDynamically = false;
|
||||
}
|
||||
_activeStateIndex = 0;
|
||||
@@ -793,10 +789,10 @@ void RenderableFieldlinesSequence::addStateToSequence(FieldlinesState& state) {
|
||||
}
|
||||
|
||||
bool RenderableFieldlinesSequence::getStatesFromCdfFiles() {
|
||||
std::vector<std::string> extraMagVars = extractMagnitudeVarsFromStrings(_extraVars);
|
||||
std::vector<std::string> extraMagVars = fls::extractMagnitudeVarsFromStrings(_extraVars);
|
||||
|
||||
std::unordered_map<std::string, std::vector<glm::vec3>> seedsPerFiles =
|
||||
extractSeedPointsFromFiles(_seedPointDirectory);
|
||||
fls::extractSeedPointsFromFiles(_seedPointDirectory);
|
||||
if (seedsPerFiles.empty()) {
|
||||
LERROR("No seed files found");
|
||||
return false;
|
||||
@@ -824,101 +820,6 @@ bool RenderableFieldlinesSequence::getStatesFromCdfFiles() {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::vector<glm::vec3>>
|
||||
extractSeedPointsFromFiles(std::filesystem::path filePath)
|
||||
{
|
||||
std::unordered_map<std::string, std::vector<glm::vec3>> outMap;
|
||||
|
||||
if (!std::filesystem::is_directory(filePath)) {
|
||||
LERROR(fmt::format(
|
||||
"The specified seed point directory: '{}' does not exist", filePath
|
||||
));
|
||||
return outMap;
|
||||
}
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
for (const fs::directory_entry& spFile : fs::directory_iterator(filePath)) {
|
||||
std::string seedFilePath = spFile.path().string();
|
||||
if (!spFile.is_regular_file() ||
|
||||
seedFilePath.substr(seedFilePath.find_last_of('.') + 1) != "txt")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::ifstream seedFile(seedFilePath);
|
||||
if (!seedFile.good()) {
|
||||
LERROR(fmt::format("Could not open seed points file '{}'", seedFilePath));
|
||||
outMap.clear();
|
||||
return {};
|
||||
}
|
||||
|
||||
LDEBUG(fmt::format("Reading seed points from file '{}'", seedFilePath));
|
||||
std::string line;
|
||||
std::vector<glm::vec3> outVec;
|
||||
while (std::getline(seedFile, line)) {
|
||||
std::stringstream ss(line);
|
||||
glm::vec3 point;
|
||||
ss >> point.x;
|
||||
ss >> point.y;
|
||||
ss >> point.z;
|
||||
outVec.push_back(std::move(point));
|
||||
}
|
||||
|
||||
if (outVec.empty()) {
|
||||
LERROR(fmt::format("Found no seed points in: {}", seedFilePath));
|
||||
outMap.clear();
|
||||
return {};
|
||||
}
|
||||
|
||||
size_t lastIndex = seedFilePath.find_last_of('.');
|
||||
std::string name = seedFilePath.substr(0, lastIndex); // remove file extention
|
||||
size_t dateAndTimeSeperator = name.find_last_of('_');
|
||||
std::string time = name.substr(dateAndTimeSeperator + 1, name.length());
|
||||
std::string date = name.substr(dateAndTimeSeperator - 8, 8); // 8 for yyyymmdd
|
||||
std::string dateAndTime = date + time;
|
||||
|
||||
// add outVec as value and time stamp as int as key
|
||||
outMap[dateAndTime] = outVec;
|
||||
}
|
||||
return outMap;
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
extractMagnitudeVarsFromStrings(std::vector<std::string> extrVars)
|
||||
{
|
||||
std::vector<std::string> extraMagVars;
|
||||
for (int i = 0; i < static_cast<int>(extrVars.size()); i++) {
|
||||
const std::string& str = extrVars[i];
|
||||
// Check if string is in the format specified for magnitude variables
|
||||
if (str.substr(0, 2) == "|(" && str.substr(str.size() - 2, 2) == ")|") {
|
||||
std::istringstream ss(str.substr(2, str.size() - 4));
|
||||
std::string magVar;
|
||||
size_t counter = 0;
|
||||
while (std::getline(ss, magVar, ',')) {
|
||||
magVar.erase(
|
||||
std::remove_if(
|
||||
magVar.begin(),
|
||||
magVar.end(),
|
||||
::isspace
|
||||
),
|
||||
magVar.end()
|
||||
);
|
||||
extraMagVars.push_back(magVar);
|
||||
counter++;
|
||||
if (counter == 3) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (counter != 3 && counter > 0) {
|
||||
extraMagVars.erase(extraMagVars.end() - counter, extraMagVars.end());
|
||||
}
|
||||
extrVars.erase(extrVars.begin() + i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return extraMagVars;
|
||||
}
|
||||
|
||||
void RenderableFieldlinesSequence::deinitializeGL() {
|
||||
glDeleteVertexArrays(1, &_vertexArrayObject);
|
||||
_vertexArrayObject = 0;
|
||||
@@ -1046,7 +947,7 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) {
|
||||
const double currentTime = data.time.j2000Seconds();
|
||||
const bool isInInterval = (currentTime >= _startTimes[0]) &&
|
||||
(currentTime < _sequenceEndTime);
|
||||
|
||||
|
||||
// Check if current time in OpenSpace is within sequence interval
|
||||
if (isInInterval) {
|
||||
const size_t nextIdx = _activeTriggerTimeIndex + 1;
|
||||
|
||||
@@ -108,7 +108,7 @@ private:
|
||||
// line segments
|
||||
bool _shouldUpdateMaskingBuffer = false;
|
||||
// note Elon: rework the case of only one state
|
||||
// hasBeenUpdated only gets sets once, first iteration of update function, to
|
||||
// hasBeenUpdated only gets sets once, first iteration of update function, to
|
||||
// guarantee the vertext position buffer to be initialized.
|
||||
bool _hasBeenUpdated = false;
|
||||
|
||||
|
||||
@@ -23,120 +23,155 @@
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/fieldlinessequence/tasks/kameleonvolumetofieldlinestask.h>
|
||||
#include <modules/fieldlinessequence/rendering/renderablefieldlinessequence.h>
|
||||
|
||||
#include <modules/fieldlinessequence/util/fieldlinesstate.h>
|
||||
#include <modules/fieldlinessequence/util/kameleonfieldlinehelper.h>
|
||||
#include <modules/volume/rawvolumewriter.h>
|
||||
#include <openspace/util/spicemanager.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <ghoul/fmt.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/dictionaryluaformatter.h>
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const char* KeyInput = "Input";
|
||||
constexpr const char* KeyTimeKernel = "TimeKernel";
|
||||
constexpr const char* KeyOutputFolder = "OutputFolder";
|
||||
constexpr const char* KeySeedpoints = "Seedpoints";
|
||||
constexpr const char* KeyTracingVar = "TracingVar";
|
||||
constexpr const char* KeyExtraScalarVars = "ExtraScalarVars";
|
||||
constexpr const char* KeyExtraMagnitudeVars = "ExtraMagnitudeVars";
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
constexpr std::string_view _loggerCat = "KameleonVolumeToFieldlinesTask";
|
||||
|
||||
struct [[codegen::Dictionary(KameleonVolumeToFieldLinesTask)]] Parameters {
|
||||
// The cdf file to extract data from
|
||||
struct [[codegen::Dictionary(KameleonVolumeToFieldlinesTask)]] Parameters {
|
||||
// The folder to the cdf files to extract data from
|
||||
std::filesystem::path input;
|
||||
// A text file with seedpoints with the format x1 y1 z1 x2 y2 z2 ...
|
||||
// Seedpoints are expressed in the native coordinate system of the model.
|
||||
std::filesystem::path seedpoints
|
||||
std::filesystem::path seedpoints;
|
||||
// If data sets parameter start_time differ from start of run,
|
||||
// elapsed_time_in_seconds might be in relation to start of run.
|
||||
// ManuelTimeOffset will be added to trigger time.
|
||||
std::optional<double> manualTimeOffset;
|
||||
// The name of the kameleon variable to use for tracing, like b, or u
|
||||
std::string tracingVar;
|
||||
// The folder to write the files to
|
||||
std::filesystem::path outputFolder;
|
||||
|
||||
enum class ConversionType {
|
||||
Json,
|
||||
Osfls
|
||||
};
|
||||
// Output type. Either osfls (OpenSpace FieldLineSequence) or json
|
||||
std::string outputType;
|
||||
ConversionType outputType;
|
||||
// A list of vector variables to extract along the fieldlines
|
||||
std::optional<std::vector<std::string>> extraScalarVars;
|
||||
std::optional<std::vector<std::string>> extraVars;
|
||||
};
|
||||
#include "kameleonvolumetofieldlinestask_codegen.cpp"
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation KameleonVolumeToFieldlinesTask::documentation() {
|
||||
return codegen::doc<Parameters>("kameleon_volume_to_fieldlines_task")
|
||||
return codegen::doc<Parameters>("kameleon_volume_to_fieldlines_task");
|
||||
}
|
||||
|
||||
KameleonVolumeToFieldlinesTask::KameleonVolumeToFieldlinesTask(
|
||||
const ghoul::Dictionary& dictionary)
|
||||
{
|
||||
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_inputPath = p.input.value();
|
||||
_seedpointsPath = p.seepoints.value();
|
||||
_outputFolder = p.outputFolder.value();
|
||||
_outputType = p.outputType.value();
|
||||
_tracingVar = p.tracingVar.value_or(_tractingVar);
|
||||
_inputPath = p.input;
|
||||
_seedpointsPath = p.seedpoints;
|
||||
_manualTimeOffset = p.manualTimeOffset.value_or(_manualTimeOffset);
|
||||
_outputFolder = p.outputFolder;
|
||||
|
||||
if (dictionary.hasKey(KeyExtraScalarVars)) {
|
||||
ghoul::Dictionary list = dictionary.value<ghoul::Dictionary>(KeyExtraScalarVars);
|
||||
for (size_t i = 0; i < list.size(); ++i) {
|
||||
_extraScalarVars.push_back(list.value<std::string>(std::to_string(i)));
|
||||
switch (p.outputType) {
|
||||
case Parameters::ConversionType::Json:
|
||||
break;
|
||||
_outputType = conversionType::Json;
|
||||
case Parameters::ConversionType::Osfls:
|
||||
_outputType = conversionType::Osfls;
|
||||
break;
|
||||
default:
|
||||
LERROR("outputType must be either json or osfls");
|
||||
}
|
||||
|
||||
_tracingVar= p.tracingVar;
|
||||
|
||||
//_tracingVar = p.tracingVar.value_or(_tractingVar);
|
||||
if (p.extraVars.has_value()) {
|
||||
for (auto var : p.extraVars.value()) {
|
||||
_extraVars.push_back(var);
|
||||
}
|
||||
}
|
||||
if (dictionary.hasKey(KeyExtraMagnitudeVars)) {
|
||||
ghoul::Dictionary list =
|
||||
dictionary.value<ghoul::Dictionary>(KeyExtraMagnitudeVars);
|
||||
|
||||
for (size_t i = 0; i < list.size(); ++i) {
|
||||
_extraMagnitudeVars.push_back(list.value<std::string>(std::to_string(i)));
|
||||
if (!std::filesystem::is_directory(_inputPath)) {
|
||||
LERROR(fmt::format(
|
||||
"KameleonVolumeToFieldlineTask: {} is not a valid directory",
|
||||
_inputPath
|
||||
));
|
||||
}
|
||||
|
||||
namespace fsm = std::filesystem;
|
||||
for (const fsm::directory_entry& e : fsm::directory_iterator(_inputPath)){
|
||||
if (e.is_regular_file()) {
|
||||
std::string eStr = e.path().string();
|
||||
_sourceFiles.push_back(eStr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string KameleonVolumeToFieldlinesTask::description() {
|
||||
return fmt::format(
|
||||
"Extract fieldline data from cdf file {} and seedpoint file {}. "
|
||||
"Write osfls file into the folder {}.",
|
||||
"Write either osfls files or json files into the folder {}.",
|
||||
_inputPath, _seedpointsPath, _outputFolder
|
||||
);
|
||||
}
|
||||
|
||||
void KameleonVolumeToFieldlinesTask::perform(
|
||||
const Task::ProgressCallback& progressCallback)
|
||||
const Task::ProgressCallback& progressCallback)
|
||||
{
|
||||
std::vector<std::string> extraMagVars =
|
||||
fls::extractMagnitudeVarsFromStrings(_extraVars);
|
||||
|
||||
std::vector<glm::vec3> seedPoints;
|
||||
bool readSeedpoints = fls::extractSeedPointsFromFile(_seedpointsPath, seedPoints);
|
||||
std::unordered_map<std::string, std::vector<glm::vec3>> seedPoints =
|
||||
fls::extractSeedPointsFromFiles(_seedpointsPath);
|
||||
|
||||
if (!readSeedpoints) {
|
||||
if (seedPoints.empty()) {
|
||||
LERROR("Falied to read seedpoints");
|
||||
return;
|
||||
}
|
||||
|
||||
for (const std::string& cdfPath : _sourceFiles) {
|
||||
FieldlinesState newState;
|
||||
bool isSuccessful = fls::convertCdfToFieldlinesState(
|
||||
newState,
|
||||
cdfPath,
|
||||
seedPoints,
|
||||
_manualTimeOffset,
|
||||
_tracingVar,
|
||||
_extraVars,
|
||||
extraMagVars
|
||||
);
|
||||
|
||||
FieldlinesState newState;
|
||||
bool isSuccessful = fls::convertCdfToFieldlinesState(
|
||||
newState,
|
||||
_inputPath,
|
||||
seedPoints,
|
||||
_tracingVar,
|
||||
_extraScalarVars,
|
||||
_extraMagnitudeVars
|
||||
);
|
||||
|
||||
if (isSuccessful) {
|
||||
return newState.saveStateToOsfls(_outputFolder);
|
||||
if (isSuccessful) {
|
||||
if (_outputType == conversionType::Osfls) {
|
||||
newState.saveStateToOsfls(absPath(_outputFolder).string());
|
||||
}
|
||||
else if (_outputType == conversionType::Json) {
|
||||
std::string timeStr = std::string(Time(newState.triggerTime()).ISO8601());
|
||||
timeStr.replace(13, 1, "-");
|
||||
timeStr.replace(16, 1, "-");
|
||||
timeStr.replace(19, 1, "-");
|
||||
std::string fileName = timeStr + "json";
|
||||
newState.saveStateToJson(_outputFolder.string() + fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Ideally, we would want to signal about progress earlier as well, but
|
||||
// convertCdfToFieldlinesState does all the work encapsulated in one function call.
|
||||
progressCallback(1.0f);
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include <string>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class KameleonVolumeToFieldlinesTask : public Task {
|
||||
public:
|
||||
KameleonVolumeToFieldlinesTask(const ghoul::Dictionary& dictionary);
|
||||
@@ -42,12 +41,17 @@ namespace openspace {
|
||||
static documentation::Documentation documentation();
|
||||
|
||||
private:
|
||||
enum class conversionType {
|
||||
Json,
|
||||
Osfls
|
||||
};
|
||||
std::string _tracingVar;
|
||||
std::vector<std::string> _extraScalarVars;
|
||||
std::vector<std::string> _extraMagnitudeVars;
|
||||
std::vector<std::string> _extraVars;
|
||||
std::filesystem::path _inputPath;
|
||||
//std::string _timeKernelPath;
|
||||
std::vector<std::string> _sourceFiles;
|
||||
double _manualTimeOffset = 0.0;
|
||||
std::filesystem::path _seedpointsPath;
|
||||
conversionType _outputType;
|
||||
std::filesystem::path _outputFolder;
|
||||
};
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ bool FieldlinesState::loadStateFromJson(const std::string& pathToJsonFile,
|
||||
}
|
||||
|
||||
/**
|
||||
* \param absPath must be the path to the file (incl. filename but excl. extension!)
|
||||
* \param absPath must be the path to the folder to save to.
|
||||
* Directory must exist! File is created (or overwritten if already existing).
|
||||
* File is structured like this: (for version 0)
|
||||
* 0. int - version number of binary state file! (in case something
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <ghoul/fmt.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <memory>
|
||||
#include <fstream>
|
||||
|
||||
#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
|
||||
@@ -74,6 +75,100 @@ namespace openspace::fls {
|
||||
#endif // OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
// ------------------------------------------------------------------------------------ //
|
||||
|
||||
std::unordered_map<std::string, std::vector<glm::vec3>>
|
||||
extractSeedPointsFromFiles(std::filesystem::path filePath) {
|
||||
std::unordered_map<std::string, std::vector<glm::vec3>> outMap;
|
||||
|
||||
if (!std::filesystem::is_directory(filePath)) {
|
||||
LERROR(fmt::format(
|
||||
"The specified seed point directory: '{}' does not exist", filePath
|
||||
));
|
||||
return outMap;
|
||||
}
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
for (const fs::directory_entry& spFile : fs::directory_iterator(filePath)) {
|
||||
std::string seedFilePath = spFile.path().string();
|
||||
if (!spFile.is_regular_file() ||
|
||||
seedFilePath.substr(seedFilePath.find_last_of('.') + 1) != "txt")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::ifstream seedFile(seedFilePath);
|
||||
if (!seedFile.good()) {
|
||||
LERROR(fmt::format("Could not open seed points file '{}'", seedFilePath));
|
||||
outMap.clear();
|
||||
return {};
|
||||
}
|
||||
|
||||
LDEBUG(fmt::format("Reading seed points from file '{}'", seedFilePath));
|
||||
std::string line;
|
||||
std::vector<glm::vec3> outVec;
|
||||
while (std::getline(seedFile, line)) {
|
||||
std::stringstream ss(line);
|
||||
glm::vec3 point;
|
||||
ss >> point.x;
|
||||
ss >> point.y;
|
||||
ss >> point.z;
|
||||
outVec.push_back(std::move(point));
|
||||
}
|
||||
|
||||
if (outVec.empty()) {
|
||||
LERROR(fmt::format("Found no seed points in: {}", seedFilePath));
|
||||
outMap.clear();
|
||||
return {};
|
||||
}
|
||||
|
||||
size_t lastIndex = seedFilePath.find_last_of('.');
|
||||
std::string name = seedFilePath.substr(0, lastIndex); // remove file extention
|
||||
size_t dateAndTimeSeperator = name.find_last_of('_');
|
||||
std::string time = name.substr(dateAndTimeSeperator + 1, name.length());
|
||||
std::string date = name.substr(dateAndTimeSeperator - 8, 8); // 8 for yyyymmdd
|
||||
std::string dateAndTime = date + time;
|
||||
|
||||
// add outVec as value and time stamp as int as key
|
||||
outMap[dateAndTime] = outVec;
|
||||
}
|
||||
return outMap;
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
extractMagnitudeVarsFromStrings(std::vector<std::string> extrVars) {
|
||||
std::vector<std::string> extraMagVars;
|
||||
for (int i = 0; i < static_cast<int>(extrVars.size()); i++) {
|
||||
const std::string& str = extrVars[i];
|
||||
// Check if string is in the format specified for magnitude variables
|
||||
if (str.substr(0, 2) == "|(" && str.substr(str.size() - 2, 2) == ")|") {
|
||||
std::istringstream ss(str.substr(2, str.size() - 4));
|
||||
std::string magVar;
|
||||
size_t counter = 0;
|
||||
while (std::getline(ss, magVar, ',')) {
|
||||
magVar.erase(
|
||||
std::remove_if(
|
||||
magVar.begin(),
|
||||
magVar.end(),
|
||||
::isspace
|
||||
),
|
||||
magVar.end()
|
||||
);
|
||||
extraMagVars.push_back(magVar);
|
||||
counter++;
|
||||
if (counter == 3) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (counter != 3 && counter > 0) {
|
||||
extraMagVars.erase(extraMagVars.end() - counter, extraMagVars.end());
|
||||
}
|
||||
extrVars.erase(extrVars.begin() + i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return extraMagVars;
|
||||
}
|
||||
|
||||
|
||||
/** Traces field lines from the provided cdf file using kameleon and stores the data in
|
||||
* the provided FieldlinesState.
|
||||
* Returns `false` if it fails to create a valid state. Requires the kameleon module to
|
||||
|
||||
@@ -35,7 +35,10 @@ namespace openspace {
|
||||
class FieldlinesState;
|
||||
|
||||
namespace fls {
|
||||
|
||||
std::unordered_map<std::string, std::vector<glm::vec3>>
|
||||
extractSeedPointsFromFiles(std::filesystem::path);
|
||||
std::vector<std::string>
|
||||
extractMagnitudeVarsFromStrings(std::vector<std::string> extrVars);
|
||||
bool convertCdfToFieldlinesState(FieldlinesState& state, const std::string& cdfPath,
|
||||
const std::unordered_map<std::string, std::vector<glm::vec3>>& seedMap,
|
||||
double manualTimeOffset, const std::string& tracingVar,
|
||||
|
||||
Reference in New Issue
Block a user