mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-07 04:00:37 -06:00
solve merge conflict
This commit is contained in:
@@ -29,22 +29,22 @@ function postInitialization()
|
||||
openspace.setPropertyValue("MilkyWay.renderable.segments", 50)
|
||||
|
||||
openspace.printInfo("Done setting default values")
|
||||
|
||||
--openspace.iswa.addCygnet(0,"x");
|
||||
--openspace.iswa.addCygnet(0,"y", "Kameleon");
|
||||
--openspace.iswa.addCygnet(0,"z", "Kameleon");
|
||||
|
||||
--openspace.iswa.addCygnet(-4,"Data");
|
||||
--openspace.iswa.addCygnet(-4,"Data","Ion");
|
||||
|
||||
--openspace.iswa.addCygnet(-1,"Data");
|
||||
--openspace.iswa.addCygnet(-2,"Data");
|
||||
--openspace.iswa.addCygnet(-3,"Data");
|
||||
|
||||
--openspace.iswa.addCygnet(-1,"Texture");
|
||||
--openspace.iswa.addCygnet(-2,"Texture");
|
||||
--openspace.iswa.addCygnet(-3,"Texture");
|
||||
|
||||
|
||||
--openspace.iswa.addCygnet(-3,"Data","GM");
|
||||
--openspace.iswa.addCygnet(-2,"Data","GM");
|
||||
--openspace.iswa.addCygnet(-1,"Data","GM");
|
||||
|
||||
|
||||
openspace.iswa.addCdfFiles("${OPENSPACE_DATA}/cdflist.json");
|
||||
|
||||
--[[
|
||||
|
||||
@@ -4,6 +4,8 @@ local file3 = '${OPENSPACE_DATA}/scene/fieldlines/bats_seeds/BATS_R_US_open_sout
|
||||
local file4 = '${OPENSPACE_DATA}/scene/fieldlines/bats_seeds/BATS_R_US_solar_wind_all.txt';
|
||||
local file5 = '${OPENSPACE_DATA}/scene/fieldlines/bats_seeds/BATS_R_US_separatrix_seeds_all.txt';
|
||||
|
||||
local volumeFile = '${OPENSPACE_DATA}/batsrus.cdf';
|
||||
|
||||
return {
|
||||
{
|
||||
Name = "Fieldlines1",
|
||||
@@ -16,7 +18,7 @@ return {
|
||||
Type = "RenderableFieldlines",
|
||||
VectorField = {
|
||||
Type = "VolumeKameleon",
|
||||
File = "${OPENSPACE_DATA}/BATSRUS.cdf",
|
||||
File = volumeFile,
|
||||
Model = "BATSRUS",
|
||||
Variables = {"bx", "by", "bz"}
|
||||
},
|
||||
@@ -42,7 +44,7 @@ return {
|
||||
Type = "RenderableFieldlines",
|
||||
VectorField = {
|
||||
Type = "VolumeKameleon",
|
||||
File = "${OPENSPACE_DATA}/BATSRUS.cdf",
|
||||
File = volumeFile,
|
||||
Model = "BATSRUS",
|
||||
Variables = {"bx", "by", "bz"}
|
||||
},
|
||||
@@ -68,7 +70,7 @@ return {
|
||||
Type = "RenderableFieldlines",
|
||||
VectorField = {
|
||||
Type = "VolumeKameleon",
|
||||
File = "${OPENSPACE_DATA}/BATSRUS.cdf",
|
||||
File = volumeFile,
|
||||
Model = "BATSRUS",
|
||||
Variables = {"bx", "by", "bz"}
|
||||
},
|
||||
@@ -94,7 +96,7 @@ return {
|
||||
Type = "RenderableFieldlines",
|
||||
VectorField = {
|
||||
Type = "VolumeKameleon",
|
||||
File = "${OPENSPACE_DATA}/BATSRUS.cdf",
|
||||
File = volumeFile,
|
||||
Model = "BATSRUS",
|
||||
Variables = {"bx", "by", "bz"}
|
||||
},
|
||||
@@ -120,7 +122,7 @@ return {
|
||||
Type = "RenderableFieldlines",
|
||||
VectorField = {
|
||||
Type = "VolumeKameleon",
|
||||
File = "${OPENSPACE_DATA}/BATSRUS.cdf",
|
||||
File = volumeFile,
|
||||
Model = "BATSRUS",
|
||||
Variables = {"bx", "by", "bz"}
|
||||
},
|
||||
|
||||
@@ -27,6 +27,9 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake)
|
||||
set(HEADER_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/iswamanager.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/dataprocessor.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/dataprocessortext.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/dataprocessorjson.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/dataprocessorkameleon.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/cygnetplane.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/iswacygnet.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/dataplane.h
|
||||
@@ -44,6 +47,9 @@ source_group("Header Files" FILES ${HEADER_FILES})
|
||||
set(SOURCE_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/iswamanager.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/dataprocessor.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/dataprocessortext.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/dataprocessorjson.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/dataprocessorkameleon.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/iswacygnet.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/cygnetplane.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/dataplane.cpp
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <ghoul/io/texture/texturereader.h>
|
||||
#include <ghoul/opengl/textureunit.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <modules/iswa/util/dataprocessortext.h>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "DataCygnet";
|
||||
@@ -42,7 +43,6 @@ DataCygnet::DataCygnet(const ghoul::Dictionary& dictionary)
|
||||
{
|
||||
addProperty(_dataOptions);
|
||||
registerProperties();
|
||||
_type = IswaManager::CygnetType::Data;
|
||||
}
|
||||
|
||||
DataCygnet::~DataCygnet(){}
|
||||
@@ -66,13 +66,7 @@ bool DataCygnet::loadTexture(){
|
||||
|
||||
if(!_dataOptions.options().size()){ // load options for value selection
|
||||
fillOptions();
|
||||
|
||||
//Temporary if statements
|
||||
if( className == "DataSphere"){
|
||||
_dataProcessor->addValuesFromJSON(_dataBuffer, _dataOptions);
|
||||
} else if(className == "DataPlane"){
|
||||
_dataProcessor->addValues(_dataBuffer, _dataOptions);
|
||||
}
|
||||
_dataProcessor->addDataValues(_dataBuffer, _dataOptions);
|
||||
|
||||
// if this datacygnet has added new values then reload texture
|
||||
// for the whole group, including this datacygnet, and return after.
|
||||
@@ -81,14 +75,9 @@ bool DataCygnet::loadTexture(){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//Temporary if statements
|
||||
std::vector<float*> data;
|
||||
if( className == "DataSphere"){
|
||||
data = _dataProcessor->readJSONData2(_dataBuffer, _dataOptions);
|
||||
} else if(className == "DataPlane"){
|
||||
data = _dataProcessor->readData2(_dataBuffer, _dataOptions);
|
||||
}
|
||||
|
||||
|
||||
std::vector<float*> data = _dataProcessor->processData(_dataBuffer, _dataOptions);
|
||||
|
||||
if(data.empty())
|
||||
return false;
|
||||
|
||||
@@ -231,13 +220,7 @@ void DataCygnet::readTransferFunctions(std::string tfPath){
|
||||
}
|
||||
|
||||
void DataCygnet::fillOptions(){
|
||||
std::vector<std::string> options;
|
||||
//Temporary if statements
|
||||
if( className == "DataSphere"){
|
||||
options = _dataProcessor->readJSONHeader(_dataBuffer);
|
||||
} else if(className == "DataPlane"){
|
||||
options = _dataProcessor->readHeader(_dataBuffer);
|
||||
}
|
||||
std::vector<std::string> options = _dataProcessor->readMetadata(_dataBuffer);
|
||||
|
||||
for(int i=0; i<options.size(); i++){
|
||||
_dataOptions.addOption({i, options[i]});
|
||||
|
||||
@@ -74,14 +74,10 @@ protected:
|
||||
properties::SelectionProperty _dataOptions;
|
||||
std::shared_ptr<DataProcessor> _dataProcessor;
|
||||
|
||||
// Temporary variable untill dataprocessor is done
|
||||
std::string className;
|
||||
|
||||
private:
|
||||
void fillOptions();
|
||||
|
||||
std::string _dataBuffer;
|
||||
|
||||
};
|
||||
} //namespace openspace
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
#include <modules/iswa/rendering/dataplane.h>
|
||||
#include <modules/iswa/util/dataprocessortext.h>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "DataPlane";
|
||||
@@ -49,14 +50,13 @@ DataPlane::DataPlane(const ghoul::Dictionary& dictionary)
|
||||
_programName = "DataPlaneProgram";
|
||||
_vsPath = "${MODULE_ISWA}/shaders/dataplane_vs.glsl";
|
||||
_fsPath = "${MODULE_ISWA}/shaders/dataplane_fs.glsl";
|
||||
|
||||
// Temporary
|
||||
className = "DataPlane";
|
||||
}
|
||||
|
||||
DataPlane::~DataPlane(){}
|
||||
|
||||
bool DataPlane::initialize(){
|
||||
std::cout << "DataPlane: " << typeid(this).name() << std::endl;
|
||||
|
||||
IswaCygnet::initialize();
|
||||
|
||||
if(_group){
|
||||
@@ -70,12 +70,7 @@ bool DataPlane::initialize(){
|
||||
OsEng.gui()._iswa.registerProperty(&_backgroundValues);
|
||||
OsEng.gui()._iswa.registerProperty(&_transferFunctionsFile);
|
||||
OsEng.gui()._iswa.registerProperty(&_dataOptions);
|
||||
_dataProcessor = std::make_shared<DataProcessor>(
|
||||
_useLog.value(),
|
||||
_useHistogram.value(),
|
||||
_normValues
|
||||
);
|
||||
|
||||
_dataProcessor = std::make_shared<DataProcessorText>();
|
||||
|
||||
//If autofiler is on, background values property should be hidden
|
||||
_autoFilter.onChange([this](){
|
||||
@@ -182,12 +177,13 @@ void DataPlane::setUniforms(){
|
||||
}
|
||||
|
||||
void DataPlane::subscribeToGroup(){
|
||||
_groupEvent->subscribe(name(), "useLogChanged", [&](const ghoul::Dictionary& dict){
|
||||
auto groupEvent = _group->groupEvent();
|
||||
groupEvent->subscribe(name(), "useLogChanged", [&](const ghoul::Dictionary& dict){
|
||||
LDEBUG(name() + " Event useLogChanged");
|
||||
_useLog.setValue(dict.value<bool>("useLog"));
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "normValuesChanged", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "normValuesChanged", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event normValuesChanged");
|
||||
std::shared_ptr<glm::vec2> values;
|
||||
bool success = dict.getValue("normValues", values);
|
||||
@@ -196,12 +192,12 @@ void DataPlane::subscribeToGroup(){
|
||||
}
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "useHistogramChanged", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "useHistogramChanged", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event useHistogramChanged");
|
||||
_useHistogram.setValue(dict.value<bool>("useHistogram"));
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "dataOptionsChanged", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "dataOptionsChanged", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event dataOptionsChanged");
|
||||
std::shared_ptr<std::vector<int> > values;
|
||||
bool success = dict.getValue("dataOptions", values);
|
||||
@@ -210,12 +206,12 @@ void DataPlane::subscribeToGroup(){
|
||||
}
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "transferFunctionsChanged", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "transferFunctionsChanged", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event transferFunctionsChanged");
|
||||
_transferFunctionsFile.setValue(dict.value<std::string>("transferFunctions"));
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "backgroundValuesChanged", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "backgroundValuesChanged", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event backgroundValuesChanged");
|
||||
std::shared_ptr<glm::vec2> values;
|
||||
bool success = dict.getValue("backgroundValues", values);
|
||||
@@ -224,16 +220,15 @@ void DataPlane::subscribeToGroup(){
|
||||
}
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "autoFilterChanged", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "autoFilterChanged", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event autoFilterChanged");
|
||||
_autoFilter.setValue(dict.value<bool>("autoFilter"));
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "updateGroup", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "updateGroup", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event updateGroup");
|
||||
loadTexture();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}// namespace openspace
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <modules/iswa/rendering/datasphere.h>
|
||||
#include <openspace/util/powerscaledsphere.h>
|
||||
#include <modules/iswa/util/dataprocessorjson.h>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "DataSphere";
|
||||
@@ -55,9 +56,6 @@ DataSphere::DataSphere(const ghoul::Dictionary& dictionary)
|
||||
_programName = "DataSphereProgram";
|
||||
_vsPath = "${MODULE_ISWA}/shaders/datasphere_vs.glsl";
|
||||
_fsPath = "${MODULE_ISWA}/shaders/datasphere_fs.glsl";
|
||||
|
||||
// Temporary
|
||||
className = "DataSphere";
|
||||
}
|
||||
|
||||
DataSphere::~DataSphere(){}
|
||||
@@ -76,12 +74,8 @@ bool DataSphere::initialize(){
|
||||
OsEng.gui()._iswa.registerProperty(&_normValues);
|
||||
OsEng.gui()._iswa.registerProperty(&_transferFunctionsFile);
|
||||
OsEng.gui()._iswa.registerProperty(&_dataOptions);
|
||||
_dataProcessor = std::make_shared<DataProcessor>(
|
||||
_useLog.value(),
|
||||
_useHistogram.value(),
|
||||
_normValues
|
||||
);
|
||||
|
||||
_dataProcessor = std::make_shared<DataProcessorJson>();
|
||||
//If autofiler is on, background values property should be hidden
|
||||
_autoFilter.onChange([this](){
|
||||
// If autofiler is selected, use _dataProcessor to set backgroundValues
|
||||
@@ -157,12 +151,13 @@ void DataSphere::setUniforms(){
|
||||
}
|
||||
|
||||
void DataSphere::subscribeToGroup(){
|
||||
_groupEvent->subscribe(name(), "useLogChanged", [&](const ghoul::Dictionary& dict){
|
||||
auto groupEvent = _group->groupEvent();
|
||||
groupEvent->subscribe(name(), "useLogChanged", [&](const ghoul::Dictionary& dict){
|
||||
LDEBUG(name() + " Event useLogChanged");
|
||||
_useLog.setValue(dict.value<bool>("useLog"));
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "normValuesChanged", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "normValuesChanged", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event normValuesChanged");
|
||||
std::shared_ptr<glm::vec2> values;
|
||||
bool success = dict.getValue("normValues", values);
|
||||
@@ -171,12 +166,12 @@ void DataSphere::subscribeToGroup(){
|
||||
}
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "useHistogramChanged", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "useHistogramChanged", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event useHistogramChanged");
|
||||
_useHistogram.setValue(dict.value<bool>("useHistogram"));
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "dataOptionsChanged", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "dataOptionsChanged", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event dataOptionsChanged");
|
||||
std::shared_ptr<std::vector<int> > values;
|
||||
bool success = dict.getValue("dataOptions", values);
|
||||
@@ -185,12 +180,12 @@ void DataSphere::subscribeToGroup(){
|
||||
}
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "transferFunctionsChanged", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "transferFunctionsChanged", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event transferFunctionsChanged");
|
||||
_transferFunctionsFile.setValue(dict.value<std::string>("transferFunctions"));
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "backgroundValuesChanged", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "backgroundValuesChanged", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event backgroundValuesChanged");
|
||||
std::shared_ptr<glm::vec2> values;
|
||||
bool success = dict.getValue("backgroundValues", values);
|
||||
@@ -199,16 +194,15 @@ void DataSphere::subscribeToGroup(){
|
||||
}
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "autoFilterChanged", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "autoFilterChanged", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event autoFilterChanged");
|
||||
_autoFilter.setValue(dict.value<bool>("autoFilter"));
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "updateGroup", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "updateGroup", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event updateGroup");
|
||||
loadTexture();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
} //namespace openspace
|
||||
@@ -26,6 +26,8 @@
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <openspace/util/transformationmanager.h>
|
||||
#include <modules/iswa/rendering/iswagroup.h>
|
||||
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "IswaCygnet";
|
||||
@@ -38,8 +40,6 @@ IswaCygnet::IswaCygnet(const ghoul::Dictionary& dictionary)
|
||||
, _delete("delete", "Delete")
|
||||
,_alpha("alpha", "Alpha", 0.9f, 0.0f, 1.0f)
|
||||
, _shader(nullptr)
|
||||
,_type(IswaManager::CygnetType::NoType)
|
||||
,_groupEvent()
|
||||
,_group(nullptr)
|
||||
,_textureDirty(false)
|
||||
{
|
||||
@@ -121,9 +121,7 @@ bool IswaCygnet::initialize(){
|
||||
|
||||
bool IswaCygnet::deinitialize(){
|
||||
if(!_data->groupName.empty())
|
||||
_groupEvent->unsubscribe(name());
|
||||
// IswaManager::ref().unregisterFromGroup(_data->groupName, this);
|
||||
|
||||
_group->groupEvent()->unsubscribe(name());
|
||||
|
||||
unregisterProperties();
|
||||
destroyGeometry();
|
||||
@@ -232,7 +230,6 @@ void IswaCygnet::initializeTime(){
|
||||
|
||||
bool IswaCygnet::createShader(){
|
||||
if (_shader == nullptr) {
|
||||
// Plane Program
|
||||
RenderEngine& renderEngine = OsEng.renderEngine();
|
||||
_shader = renderEngine.buildRenderProgram(_programName,
|
||||
_vsPath,
|
||||
@@ -244,21 +241,21 @@ bool IswaCygnet::createShader(){
|
||||
}
|
||||
|
||||
void IswaCygnet::initializeGroup(){
|
||||
_groupEvent = IswaManager::ref().groupEvent(_data->groupName, _type);
|
||||
_group = IswaManager::ref().registerToGroup(_data->groupName, _type);
|
||||
_group = IswaManager::ref().iswaGroup(_data->groupName);
|
||||
|
||||
//Subscribe to enable propert and delete
|
||||
_groupEvent->subscribe(name(), "enabledChanged", [&](const ghoul::Dictionary& dict){
|
||||
//Subscribe to enable and delete property
|
||||
auto groupEvent = _group->groupEvent();
|
||||
groupEvent->subscribe(name(), "enabledChanged", [&](const ghoul::Dictionary& dict){
|
||||
LDEBUG(name() + " Event enabledChanged");
|
||||
_enabled.setValue(dict.value<bool>("enabled"));
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "alphaChanged", [&](const ghoul::Dictionary& dict){
|
||||
groupEvent->subscribe(name(), "alphaChanged", [&](const ghoul::Dictionary& dict){
|
||||
LDEBUG(name() + " Event alphaChanged");
|
||||
_alpha.setValue(dict.value<float>("alpha"));
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "clearGroup", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "clearGroup", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event clearGroup");
|
||||
OsEng.scriptEngine().queueScript("openspace.removeSceneGraphNode('" + name() + "')");
|
||||
});
|
||||
|
||||
@@ -116,11 +116,8 @@ protected:
|
||||
std::vector<std::shared_ptr<TransferFunction>> _transferFunctions;
|
||||
std::future<DownloadManager::MemoryFile> _futureObject;
|
||||
|
||||
std::shared_ptr<ghoul::Event<ghoul::Dictionary> > _groupEvent;
|
||||
|
||||
std::shared_ptr<IswaGroup> _group;
|
||||
|
||||
IswaManager::CygnetType _type;
|
||||
bool _textureDirty;
|
||||
|
||||
std::string _vsPath;
|
||||
|
||||
@@ -27,6 +27,15 @@
|
||||
#include <fstream>
|
||||
#include <modules/iswa/ext/json/json.hpp>
|
||||
|
||||
#include <modules/iswa/util/dataprocessortext.h>
|
||||
#include <modules/iswa/util/dataprocessorjson.h>
|
||||
#include <modules/iswa/util/dataprocessorkameleon.h>
|
||||
|
||||
#include <modules/iswa/rendering/dataplane.h>
|
||||
#include <modules/iswa/rendering/datasphere.h>
|
||||
#include <modules/iswa/rendering/kameleonplane.h>
|
||||
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "IswaGroup";
|
||||
using json = nlohmann::json;
|
||||
@@ -34,8 +43,7 @@ namespace {
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
IswaGroup::IswaGroup(std::string name, IswaManager::CygnetType type)
|
||||
IswaGroup::IswaGroup(std::string name, std::string type)
|
||||
:_enabled("enabled", "Enabled", true)
|
||||
,_alpha("alpha", "Alpha", 0.9f, 0.0f, 1.0f)
|
||||
,_useLog("useLog","Use Logarithm", false)
|
||||
@@ -48,8 +56,8 @@ IswaGroup::IswaGroup(std::string name, IswaManager::CygnetType type)
|
||||
,_dataOptions("dataOptions", "Data Options")
|
||||
,_fieldlines("fieldlineSeedsIndexFile", "Fieldline Seedpoints")
|
||||
,_fieldlineIndexFile("")
|
||||
,_type(type)
|
||||
,_registered(false)
|
||||
,_type(type)
|
||||
{
|
||||
setName(name);
|
||||
|
||||
@@ -67,11 +75,7 @@ IswaGroup::IswaGroup(std::string name, IswaManager::CygnetType type)
|
||||
|
||||
addProperty(_delete);
|
||||
|
||||
_dataProcessor = std::make_shared<DataProcessor>(
|
||||
_useLog.value(),
|
||||
_useHistogram.value(),
|
||||
_normValues
|
||||
);
|
||||
createDataProcessor();
|
||||
_groupEvent = std::make_shared<ghoul::Event<ghoul::Dictionary> >();
|
||||
registerProperties();
|
||||
|
||||
@@ -82,9 +86,10 @@ IswaGroup::~IswaGroup(){}
|
||||
|
||||
|
||||
void IswaGroup::registerOptions(const std::vector<properties::SelectionProperty::Option>& options){
|
||||
if(!_registered){
|
||||
registerProperties(); }
|
||||
if(_type == IswaManager::CygnetType::Data){
|
||||
if(!_registered)
|
||||
registerProperties();
|
||||
if(_type == typeid(DataPlane).name() || _type == typeid(DataSphere).name() ||
|
||||
_type == typeid(KameleonPlane).name()){
|
||||
if(_dataOptions.options().empty()){
|
||||
for(auto option : options){
|
||||
_dataOptions.addOption({option.value, option.description});
|
||||
@@ -108,8 +113,7 @@ void IswaGroup::setFieldlineInfo(std::string fieldlineIndexFile, std::string kam
|
||||
}
|
||||
}
|
||||
|
||||
bool IswaGroup::isType(IswaManager::CygnetType type){
|
||||
if(_type == IswaManager::CygnetType::NoType) return true;
|
||||
bool IswaGroup::isType(std::string type){
|
||||
return (_type == type);
|
||||
}
|
||||
|
||||
@@ -128,14 +132,14 @@ void IswaGroup::registerProperties(){
|
||||
});
|
||||
|
||||
|
||||
if(_type == IswaManager::CygnetType::Data){
|
||||
if(_type == typeid(DataPlane).name() || _type == typeid(DataSphere).name() ||
|
||||
_type == typeid(KameleonPlane).name() ){
|
||||
OsEng.gui()._iswa.registerProperty(&_useLog);
|
||||
OsEng.gui()._iswa.registerProperty(&_useHistogram);
|
||||
OsEng.gui()._iswa.registerProperty(&_autoFilter);
|
||||
OsEng.gui()._iswa.registerProperty(&_normValues);
|
||||
OsEng.gui()._iswa.registerProperty(&_backgroundValues);
|
||||
OsEng.gui()._iswa.registerProperty(&_transferFunctionsFile);
|
||||
OsEng.gui()._iswa.registerProperty(&_fieldlines);
|
||||
OsEng.gui()._iswa.registerProperty(&_dataOptions);
|
||||
|
||||
_useLog.onChange([this]{
|
||||
@@ -183,6 +187,11 @@ void IswaGroup::registerProperties(){
|
||||
_groupEvent->publish("dataOptionsChanged", ghoul::Dictionary({{"dataOptions", std::make_shared<std::vector<int> >(_dataOptions.value())}}));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
if(_type == typeid(KameleonPlane).name()){
|
||||
OsEng.gui()._iswa.registerProperty(&_fieldlines);
|
||||
|
||||
_fieldlines.onChange([this]{
|
||||
updateFieldlineSeeds();
|
||||
// LDEBUG("Group " + name() + " published fieldlinesChanged");
|
||||
@@ -279,4 +288,14 @@ void IswaGroup::clearFieldlines(){
|
||||
}
|
||||
}
|
||||
|
||||
void IswaGroup::createDataProcessor(){
|
||||
if(_type == typeid(DataPlane).name()){
|
||||
_dataProcessor = std::make_shared<DataProcessorText>();
|
||||
}else if(_type == typeid(DataSphere).name()){
|
||||
_dataProcessor = std::make_shared<DataProcessorJson>();
|
||||
}else if(_type == typeid(KameleonPlane).name()){
|
||||
_dataProcessor = std::make_shared<DataProcessorKameleon>();
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace openspace
|
||||
@@ -43,28 +43,24 @@ class IswaCygnet;
|
||||
class IswaGroup : public properties::PropertyOwner{
|
||||
public:
|
||||
IswaGroup(std::string name, IswaManager::CygnetType type);
|
||||
IswaGroup(std::string name, std::string type);
|
||||
~IswaGroup();
|
||||
//void registerCygnet(IswaCygnet* cygnet, IswaManager::CygnetType type);
|
||||
//void unregisterCygnet(IswaCygnet* cygnet);
|
||||
void registerOptions(const std::vector<properties::SelectionProperty::Option>& options);
|
||||
void registerFieldLineOptions(const std::vector<properties::SelectionProperty::Option>& options);
|
||||
bool isType(IswaManager::CygnetType type);
|
||||
bool isType(std::string type);
|
||||
|
||||
void clearGroup();
|
||||
void updateGroup();
|
||||
|
||||
std::shared_ptr<ghoul::Event<ghoul::Dictionary> > groupEvent(){ return _groupEvent; };
|
||||
std::shared_ptr<DataProcessor> dataProcessor();
|
||||
std::shared_ptr<ghoul::Event<ghoul::Dictionary> > groupEvent(){ return _groupEvent; };
|
||||
std::vector<int> fieldlineValue() {return _fieldlines.value();}
|
||||
std::vector<int> dataOptionsValue() {return _dataOptions.value();}
|
||||
void setFieldlineInfo(std::string fieldlineIndexFile, std::string kameleonPath);
|
||||
// bool useLog(){return _useLog.value();};
|
||||
// glm::vec2 normValues(){return _normValues.value();};
|
||||
// bool useHistogram(){return _useHistogram.value();};
|
||||
// std::vector<int> dataOptions(){return _dataOptions.value();};
|
||||
// std::string transferFunctionsFile(){return _transferFunctionsFile.value();};
|
||||
// glm::vec2 backgroundValues(){return _backgroundValues.value();};
|
||||
|
||||
private:
|
||||
void createDataProcessor();
|
||||
|
||||
void registerProperties();
|
||||
void unregisterProperties();
|
||||
|
||||
@@ -83,25 +79,17 @@ private:
|
||||
properties::SelectionProperty _dataOptions;
|
||||
properties::SelectionProperty _fieldlines;
|
||||
properties::TriggerProperty _delete;
|
||||
// properties::SelectionProperty _dataOptions;
|
||||
// properties::StringProperty _transferFunctionsFile;
|
||||
// properties::Vec2Property _normValues;
|
||||
// properties::Vec2Property _backgroundValues;
|
||||
// properties::BoolProperty _useLog;
|
||||
// properties::BoolProperty _useHistogram;;
|
||||
|
||||
// int groupId;
|
||||
// IswaCygnet cygnet;
|
||||
int _id;
|
||||
std::shared_ptr<ghoul::Event<ghoul::Dictionary> > _groupEvent;
|
||||
std::shared_ptr<DataProcessor> _dataProcessor;
|
||||
//std::vector<IswaCygnet* > _cygnets;
|
||||
IswaManager::CygnetType _type;
|
||||
|
||||
bool _registered;
|
||||
|
||||
std::string _fieldlineIndexFile;
|
||||
std::string _kameleonPath;
|
||||
std::map<int, std::tuple<std::string, std::string, bool> > _fieldlineState;
|
||||
std::string _type;
|
||||
};
|
||||
|
||||
} //namespace openspace
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <fstream>
|
||||
#include <modules/iswa/ext/json/json.hpp>
|
||||
#include <modules/iswa/rendering/iswagroup.h>
|
||||
#include <modules/iswa/util/dataprocessorkameleon.h>
|
||||
|
||||
|
||||
namespace {
|
||||
@@ -59,7 +60,7 @@ KameleonPlane::KameleonPlane(const ghoul::Dictionary& dictionary)
|
||||
,_transferFunctionsFile("transferfunctions", "Transfer Functions", "${SCENE}/iswa/tfs/hot.tf")
|
||||
,_dataOptions("dataOptions", "Data Options")
|
||||
,_fieldlines("fieldlineSeedsIndexFile", "Fieldline Seedpoints")
|
||||
,_resolution("resolution", "Resolutionx100", 1, 1, 5)
|
||||
,_resolution("resolution", "Resolutionx100", 3, 1, 5)
|
||||
,_slice("slice", "Slice", 0.0, 0.0, 1.0)
|
||||
{
|
||||
|
||||
@@ -76,9 +77,6 @@ KameleonPlane::KameleonPlane(const ghoul::Dictionary& dictionary)
|
||||
addProperty(_dataOptions);
|
||||
addProperty(_fieldlines);
|
||||
|
||||
|
||||
_type = IswaManager::CygnetType::Data;
|
||||
|
||||
dictionary.getValue("kwPath", _kwPath);
|
||||
|
||||
std::string fieldlineIndexFile;
|
||||
@@ -119,11 +117,11 @@ KameleonPlane::~KameleonPlane(){}
|
||||
bool KameleonPlane::deinitialize(){
|
||||
IswaCygnet::deinitialize();
|
||||
_fieldlines.set(std::vector<int>());
|
||||
_kw = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KameleonPlane::initialize(){
|
||||
_kw = std::make_shared<KameleonWrapper>(absPath(_kwPath));
|
||||
// _kw = std::make_shared<KameleonWrapper>(absPath(_kwPath));
|
||||
_textures.push_back(nullptr);
|
||||
|
||||
if(!_data->groupName.empty()){
|
||||
@@ -138,13 +136,14 @@ bool KameleonPlane::initialize(){
|
||||
|
||||
if(_group){
|
||||
_dataProcessor = _group->dataProcessor();
|
||||
auto groupEvent = _group->groupEvent();
|
||||
|
||||
_groupEvent->subscribe(name(), "useLogChanged", [&](const ghoul::Dictionary& dict){
|
||||
groupEvent->subscribe(name(), "useLogChanged", [&](const ghoul::Dictionary& dict){
|
||||
LDEBUG(name() + " Event useLogChanged");
|
||||
_useLog.setValue(dict.value<bool>("useLog"));
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "normValuesChanged", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "normValuesChanged", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event normValuesChanged");
|
||||
std::shared_ptr<glm::vec2> values;
|
||||
bool success = dict.getValue("normValues", values);
|
||||
@@ -153,12 +152,12 @@ bool KameleonPlane::initialize(){
|
||||
}
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "useHistogramChanged", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "useHistogramChanged", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event useHistogramChanged");
|
||||
_useHistogram.setValue(dict.value<bool>("useHistogram"));
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "dataOptionsChanged", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "dataOptionsChanged", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event dataOptionsChanged");
|
||||
std::shared_ptr<std::vector<int> > values;
|
||||
bool success = dict.getValue("dataOptions", values);
|
||||
@@ -167,12 +166,12 @@ bool KameleonPlane::initialize(){
|
||||
}
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "transferFunctionsChanged", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "transferFunctionsChanged", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event transferFunctionsChanged");
|
||||
_transferFunctionsFile.setValue(dict.value<std::string>("transferFunctions"));
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "backgroundValuesChanged", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "backgroundValuesChanged", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event backgroundValuesChanged");
|
||||
std::shared_ptr<glm::vec2> values;
|
||||
bool success = dict.getValue("backgroundValues", values);
|
||||
@@ -181,12 +180,12 @@ bool KameleonPlane::initialize(){
|
||||
}
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "autoFilterChanged", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "autoFilterChanged", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event autoFilterChanged");
|
||||
_autoFilter.setValue(dict.value<bool>("autoFilter"));
|
||||
});
|
||||
|
||||
_groupEvent->subscribe(name(), "updateGroup", [&](ghoul::Dictionary dict){
|
||||
groupEvent->subscribe(name(), "updateGroup", [&](ghoul::Dictionary dict){
|
||||
LDEBUG(name() + " Event updateGroup");
|
||||
loadTexture();
|
||||
});
|
||||
@@ -201,11 +200,7 @@ bool KameleonPlane::initialize(){
|
||||
OsEng.gui()._iswa.registerProperty(&_fieldlines);
|
||||
OsEng.gui()._iswa.registerProperty(&_dataOptions);
|
||||
|
||||
_dataProcessor = std::make_shared<DataProcessor>(
|
||||
_useLog.value(),
|
||||
_useHistogram.value(),
|
||||
_normValues
|
||||
);
|
||||
_dataProcessor = std::make_shared<DataProcessorKameleon>();
|
||||
}
|
||||
|
||||
setTransferFunctions(_transferFunctionsFile.value());
|
||||
@@ -245,31 +240,39 @@ bool KameleonPlane::initialize(){
|
||||
updateFieldlineSeeds();
|
||||
});
|
||||
|
||||
_dimensions = glm::size3_t(_resolution.value()*100);
|
||||
if(_data->scale.x == 0){
|
||||
_dimensions.x = 1;
|
||||
_dimensions.z = (int) _dimensions.y * (_data->scale.y/_data->scale.z);
|
||||
_textureDimensions = glm::size3_t(_dimensions.y, _dimensions.z, 1);
|
||||
|
||||
_data->offset.x = _data->gridMin.x+_slice.value()*_scale;
|
||||
|
||||
}else if(_data->scale.y == 0){
|
||||
_dimensions.y = 1;
|
||||
_dimensions.z = (int) _dimensions.x * (_data->scale.x/_data->scale.z);
|
||||
_textureDimensions = glm::size3_t(_dimensions.x, _dimensions.z, 1);
|
||||
|
||||
_data->offset.y = _data->gridMin.y+_slice.value()*_scale;
|
||||
}else{
|
||||
_dimensions.z = 1;
|
||||
_dimensions.y = (int) _dimensions.x * (_data->scale.x/_data->scale.y);
|
||||
_textureDimensions = glm::size3_t(_dimensions.x, _dimensions.y, 1);
|
||||
|
||||
_data->offset.z = _data->gridMin.z+_slice.value()*_scale;
|
||||
}
|
||||
|
||||
fillOptions();
|
||||
std::dynamic_pointer_cast<DataProcessorKameleon>(_dataProcessor)->dimensions(_dimensions);
|
||||
_dataProcessor->addDataValues(_kwPath, _dataOptions);
|
||||
|
||||
updateTexture();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KameleonPlane::loadTexture() {
|
||||
std::vector<int> selectedOptions = _dataOptions.value();
|
||||
auto options = _dataOptions.options();
|
||||
|
||||
for(int option : selectedOptions){
|
||||
if(!_dataSlices[option]){
|
||||
|
||||
std::string optionName = options[option].description;
|
||||
_dataSlices[option] = _kw->getUniformSliceValues(optionName, _dimensions, _slice.value());
|
||||
if(!_textures[option]){
|
||||
_dataProcessor->addValuesFromKameleonData(_dataSlices[option], _dimensions, options.size(), option);
|
||||
|
||||
if(_group)
|
||||
_group->updateGroup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<float*> data = _dataProcessor->processKameleonData2(_dataSlices, _dimensions, _dataOptions);
|
||||
std::vector<float*> data = std::dynamic_pointer_cast<DataProcessorKameleon> (_dataProcessor)->processData(_kwPath, _dataOptions, _slice);
|
||||
|
||||
if(data.empty())
|
||||
return false;
|
||||
@@ -278,6 +281,8 @@ bool KameleonPlane::loadTexture() {
|
||||
_backgroundValues.setValue(_dataProcessor->filterValues());
|
||||
|
||||
bool texturesReady = false;
|
||||
std::vector<int> selectedOptions = _dataOptions.value();
|
||||
|
||||
for(int option: selectedOptions){
|
||||
float* values = data[option];
|
||||
if(!values) continue;
|
||||
@@ -309,35 +314,22 @@ bool KameleonPlane::loadTexture() {
|
||||
}
|
||||
|
||||
bool KameleonPlane::updateTexture(){
|
||||
_dimensions = glm::size3_t(_resolution.value()*100);
|
||||
|
||||
if(_data->scale.x == 0){
|
||||
_dimensions.x = 1;
|
||||
_dimensions.z = (int) _dimensions.y * (_data->scale.y/_data->scale.z);
|
||||
_textureDimensions = glm::size3_t(_dimensions.y, _dimensions.z, 1);
|
||||
|
||||
_data->offset.x = _data->gridMin.x+_slice.value()*_scale;
|
||||
|
||||
}else if(_data->scale.y == 0){
|
||||
_dimensions.y = 1;
|
||||
_dimensions.z = (int) _dimensions.x * (_data->scale.x/_data->scale.z);
|
||||
_textureDimensions = glm::size3_t(_dimensions.x, _dimensions.z, 1);
|
||||
|
||||
_data->offset.y = _data->gridMin.y+_slice.value()*_scale;
|
||||
}else{
|
||||
_dimensions.z = 1;
|
||||
_dimensions.y = (int) _dimensions.x * (_data->scale.x/_data->scale.y);
|
||||
_textureDimensions = glm::size3_t(_dimensions.x, _dimensions.y, 1);
|
||||
|
||||
_data->offset.z = _data->gridMin.z+_slice.value()*_scale;
|
||||
}
|
||||
|
||||
for(int i=0; i<_dataSlices.size(); ++i){
|
||||
float* slice = _dataSlices[i];
|
||||
if(slice){
|
||||
_dataSlices[i] = nullptr;
|
||||
delete slice;
|
||||
}
|
||||
}
|
||||
// for(int i=0; i<_dataSlices.size(); ++i){
|
||||
// float* slice = _dataSlices[i];
|
||||
// if(slice){
|
||||
// _dataSlices[i] = nullptr;
|
||||
// delete slice;
|
||||
// }
|
||||
// }
|
||||
|
||||
_textureDirty = true;
|
||||
|
||||
@@ -431,7 +423,8 @@ void KameleonPlane::setTransferFunctions(std::string tfPath){
|
||||
}
|
||||
|
||||
void KameleonPlane::fillOptions(){
|
||||
std::vector<std::string> options = _kw->getVariables();
|
||||
std::cout << "Time to fill options" << std::endl;
|
||||
std::vector<std::string> options = _dataProcessor->readMetadata(_kwPath);
|
||||
int numOptions = 0;
|
||||
|
||||
for(std::string option : options){
|
||||
|
||||
@@ -36,7 +36,6 @@ TextureCygnet::TextureCygnet(const ghoul::Dictionary& dictionary)
|
||||
:IswaCygnet(dictionary)
|
||||
{
|
||||
registerProperties();
|
||||
_type = IswaManager::CygnetType::Texture;
|
||||
}
|
||||
|
||||
TextureCygnet::~TextureCygnet(){}
|
||||
|
||||
@@ -43,12 +43,20 @@ namespace {
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
DataProcessor::DataProcessor()
|
||||
:_useLog(false)
|
||||
,_useHistogram(false)
|
||||
,_normValues(glm::vec2(1.0))
|
||||
,_filterValues(glm::vec2(0.0))
|
||||
{
|
||||
_coordinateVariables = {"x", "y", "z", "phi", "theta"};
|
||||
}
|
||||
|
||||
DataProcessor::DataProcessor(bool useLog, bool useHistogram, glm::vec2 normValues)
|
||||
:_useLog(useLog)
|
||||
,_useHistogram(useHistogram)
|
||||
,_normValues(normValues)
|
||||
,_filterValues(glm::vec2(0))
|
||||
,_numValues(0)
|
||||
{
|
||||
_coordinateVariables = {"x", "y", "z", "phi", "theta"};
|
||||
};
|
||||
@@ -122,7 +130,7 @@ void DataProcessor::addValues(std::string& dataBuffer, properties::SelectionProp
|
||||
if(_min.empty()) _min = std::vector<float>(numOptions, std::numeric_limits<float>::max());
|
||||
if(_max.empty()) _max = std::vector<float>(numOptions, std::numeric_limits<float>::min());
|
||||
if(_sum.empty()) _sum = std::vector<float>(numOptions, 0.0f);
|
||||
if(_sd.empty()) _sd = std::vector<float>(numOptions, 0.0f);
|
||||
if(_standardDeviation.empty()) _standardDeviation = std::vector<float>(numOptions, 0.0f);
|
||||
if(_numValues.empty()) _numValues= std::vector<float>(numOptions, 0.0f);
|
||||
if(_histograms.empty())_histograms = std::vector<std::shared_ptr<Histogram>>(numOptions, nullptr);
|
||||
|
||||
@@ -139,6 +147,8 @@ void DataProcessor::addValues(std::string& dataBuffer, properties::SelectionProp
|
||||
|
||||
std::stringstream ss(line);
|
||||
std::vector<float> value;
|
||||
|
||||
|
||||
float v;
|
||||
while(ss >> v){
|
||||
value.push_back(v);
|
||||
@@ -174,7 +184,7 @@ void DataProcessor::addValues(std::string& dataBuffer, properties::SelectionProp
|
||||
float sd = sqrt(var / numValues);
|
||||
|
||||
_sum[i] += sum[i];
|
||||
_sd[i] = sqrt(pow(_sd[i],2) + pow(sd, 2));
|
||||
_standardDeviation[i] = sqrt(pow(_standardDeviation[i],2) + pow(sd, 2));
|
||||
_numValues[i] += numValues;
|
||||
_histograms[i]->generateEqualizer();
|
||||
}
|
||||
@@ -321,7 +331,7 @@ std::vector<float*> DataProcessor::readData2(std::string& dataBuffer, properties
|
||||
for(int option : selectedOptions){
|
||||
std::shared_ptr<Histogram> histogram = _histograms[option];
|
||||
float mean = (1.0 / _numValues[option]) * _sum[option];
|
||||
float sd = _sd[option];
|
||||
float sd = _standardDeviation[option];
|
||||
|
||||
float filterMid = histogram->highestBinValue(_useHistogram);
|
||||
float filterWidth = mean+histogram->binWidth();
|
||||
@@ -419,7 +429,7 @@ void DataProcessor::addValuesFromJSON(std::string& dataBuffer, properties::Selec
|
||||
if(_min.empty()) _min = std::vector<float>(numOptions, std::numeric_limits<float>::max());
|
||||
if(_max.empty()) _max = std::vector<float>(numOptions, std::numeric_limits<float>::min());
|
||||
if(_sum.empty()) _sum = std::vector<float>(numOptions, 0.0f);
|
||||
if(_sd.empty()) _sd = std::vector<float>(numOptions, 0.0f);
|
||||
if(_standardDeviation.empty()) _standardDeviation = std::vector<float>(numOptions, 0.0f);
|
||||
if(_numValues.empty()) _numValues= std::vector<float>(numOptions, 0.0f);
|
||||
if(_histograms.empty())_histograms = std::vector<std::shared_ptr<Histogram>>(numOptions, nullptr);
|
||||
|
||||
@@ -476,7 +486,7 @@ void DataProcessor::addValuesFromJSON(std::string& dataBuffer, properties::Selec
|
||||
// // // float sd = sqrt(var / numValues);
|
||||
|
||||
// // // _sum[i] += sum[i];
|
||||
// // // _sd[i] = sqrt(pow(_sd[i],2) + pow(sd, 2));
|
||||
// // // _standardDeviation[i] = sqrt(pow(_standardDeviation[i],2) + pow(sd, 2));
|
||||
// // // _numValues[i] += numValues;
|
||||
// // // _histograms[i]->generateEqualizer();
|
||||
// // // }
|
||||
@@ -500,7 +510,7 @@ void DataProcessor::addValuesFromJSON(std::string& dataBuffer, properties::Selec
|
||||
float sd = sqrt(var / numValues);
|
||||
|
||||
_sum[i] += sum[i];
|
||||
_sd[i] = sqrt(pow(_sd[i],2) + pow(sd, 2));
|
||||
_standardDeviation[i] = sqrt(pow(_standardDeviation[i],2) + pow(sd, 2));
|
||||
_numValues[i] += numValues;
|
||||
_histograms[i]->generateEqualizer();
|
||||
}
|
||||
@@ -548,7 +558,7 @@ std::vector<float*> DataProcessor::readJSONData2(std::string& dataBuffer, proper
|
||||
|
||||
if(!_histograms.empty()){
|
||||
float mean = (1.0 / _numValues[option]) * _sum[option];
|
||||
float sd = _sd[option];
|
||||
float sd = _standardDeviation[option];
|
||||
|
||||
std::shared_ptr<Histogram> histogram = _histograms[option];
|
||||
float filterMid = histogram->highestBinValue(_useHistogram);
|
||||
@@ -586,7 +596,7 @@ void DataProcessor::addValuesFromKameleonData(float* kdata, glm::size3_t dimensi
|
||||
if(_min.empty()) _min = std::vector<float>(numOptions, std::numeric_limits<float>::max());
|
||||
if(_max.empty()) _max = std::vector<float>(numOptions, std::numeric_limits<float>::min());
|
||||
if(_sum.empty()) _sum= std::vector<float>(numOptions, 0.0f);
|
||||
if(_sd.empty()) _sd= std::vector<float>(numOptions, 0.0f);
|
||||
if(_standardDeviation.empty()) _standardDeviation= std::vector<float>(numOptions, 0.0f);
|
||||
if(_numValues.empty()) _numValues= std::vector<float>(numOptions, 0.0f);
|
||||
if(_histograms.empty())_histograms = std::vector<std::shared_ptr<Histogram>>(numOptions, nullptr);
|
||||
|
||||
@@ -619,7 +629,7 @@ void DataProcessor::addValuesFromKameleonData(float* kdata, glm::size3_t dimensi
|
||||
float sd = sqrt(var / numValues);
|
||||
|
||||
_sum[i] += sum;
|
||||
_sd[i] = sqrt(pow(_sd[i],2) + pow(sd, 2));
|
||||
_standardDeviation[i] = sqrt(pow(_standardDeviation[i],2) + pow(sd, 2));
|
||||
_numValues[i] += numValues;
|
||||
_histograms[i]->generateEqualizer();
|
||||
}
|
||||
@@ -638,7 +648,7 @@ std::vector<float*> DataProcessor::processKameleonData2(std::vector<float*> kdat
|
||||
data[option] = new float[numValues]{0.0f};
|
||||
|
||||
float mean = (1.0 / _numValues[option]) * _sum[option];
|
||||
float sd = _sd[option];
|
||||
float sd = _standardDeviation[option];
|
||||
|
||||
for(int i=0; i<numValues; i++){
|
||||
float v = kdata[option][i];
|
||||
@@ -687,8 +697,8 @@ std::vector<float*> DataProcessor::processKameleonData(std::vector<float*> kdata
|
||||
_sum= std::vector<float>(numOptions, 0.0f);
|
||||
}
|
||||
|
||||
if(_sd.empty()){
|
||||
_sd= std::vector<float>(numOptions, 0.0f);
|
||||
if(_standardDeviation.empty()){
|
||||
_standardDeviation= std::vector<float>(numOptions, 0.0f);
|
||||
}
|
||||
|
||||
if(_histograms.empty()){
|
||||
@@ -801,7 +811,7 @@ float DataProcessor::processDataPoint(float value, int option){
|
||||
if(_numValues.empty()) return 0.0f;
|
||||
std::shared_ptr<Histogram> histogram = _histograms[option];
|
||||
float mean = (1.0 / _numValues[option]) * _sum[option];
|
||||
float sd = _sd[option];
|
||||
float sd = _standardDeviation[option];
|
||||
|
||||
if(_useHistogram){
|
||||
// std::cout << sd << " " <<
|
||||
@@ -835,9 +845,86 @@ void DataProcessor::clear(){
|
||||
_min.clear();
|
||||
_max.clear();
|
||||
_sum.clear();
|
||||
_sd.clear();
|
||||
_standardDeviation.clear();
|
||||
_histograms.clear();
|
||||
_numValues.clear();
|
||||
}
|
||||
|
||||
void DataProcessor::initializeVectors(int numOptions){
|
||||
if(_min.empty()) _min = std::vector<float>(numOptions, std::numeric_limits<float>::max());
|
||||
if(_max.empty()) _max = std::vector<float>(numOptions, std::numeric_limits<float>::min());
|
||||
if(_sum.empty()) _sum = std::vector<float>(numOptions, 0.0f);
|
||||
if(_standardDeviation.empty()) _standardDeviation = std::vector<float>(numOptions, 0.0f);
|
||||
if(_numValues.empty()) _numValues = std::vector<float>(numOptions, 0.0f);
|
||||
if(_histograms.empty())_histograms = std::vector<std::shared_ptr<Histogram>>(numOptions, nullptr);
|
||||
}
|
||||
|
||||
void DataProcessor::calculateFilterValues(std::vector<int> selectedOptions){
|
||||
int numSelected = selectedOptions.size();
|
||||
std::shared_ptr<Histogram> histogram;
|
||||
float mean, standardDeviation, filterMid, filterWidth;
|
||||
|
||||
_filterValues = glm::vec2(0.0);
|
||||
if(numSelected <= 0) return;
|
||||
|
||||
|
||||
if(!_histograms.empty()){
|
||||
for(int option : selectedOptions){
|
||||
histogram = _histograms[option];
|
||||
mean = (1.0/_numValues[option])*_sum[option];
|
||||
standardDeviation = _standardDeviation[option];
|
||||
|
||||
filterMid = histogram->highestBinValue(_useHistogram);
|
||||
filterWidth = mean+histogram->binWidth();
|
||||
|
||||
if(_useHistogram){
|
||||
standardDeviation = histogram->equalize(standardDeviation);
|
||||
mean = histogram->equalize(mean);
|
||||
filterWidth = mean+1;
|
||||
}
|
||||
|
||||
filterMid = normalizeWithStandardScore(filterMid, mean, standardDeviation);
|
||||
filterWidth = fabs(0.5-normalizeWithStandardScore(filterWidth, mean, standardDeviation));
|
||||
_filterValues += glm::vec2(filterMid, filterWidth);
|
||||
|
||||
}
|
||||
_filterValues /= numSelected;
|
||||
}
|
||||
}
|
||||
|
||||
void DataProcessor::add(std::vector<std::vector<float>>& optionValues, std::vector<float>& sum){
|
||||
int numOptions = optionValues.size();
|
||||
int numValues;
|
||||
float mean, value, variance, standardDeviation;
|
||||
|
||||
for(int i=0; i<numOptions; i++){
|
||||
if(!_histograms[i]){
|
||||
_histograms[i] = std::make_shared<Histogram>(_min[i], _max[i], 512);
|
||||
}
|
||||
else{
|
||||
_histograms[i]->changeRange(_min[i], _max[i]);
|
||||
}
|
||||
|
||||
std::vector<float> values = optionValues[i];
|
||||
numValues = values.size();
|
||||
|
||||
variance = 0;
|
||||
mean = (1.0f/numValues)*sum[i];
|
||||
|
||||
for(int j=0; j<numValues; j++){
|
||||
value = values[j];
|
||||
variance += pow(value-mean, 2);
|
||||
_histograms[i]->add(value, 1);
|
||||
}
|
||||
|
||||
standardDeviation = sqrt(variance/ numValues);
|
||||
|
||||
_sum[i] += sum[i];
|
||||
_standardDeviation[i] = sqrt(pow(standardDeviation, 2) + pow(_standardDeviation[i], 2));
|
||||
_numValues[i] += numValues;
|
||||
|
||||
_histograms[i]->generateEqualizer();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -37,6 +37,7 @@ namespace openspace{
|
||||
class DataProcessor{
|
||||
friend class IswaGroup;
|
||||
public:
|
||||
DataProcessor();
|
||||
DataProcessor(bool useLog, bool useHistogram, glm::vec2 normValues);
|
||||
~DataProcessor();
|
||||
|
||||
@@ -73,7 +74,11 @@ public:
|
||||
void clear();
|
||||
|
||||
glm::vec2 filterValues();
|
||||
private:
|
||||
|
||||
virtual std::vector<std::string> readMetadata(std::string data){};
|
||||
virtual void addDataValues(std::string data, properties::SelectionProperty& dataOptions){};
|
||||
virtual std::vector<float*> processData(std::string data, properties::SelectionProperty& dataOptions){};
|
||||
protected:
|
||||
void processData(
|
||||
float* outputData, // Where you want your processed data to go
|
||||
std::vector<float>& inputData, //data that needs processing
|
||||
@@ -84,9 +89,12 @@ private:
|
||||
);
|
||||
|
||||
float processDataPoint(float value, int option);
|
||||
|
||||
float normalizeWithStandardScore(float value, float mean, float sd);
|
||||
|
||||
void initializeVectors(int numOptions);
|
||||
void calculateFilterValues(std::vector<int> selectedOptions);
|
||||
void add(std::vector<std::vector<float>>& optionValues, std::vector<float>& sum);
|
||||
|
||||
glm::size3_t _dimensions;
|
||||
bool _useLog;
|
||||
bool _useHistogram;
|
||||
@@ -96,7 +104,7 @@ private:
|
||||
std::vector<float> _min;
|
||||
std::vector<float> _max;
|
||||
std::vector<float> _sum;
|
||||
std::vector<float> _sd;
|
||||
std::vector<float> _standardDeviation;
|
||||
std::vector<float> _numValues;
|
||||
std::vector<std::shared_ptr<Histogram>> _histograms;
|
||||
// int _numValues;
|
||||
|
||||
142
modules/iswa/util/dataprocessorjson.cpp
Normal file
142
modules/iswa/util/dataprocessorjson.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2015 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
#include <modules/iswa/util/dataprocessorjson.h>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <modules/iswa/ext/json/json.hpp>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "DataProcessorJson";
|
||||
using json = nlohmann::json;
|
||||
}
|
||||
|
||||
namespace openspace{
|
||||
|
||||
DataProcessorJson::DataProcessorJson()
|
||||
:DataProcessor()
|
||||
{}
|
||||
|
||||
DataProcessorJson::~DataProcessorJson(){}
|
||||
|
||||
std::vector<std::string> DataProcessorJson::readMetadata(std::string data){
|
||||
std::vector<std::string> options = std::vector<std::string>();
|
||||
if(!data.empty()){
|
||||
json j = json::parse(data);
|
||||
json variables = j["variables"];
|
||||
|
||||
for(json::iterator it = variables.begin(); it != variables.end(); ++it){
|
||||
std::string option = it.key();
|
||||
if(option == "x"){
|
||||
json row = it.value();
|
||||
json col = row.at(0);
|
||||
|
||||
_dimensions = glm::size3_t(col.size(), row.size(), 1);
|
||||
}
|
||||
|
||||
if(_coordinateVariables.find(option) == _coordinateVariables.end()){
|
||||
options.push_back(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
void DataProcessorJson::addDataValues(std::string data, properties::SelectionProperty& dataOptions){
|
||||
int numOptions = dataOptions.options().size();
|
||||
initializeVectors(numOptions);
|
||||
|
||||
if(!data.empty()){
|
||||
json j = json::parse(data);
|
||||
json variables = j["variables"];
|
||||
|
||||
std::vector<float> sum(numOptions, 0.0f);
|
||||
std::vector<std::vector<float>> optionValues(numOptions, std::vector<float>());
|
||||
auto options = dataOptions.options();
|
||||
|
||||
float value;
|
||||
|
||||
for(int i=0; i<numOptions; i++){
|
||||
json row = variables[options[i].description];
|
||||
int rowsize = row.size();
|
||||
|
||||
for(int y=0; y<row.size(); y++){
|
||||
json col = row.at(y);
|
||||
int colsize = col.size();
|
||||
|
||||
for(int x=0; x<colsize; x++){
|
||||
value = col.at(x);
|
||||
|
||||
optionValues[i].push_back(value);
|
||||
_min[i] = std::min(_min[i], value);
|
||||
_max[i] = std::max(_max[i], value);
|
||||
sum[i] += value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
add(optionValues, sum);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<float*> DataProcessorJson::processData(std::string data, properties::SelectionProperty& dataOptions){
|
||||
if(!data.empty()){
|
||||
json j = json::parse(data);
|
||||
json variables = j["variables"];
|
||||
|
||||
std::vector<int> selectedOptions = dataOptions.value();
|
||||
int numSelected = selectedOptions.size();
|
||||
|
||||
auto options = dataOptions.options();
|
||||
int numOptions = options.size();
|
||||
|
||||
float value;
|
||||
int rowsize, colsize, i;
|
||||
|
||||
std::vector<float*> dataOptions(numOptions, nullptr);
|
||||
for(int option : selectedOptions){
|
||||
dataOptions[option] = new float[_dimensions.x*_dimensions.y]{0.0f};
|
||||
|
||||
json row = variables[options[option].description];
|
||||
rowsize = row.size();
|
||||
|
||||
for(int y=0; y<rowsize; y++){
|
||||
json col = row.at(y);
|
||||
colsize = col.size();
|
||||
|
||||
for(int x=0; x<colsize; x++){
|
||||
value = col.at(x);
|
||||
i = x+y*colsize;
|
||||
|
||||
dataOptions[option][i] = processDataPoint(value, option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
calculateFilterValues(selectedOptions);
|
||||
return dataOptions;
|
||||
}
|
||||
return std::vector<float*>();
|
||||
}
|
||||
|
||||
}//namespace openspace
|
||||
42
modules/iswa/util/dataprocessorjson.h
Normal file
42
modules/iswa/util/dataprocessorjson.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2015 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
#include <modules/iswa/util/dataprocessor.h>
|
||||
|
||||
#ifndef __DATAPROCESSORJSON_H__
|
||||
#define __DATAPROCESSORJSON_H__
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class DataProcessorJson : public DataProcessor {
|
||||
public:
|
||||
DataProcessorJson();
|
||||
~DataProcessorJson();
|
||||
|
||||
virtual std::vector<std::string> readMetadata(std::string data) override;
|
||||
virtual void addDataValues(std::string data, properties::SelectionProperty& dataOptions) override;
|
||||
virtual std::vector<float*> processData(std::string data, properties::SelectionProperty& dataOptions) override;
|
||||
};
|
||||
|
||||
}// namespace
|
||||
#endif __DATAPROCESSORJSON_H__
|
||||
143
modules/iswa/util/dataprocessorkameleon.cpp
Normal file
143
modules/iswa/util/dataprocessorkameleon.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2015 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
#include <modules/iswa/util/dataprocessorkameleon.h>
|
||||
#include <algorithm>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "DataProcessorKameleon";
|
||||
}
|
||||
|
||||
namespace openspace{
|
||||
|
||||
DataProcessorKameleon::DataProcessorKameleon()
|
||||
:DataProcessor()
|
||||
,_kwPath("")
|
||||
,_kw(nullptr)
|
||||
,_initialized(false)
|
||||
,_slice(0.5)
|
||||
{}
|
||||
|
||||
DataProcessorKameleon::~DataProcessorKameleon(){}
|
||||
|
||||
|
||||
std::vector<std::string> DataProcessorKameleon::readMetadata(std::string path){
|
||||
std::cout << "The path! " << path << std::endl;
|
||||
if(!path.empty()){
|
||||
std::cout << "not empty!";
|
||||
if(path != _kwPath || !_kw){
|
||||
std::cout << "tmie to create!";
|
||||
|
||||
initializeKameleonWrapper(path);
|
||||
}
|
||||
|
||||
std::cout << "return variables!";
|
||||
return _kw->getVariables();
|
||||
}
|
||||
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
void DataProcessorKameleon::addDataValues(std::string path, properties::SelectionProperty& dataOptions){
|
||||
int numOptions = dataOptions.options().size();
|
||||
initializeVectors(numOptions);
|
||||
|
||||
if(!path.empty()){
|
||||
if(path != _kwPath || !_kw)
|
||||
initializeKameleonWrapper(path);
|
||||
|
||||
std::vector<float> sum(numOptions, 0.0f);
|
||||
std::vector<std::vector<float>> optionValues(numOptions, std::vector<float>());
|
||||
auto options = dataOptions.options();
|
||||
|
||||
int numValues = _dimensions.x*_dimensions.y*_dimensions.z;
|
||||
|
||||
float* values;
|
||||
float value;
|
||||
|
||||
for(int i=0; i<numOptions; i++){
|
||||
values = _kw->getUniformSliceValues(options[i].description, _dimensions, 0.5f);
|
||||
|
||||
for(int j=0; j<numValues; j++){
|
||||
value = values[j];
|
||||
|
||||
optionValues[i].push_back(value);
|
||||
_min[i] = std::min(_min[i], value);
|
||||
_max[i] = std::max(_max[i], value);
|
||||
sum[i] += value;
|
||||
}
|
||||
}
|
||||
|
||||
add(optionValues, sum);
|
||||
}
|
||||
}
|
||||
std::vector<float*> DataProcessorKameleon::processData(std::string path, properties::SelectionProperty& dataOptions, float slice){
|
||||
_slice = slice;
|
||||
return processData(path, dataOptions);
|
||||
}
|
||||
|
||||
std::vector<float*> DataProcessorKameleon::processData(std::string path, properties::SelectionProperty& dataOptions){
|
||||
int numOptions = dataOptions.options().size();
|
||||
|
||||
if(!path.empty()){
|
||||
if(path != _kwPath || !_kw)
|
||||
initializeKameleonWrapper(path);
|
||||
|
||||
std::vector<int> selectedOptions = dataOptions.value();
|
||||
int numSelected = selectedOptions.size();
|
||||
|
||||
auto options = dataOptions.options();
|
||||
int numOptions = options.size();
|
||||
|
||||
int numValues = _dimensions.x*_dimensions.y*_dimensions.z;
|
||||
|
||||
float value;
|
||||
|
||||
std::vector<float*> dataOptions(numOptions, nullptr);
|
||||
for(int option : selectedOptions){
|
||||
dataOptions[option] = _kw->getUniformSliceValues(options[option].description, _dimensions, _slice);
|
||||
|
||||
for(int i=0; i<numValues; i++){
|
||||
value = dataOptions[option][i];
|
||||
dataOptions[option][i] = processDataPoint(value, option);
|
||||
}
|
||||
}
|
||||
|
||||
calculateFilterValues(selectedOptions);
|
||||
return dataOptions;
|
||||
}
|
||||
return std::vector<float*>(numOptions, nullptr);
|
||||
}
|
||||
|
||||
void DataProcessorKameleon::initializeKameleonWrapper(std::string path){
|
||||
const std::string& extension = ghoul::filesystem::File(absPath(path)).fileExtension();
|
||||
if(FileSys.fileExists(absPath(path)) && extension == "cdf"){
|
||||
if(_kw) _kw->close();
|
||||
|
||||
_kwPath = path;
|
||||
_kw = std::make_shared<KameleonWrapper>(absPath(_kwPath));
|
||||
}
|
||||
}
|
||||
|
||||
}//namespace openspace
|
||||
55
modules/iswa/util/dataprocessorkameleon.h
Normal file
55
modules/iswa/util/dataprocessorkameleon.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2015 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
#include <modules/iswa/util/dataprocessor.h>
|
||||
#include <modules/kameleon/include/kameleonwrapper.h>
|
||||
|
||||
#ifndef __DATAPROCESSORKAMELEON_H__
|
||||
#define __DATAPROCESSORKAMELEON_H__
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class DataProcessorKameleon : public DataProcessor {
|
||||
public:
|
||||
DataProcessorKameleon();
|
||||
~DataProcessorKameleon();
|
||||
|
||||
virtual std::vector<std::string> readMetadata(std::string path) override;
|
||||
virtual void addDataValues(std::string data, properties::SelectionProperty& dataOptions) override;
|
||||
virtual std::vector<float*> processData(std::string path, properties::SelectionProperty& dataOptions) override;
|
||||
virtual std::vector<float*> processData(std::string path, properties::SelectionProperty& dataOptions, float slize);
|
||||
void dimensions(glm::size3_t dimensions){_dimensions = dimensions;}
|
||||
|
||||
private:
|
||||
void initializeKameleonWrapper(std::string kwPath);
|
||||
|
||||
std::shared_ptr<KameleonWrapper> _kw;
|
||||
std::string _kwPath;
|
||||
std::vector<std::string> _loadedVariables;
|
||||
bool _initialized;
|
||||
float _slice;
|
||||
// std::vector<float*> _data;
|
||||
};
|
||||
|
||||
}// namespace
|
||||
#endif __DATAPROCESSORKAMELEON_H__
|
||||
163
modules/iswa/util/dataprocessortext.cpp
Normal file
163
modules/iswa/util/dataprocessortext.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2015 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
#include <modules/iswa/util/dataprocessortext.h>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "DataProcessorText";
|
||||
}
|
||||
|
||||
namespace openspace{
|
||||
|
||||
DataProcessorText::DataProcessorText()
|
||||
:DataProcessor()
|
||||
{}
|
||||
|
||||
DataProcessorText::~DataProcessorText(){}
|
||||
|
||||
std::vector<std::string> DataProcessorText::readMetadata(std::string data){
|
||||
//The intresting part of the file looks like this:
|
||||
//# Output data: field with 61x61=3721 elements
|
||||
//# x y z N V_x B_x
|
||||
|
||||
std::vector<std::string> options = std::vector<std::string>();
|
||||
std::string info = "# Output data: field with "; //The string where the interesting data begins
|
||||
if(!data.empty()){
|
||||
std::string line;
|
||||
std::stringstream memorystream(data);
|
||||
|
||||
while(getline(memorystream, line)){
|
||||
if(line.find(info) == 0){
|
||||
line = line.substr(info.size());
|
||||
std::stringstream ss(line);
|
||||
|
||||
std::string token;
|
||||
getline(ss, token, 'x');
|
||||
int x = std::stoi(token);
|
||||
|
||||
getline(ss, token, '=');
|
||||
int y = std::stoi(token);
|
||||
|
||||
_dimensions = glm::size3_t(x, y, 1);
|
||||
|
||||
getline(memorystream, line);
|
||||
line = line.substr(1); //because of the # char
|
||||
|
||||
ss = std::stringstream(line);
|
||||
std::string option;
|
||||
while(ss >> option){
|
||||
if(_coordinateVariables.find(option) == _coordinateVariables.end())
|
||||
options.push_back(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
void DataProcessorText::addDataValues(std::string data, properties::SelectionProperty& dataOptions){
|
||||
int numOptions = dataOptions.options().size();
|
||||
initializeVectors(numOptions);
|
||||
|
||||
if(!data.empty()){
|
||||
std::string line;
|
||||
std::stringstream memorystream(data);
|
||||
|
||||
std::vector<float> sum(numOptions, 0.0f); //for standard diviation in the add() function
|
||||
std::vector<std::vector<float>> optionValues(numOptions, std::vector<float>());
|
||||
|
||||
std::vector<float> values;
|
||||
float value;
|
||||
|
||||
while(getline(memorystream, line)){
|
||||
if(line.find("#") == 0) continue;
|
||||
|
||||
values = std::vector<float>();
|
||||
std::stringstream ss(line);
|
||||
copy(
|
||||
std::istream_iterator<float> (ss),
|
||||
std::istream_iterator<float> (),
|
||||
back_inserter(values)
|
||||
);
|
||||
|
||||
if(values.size() <= 0) continue;
|
||||
|
||||
for(int i=0; i<numOptions; i++){
|
||||
value = values[i+3];
|
||||
|
||||
optionValues[i].push_back(value);
|
||||
_min[i] = std::min(_min[i], value);
|
||||
_max[i] = std::max(_max[i], value);
|
||||
sum[i] += value;
|
||||
}
|
||||
}
|
||||
|
||||
add(optionValues, sum);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<float*> DataProcessorText::processData(std::string data, properties::SelectionProperty& dataOptions){
|
||||
if(!data.empty()){
|
||||
std::string line;
|
||||
std::stringstream memorystream(data);
|
||||
|
||||
std::vector<int> selectedOptions = dataOptions.value();
|
||||
int numSelected = selectedOptions.size();
|
||||
int numOptions = dataOptions.options().size();
|
||||
|
||||
std::vector<float> values;
|
||||
float value;
|
||||
|
||||
std::vector<float*> dataOptions(numOptions, nullptr);
|
||||
for(int option : selectedOptions){
|
||||
dataOptions[option] = new float[_dimensions.x*_dimensions.y]{0.0f};
|
||||
}
|
||||
|
||||
int numValues = 0;
|
||||
while(getline(memorystream, line)){
|
||||
if(line.find("#") == 0) continue;
|
||||
|
||||
values = std::vector<float>();
|
||||
std::stringstream ss(line);
|
||||
copy(
|
||||
std::istream_iterator<float> (ss),
|
||||
std::istream_iterator<float> (),
|
||||
back_inserter(values)
|
||||
);
|
||||
|
||||
for(int option : selectedOptions){
|
||||
value = values[option+3]; //+3 because options x, y and z in the file
|
||||
dataOptions[option][numValues] = processDataPoint(value, option);
|
||||
}
|
||||
numValues++;
|
||||
}
|
||||
|
||||
calculateFilterValues(selectedOptions);
|
||||
return dataOptions;
|
||||
}
|
||||
return std::vector<float*>();
|
||||
}
|
||||
|
||||
}//namespace openspace
|
||||
47
modules/iswa/util/dataprocessortext.h
Normal file
47
modules/iswa/util/dataprocessortext.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2015 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
#include <modules/iswa/util/dataprocessor.h>
|
||||
|
||||
#ifndef __DATAPROCESSORTEXT_H__
|
||||
#define __DATAPROCESSORTEXT_H__
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class DataProcessorText : public DataProcessor {
|
||||
public:
|
||||
DataProcessorText();
|
||||
~DataProcessorText();
|
||||
|
||||
virtual std::vector<std::string> readMetadata(std::string data) override;
|
||||
virtual void addDataValues(std::string data, properties::SelectionProperty& dataOptions) override;
|
||||
virtual std::vector<float*> processData(std::string data, properties::SelectionProperty& dataOptions) override;
|
||||
|
||||
private:
|
||||
// void initialize(int numOptions);
|
||||
// void add(std::vector<std::vector<float>>& optionValues, std::vector<float>& sum);
|
||||
// void calculateFilterValues(std::vector<int> selectedOptions);
|
||||
};
|
||||
|
||||
}// namespace
|
||||
#endif __DATAPROCESSORTEXT_H__
|
||||
@@ -70,6 +70,10 @@ IswaManager::IswaManager()
|
||||
_type[CygnetType::Texture] = "Texture";
|
||||
_type[CygnetType::Data] = "Data";
|
||||
_type[CygnetType::Kameleon] = "Kameleon";
|
||||
// _type[CygnetType::TexturePlane] = "TexturePlane";
|
||||
// _type[CygnetType::DataPlane] = "DataPlane";
|
||||
// _type[CygnetType::KameleonPlane] = "KameleonPlane";
|
||||
// _type[CygnetType::Kameleon] = "DataSphere";
|
||||
|
||||
_geom[CygnetGeometry::Plane] = "Plane";
|
||||
_geom[CygnetGeometry::Sphere] = "Sphere";
|
||||
@@ -160,8 +164,8 @@ void IswaManager::addKameleonCdf(std::string group, int pos){
|
||||
// auto info = _cdfInformation[group][pos];
|
||||
// std::cout << group << " " << pos << std::endl;
|
||||
createKameleonPlane(_cdfInformation[group][pos], "z");
|
||||
createKameleonPlane(_cdfInformation[group][pos], "y");
|
||||
createKameleonPlane(_cdfInformation[group][pos], "x");
|
||||
// createKameleonPlane(_cdfInformation[group][pos], "y");
|
||||
// createKameleonPlane(_cdfInformation[group][pos], "x");
|
||||
}
|
||||
|
||||
std::future<DownloadManager::MemoryFile> IswaManager::fetchImageCygnet(int id){
|
||||
@@ -213,41 +217,14 @@ std::string IswaManager::iswaUrl(int id, std::string type){
|
||||
return url;
|
||||
}
|
||||
|
||||
std::shared_ptr<ghoul::Event<ghoul::Dictionary> > IswaManager::groupEvent(std::string groupName, CygnetType type){
|
||||
|
||||
// Do some type checking and get the groupEvent
|
||||
void IswaManager::registerGroup(std::string groupName, std::string type){
|
||||
if(_groups.find(groupName) == _groups.end()){
|
||||
_groups.insert(std::pair<std::string, std::shared_ptr<IswaGroup>>(groupName, std::make_shared<IswaGroup>(groupName, type)));
|
||||
} else if(!_groups[groupName]->isType(type)){
|
||||
LWARNING("Can't subscribe to Events from groups with diffent type");
|
||||
return nullptr;
|
||||
LWARNING("Can't add cygnet to groups with diffent type");
|
||||
}
|
||||
|
||||
return _groups[groupName]->groupEvent();
|
||||
}
|
||||
|
||||
std::shared_ptr<IswaGroup> IswaManager::registerToGroup(std::string groupName, CygnetType type){
|
||||
if(_groups.find(groupName) == _groups.end()){
|
||||
_groups.insert(std::pair<std::string, std::shared_ptr<IswaGroup>>(groupName, std::make_shared<IswaGroup>(groupName, type)));
|
||||
} else if(!_groups[groupName]->isType(type)){
|
||||
LWARNING("Can't subscribe to Events from groups with diffent type");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return _groups[groupName];
|
||||
}
|
||||
|
||||
// void IswaManager::unregisterFromGroup(std::string name, IswaCygnet* cygnet){
|
||||
// if(_groups.find(name) != _groups.end()){
|
||||
// _groups[name]->unregisterCygnet(cygnet);
|
||||
// }
|
||||
// }
|
||||
|
||||
// void IswaManager::registerOptionsToGroup(std::string name, const std::vector<properties::SelectionProperty::Option>& options){
|
||||
// if(_groups.find(name) != _groups.end()){
|
||||
// _groups[name]->registerOptions(options);
|
||||
// }
|
||||
// }
|
||||
|
||||
std::shared_ptr<IswaGroup> IswaManager::iswaGroup(std::string name){
|
||||
if(_groups.find(name) != _groups.end()){
|
||||
@@ -384,6 +361,7 @@ std::string IswaManager::parseKWToLuaTable(CdfInfo info, std::string cut){
|
||||
"axisCut = '"+cut+"',"
|
||||
"CoordinateType = '" + coordinateType + "', "
|
||||
"Group = '"+ info.group + "',"
|
||||
"Group = '',"
|
||||
"fieldlineSeedsIndexFile = '"+info.fieldlineSeedsIndexFile+"'"
|
||||
"}"
|
||||
"}"
|
||||
@@ -451,12 +429,26 @@ void IswaManager::createScreenSpace(int id){
|
||||
|
||||
void IswaManager::createPlane(std::shared_ptr<MetadataFuture> data){
|
||||
// check if this plane already exist
|
||||
std::cout << "IswaManager: " << typeid(DataPlane).name() << std::endl;
|
||||
|
||||
std::string name = _type[data->type] + _geom[data->geom] + std::to_string(data->id);
|
||||
|
||||
if(!data->group.empty()){
|
||||
std::string type;
|
||||
if(data->type == CygnetType::Data){
|
||||
type = typeid(DataPlane).name();
|
||||
}else{
|
||||
type = typeid(TexturePlane).name();
|
||||
}
|
||||
|
||||
registerGroup(data->group, type);
|
||||
|
||||
auto it = _groups.find(data->group);
|
||||
if(it == _groups.end() || (*it).second->isType((CygnetType) data->type))
|
||||
if(it == _groups.end() || (*it).second->isType(type)){
|
||||
name = data->group +"_"+ name;
|
||||
}else{
|
||||
data->group="";
|
||||
}
|
||||
}
|
||||
|
||||
data->name = name;
|
||||
@@ -478,9 +470,15 @@ void IswaManager::createSphere(std::shared_ptr<MetadataFuture> data){
|
||||
std::string name = _type[data->type] + _geom[data->geom] + std::to_string(data->id);
|
||||
|
||||
if(!data->group.empty()){
|
||||
std::string type = typeid(DataSphere).name();
|
||||
registerGroup(data->group, type);
|
||||
|
||||
auto it = _groups.find(data->group);
|
||||
if(it == _groups.end() || (*it).second->isType((CygnetType) data->type))
|
||||
if(it == _groups.end() || (*it).second->isType(type)){
|
||||
name = data->group +"_"+name;
|
||||
}else{
|
||||
data->group="";
|
||||
}
|
||||
}
|
||||
|
||||
data->name = name;
|
||||
|
||||
@@ -94,8 +94,8 @@ public:
|
||||
std::string iswaUrl(int id, std::string type = "image");
|
||||
|
||||
std::shared_ptr<ghoul::Event<ghoul::Dictionary> > groupEvent(std::string name, CygnetType type);
|
||||
std::shared_ptr<IswaGroup> registerToGroup(std::string name, CygnetType type);
|
||||
void unregisterFromGroup(std::string name, IswaCygnet* cygnet);
|
||||
// std::shared_ptr<IswaGroup> getIswaGroup(std::string groupName, CygnetType type);
|
||||
// void unregisterFromGroup(std::string name, IswaCygnet* cygnet);
|
||||
// void registerOptionsToGroup(std::string name, const std::vector<properties::SelectionProperty::Option>& options);
|
||||
std::shared_ptr<IswaGroup> iswaGroup(std::string name);
|
||||
|
||||
@@ -124,6 +124,8 @@ private:
|
||||
|
||||
void fillCygnetInfo(std::string jsonString);
|
||||
|
||||
void registerGroup(std::string groupName, std::string type);
|
||||
|
||||
std::map<std::string, std::string> _month;
|
||||
std::map<int, std::string> _type;
|
||||
std::map<int, std::string> _geom;
|
||||
|
||||
@@ -139,6 +139,7 @@ public:
|
||||
std::string getParent();
|
||||
std::string getFrame();
|
||||
std::vector<std::string> getVariables();
|
||||
std::vector<std::string> getLoadedVariables();
|
||||
|
||||
private:
|
||||
typedef std::vector<glm::vec3> TraceLine;
|
||||
|
||||
@@ -477,12 +477,12 @@ float* KameleonWrapper::getUniformSliceValues(
|
||||
}
|
||||
}
|
||||
}
|
||||
for(size_t i = 0; i < size; ++i) {
|
||||
// for(size_t i = 0; i < size; ++i) {
|
||||
// double normalizedVal = (doubleData[i]-minValue)/(maxValue-minValue);
|
||||
// data[i] = glm::clamp(normalizedVal, 0.0, 1.0);
|
||||
// data[i] = 1;
|
||||
// std::cout << minValue << ", " << maxValue << ", " << doubleData[i] << ", " << normalizedVal << ", " << data[i] << std::endl;
|
||||
}
|
||||
// }
|
||||
|
||||
delete[] doubleData;
|
||||
return data;
|
||||
@@ -1057,4 +1057,8 @@ std::vector<std::string> KameleonWrapper::getVariables(){
|
||||
return variableNames;
|
||||
}
|
||||
|
||||
std::vector<std::string> KameleonWrapper::getLoadedVariables(){
|
||||
return _kameleon->getLoadedVariables();
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
Reference in New Issue
Block a user