Notice: If you are member of any public project or group, please make sure that your GitLab username is not the same as the LRZ identifier/Kennung (see https://gitlab.lrz.de/profile/account). Please change your username if necessary. For more information see the section "Public projects / Öffentliche Projekte" at https://doku.lrz.de/display/PUBLIC/GitLab . Thank you!

Commit 180238b4 authored by Jakob Weiss's avatar Jakob Weiss

Transfer function backup and restore

It is now possible to backup and restore 1D transfer functions in a very simple text file format.
parent 923f47db
......@@ -40,6 +40,7 @@
#include <QCheckBox>
#include <QGridLayout>
#include <QLabel>
#include <QFileDialog>
#include <QPushButton>
#include <QVBoxLayout>
......@@ -55,6 +56,8 @@ namespace campvis {
, _btnAddGeometry(0)
, _btnRemoveGeometry(0)
, _cbLogScale(0)
, _btnSaveTF(nullptr)
, _btnLoadTF(nullptr)
{
_selectedGeometry = 0;
setupGUI();
......@@ -257,6 +260,15 @@ namespace campvis {
_cbLogScale->setChecked(true);
buttonLayout->addWidget(_cbLogScale);
connect(_cbLogScale, SIGNAL(stateChanged(int)), this, SLOT(onCbLogScaleStateChanged(int)));
_btnSaveTF = new QPushButton(tr("Save TF"), this);
buttonLayout->addWidget(_btnSaveTF);
connect(_btnSaveTF, &QPushButton::clicked, this, &Geometry1DTransferFunctionEditor::onBtnSaveTFClicked);
_btnLoadTF = new QPushButton(tr("Load TF"), this);
buttonLayout->addWidget(_btnLoadTF);
connect(_btnLoadTF, &QPushButton::clicked, this, &Geometry1DTransferFunctionEditor::onBtnLoadTFClicked);
_layout->setColumnStretch(2, 1);
_layout->setRowStretch(2, 1);
}
......@@ -337,6 +349,31 @@ namespace campvis {
emit s_invalidated();
}
void Geometry1DTransferFunctionEditor::onBtnSaveTFClicked()
{
std::cout << "Saving transfer function...." << std::endl;
QString of = QFileDialog::getSaveFileName(this, tr("Open Transfer Function"), ".", "*.txt");
if (!of.isEmpty()) {
Geometry1DTransferFunction* gtf = static_cast<Geometry1DTransferFunction*>(_transferFunction);
std::ofstream tfFile(of.toStdString());
gtf->serialize(tfFile);
}
}
void Geometry1DTransferFunctionEditor::onBtnLoadTFClicked()
{
std::cout << "Loading transfer function..." << std::endl;
QString of = QFileDialog::getOpenFileName(this, tr("Open Transfer Function"), ".", "*.txt");
if (!of.isEmpty()) {
std::ifstream tfFile(of.toStdString());
//Geometry1DTransferFunction* gtf = static_cast<Geometry1DTransferFunction*>(_transferFunction);
Geometry1DTransferFunction* gtf = Geometry1DTransferFunction::unserialize(tfFile);
_tfProperty->replaceTF(gtf);
}
}
void Geometry1DTransferFunctionEditor::onTfAboutToBeDeleted() {
disconnectFromTf();
}
......
......@@ -117,6 +117,16 @@ namespace campvis {
*/
void onCbLogScaleStateChanged(int state);
/**
* Slot to be called when the TF save button is clicked.
*/
void onBtnSaveTFClicked();
/**
* Slot to be called when the TF load button is clicked.
*/
void onBtnLoadTFClicked();
/**
* Slot reacting to the invalidated signal, issueing a new paint job
*/
......@@ -162,6 +172,8 @@ namespace campvis {
QPushButton* _btnAddGeometry;
QPushButton* _btnRemoveGeometry;
QCheckBox* _cbLogScale;
QPushButton* _btnSaveTF;
QPushButton* _btnLoadTF;
};
}
......
......@@ -56,4 +56,53 @@ namespace campvis {
return 1;
}
void Geometry1DTransferFunction::serialize(std::ostream & stream) const
{
stream << "Domain: " << _intensityDomain.x << " " << _intensityDomain.y << std::endl;
stream << "Size: " << _size.x << " " << _size.y << " " << _size.z << std::endl;
stream << "Number of Geometries: " << _geometries.size() << std::endl;
for (auto it = _geometries.begin(); it != _geometries.end(); ++it) {
auto keypoints = (*it)->getKeyPoints();
stream << keypoints.size() << " ";
for (auto kpit = keypoints.begin(); kpit != keypoints.end(); ++kpit) {
stream << " { " << (*kpit)._position << " " << int((*kpit)._color.r) << "," << int((*kpit)._color.g) << ","
<< int((*kpit)._color.b) << "," << int((*kpit)._color.a) << " } ";
}
stream << std::endl;
}
}
Geometry1DTransferFunction * Geometry1DTransferFunction::unserialize(std::istream & stream)
{
cgt::vec2 domain; stream.ignore(10, ':'); stream >> domain.x >> domain.y;
cgt::svec3 size; stream.ignore(10, ':'); stream >> size.x >> size.y >> size.z;
size_t numGeometries; stream.ignore(25, ':'); stream >> numGeometries;
auto tf = new Geometry1DTransferFunction(size.x, domain);
for (size_t i = 0; i < numGeometries; ++i) {
size_t numKeypoints;
stream >> numKeypoints;
std::vector<TFGeometry1D::KeyPoint> keypoints;
for (size_t j = 0; j < numKeypoints; ++j) {
float position;
cgt::ivec4 color;
stream.ignore(5, '{'); stream >> position;
stream >> color.r; stream.ignore(3, ',');
stream >> color.g; stream.ignore(3, ',');
stream >> color.b; stream.ignore(3, ',');
stream >> color.a; stream.ignore(5, '}');
keypoints.push_back(TFGeometry1D::KeyPoint(position, color));
}
TFGeometry1D *geom = new TFGeometry1D(keypoints);
tf->addGeometry(geom);
}
return tf;
}
}
\ No newline at end of file
......@@ -62,6 +62,16 @@ namespace campvis {
*/
virtual size_t getDimensionality() const;
/**
* Serializes the transfer function to a stream
*/
void serialize(std::ostream& stream) const;
/**
* Reads a serialized transfer function from a stream
*/
static Geometry1DTransferFunction* unserialize(std::istream& stream);
protected:
static const std::string loggerCat_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment