2.12.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Commit 110bf0e2 authored by schultezub's avatar schultezub
Browse files

* Implemented logarithmic scale for TF editor intensity histogram

* Various fixes for transfer functions and its editors

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@421 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 24125f05
......@@ -43,6 +43,7 @@
#include "core/properties/transferfunctionproperty.h"
#include "core/tools/opengljobprocessor.h"
#include <QCheckBox>
#include <QGridLayout>
#include <QLabel>
#include <QPushButton>
......@@ -52,11 +53,14 @@ namespace campvis {
Geometry1DTransferFunctionEditor::Geometry1DTransferFunctionEditor(Geometry1DTransferFunction* tf, QWidget* parent /*= 0*/)
: AbstractTransferFunctionEditor(tf, parent)
, _logScale(true)
, _layout(0)
, _canvas(0)
, _lblIntensityLeft(0)
, _lblIntensityRight(0)
, _btnAddGeometry(0)
, _btnRemoveGeometry(0)
, _cbLogScale(0)
{
_selectedGeometry = 0;
setupGUI();
......@@ -120,18 +124,25 @@ namespace campvis {
size_t numBuckets = ih->getNumBuckets(0);
if (numBuckets > 0) {
float maxFilling = static_cast<float>(ih->getMaxFilling());
if (_logScale)
maxFilling = log(maxFilling);
float xl = static_cast<float>(0.f) / static_cast<float>(numBuckets);
float xr = 0.f;
float yl = static_cast<float>(ih->getNumElements(0)) / maxFilling;
float yl = (_logScale
? log(static_cast<float>(ih->getNumElements(0))) / maxFilling
: static_cast<float>(ih->getNumElements(0)) / maxFilling);
float yr = 0.f;
glBegin(GL_QUADS);
glColor4f(1.f, .75f, 0.f, .5f);
for (size_t i = 1; i < numBuckets; ++i) {
xr = static_cast<float>(i) / static_cast<float>(numBuckets);
yr = static_cast<float>(ih->getNumElements(i)) / maxFilling;
yr = (_logScale
? std::max(0.f, log(static_cast<float>(ih->getNumElements(i))) / maxFilling)
: static_cast<float>(ih->getNumElements(i)) / maxFilling);
glVertex2f(xl, 0.f);
glVertex2f(xl, yl);
glVertex2f(xr, yr);
......@@ -249,7 +260,10 @@ namespace campvis {
_btnRemoveGeometry = new QPushButton(tr("Remove Geometry"), this);
buttonLayout->addWidget(_btnRemoveGeometry);
connect(_btnRemoveGeometry, SIGNAL(clicked()), this, SLOT(onBtnRemoveGeometryClicked()));
_cbLogScale = new QCheckBox(tr("Logarithmic Scale"), this);
_cbLogScale->setChecked(true);
buttonLayout->addWidget(_cbLogScale);
connect(_cbLogScale, SIGNAL(stateChanged(int)), this, SLOT(onCbLogScaleStateChanged(int)));
_layout->setColumnStretch(2, 1);
_layout->setRowStretch(2, 1);
}
......@@ -325,5 +339,10 @@ namespace campvis {
}
}
void Geometry1DTransferFunctionEditor::onCbLogScaleStateChanged(int state) {
_logScale = (state & Qt::Checked);
invalidate();
}
}
\ No newline at end of file
......@@ -36,6 +36,7 @@
#include "core/classification/tfgeometry1d.h"
#include "application/gui/properties/abstracttransferfunctioneditor.h"
class QCheckBox;
class QGridLayout;
class QLabel;
class QPushButton;
......@@ -104,6 +105,12 @@ namespace campvis {
*/
void onBtnRemoveGeometryClicked();
/**
* Slot to be called when _cbLogScale's check state has changed.
* \param state the checkbox's new Qt::CheckState.
*/
void onCbLogScaleStateChanged(int state);
protected:
/**
* Gets called when the property has changed, so that widget can update its state.
......@@ -128,6 +135,7 @@ namespace campvis {
std::vector<AbstractTFGeometryManipulator*> _manipulators;
tbb::atomic<WholeTFGeometryManipulator*> _selectedGeometry;
bool _logScale;
tbb::mutex _localMutex;
QGridLayout* _layout;
......@@ -137,6 +145,7 @@ namespace campvis {
QLabel* _lblIntensityRight;
QPushButton* _btnAddGeometry;
QPushButton* _btnRemoveGeometry;
QCheckBox* _cbLogScale;
};
}
......
......@@ -112,12 +112,12 @@ namespace campvis {
const tgt::vec2& domain = tf->getIntensityDomain();
_spinDomainLeft->blockSignals(true);
//_spinDomainLeft->setMaximum(domain.y);
_spinDomainLeft->setMaximum(domain.y);
_spinDomainLeft->setValue(domain.x);
_spinDomainLeft->blockSignals(false);
_spinDomainRight->blockSignals(true);
/*_spinDomainRight->setMinimum(domain.x);*/
_spinDomainRight->setMinimum(domain.x);
_spinDomainRight->setValue(domain.y);
_spinDomainRight->blockSignals(false);
}
......@@ -125,8 +125,8 @@ namespace campvis {
void TransferFunctionPropertyWidget::onDomainChanged(double value) {
TransferFunctionProperty* prop = static_cast<TransferFunctionProperty*>(_property);
_ignorePropertyUpdates = true;
// _spinDomainLeft->setMaximum(_spinDomainRight->value());
// _spinDomainRight->setMinimum(_spinDomainLeft->value());
_spinDomainLeft->setMaximum(_spinDomainRight->value());
_spinDomainRight->setMinimum(_spinDomainLeft->value());
tgt::vec2 newDomain(static_cast<float>(_spinDomainLeft->value()), static_cast<float>(_spinDomainRight->value()));
prop->getTF()->setIntensityDomain(newDomain);
_ignorePropertyUpdates = false;
......
......@@ -173,13 +173,15 @@ namespace campvis {
_intensityHistogram = 0;
if (_imageHandle.getData() != 0) {
const ImageRepresentationLocal* idl = dynamic_cast<const ImageRepresentationLocal*>(_imageHandle.getData());
if (idl != 0) {
float mins = _intensityDomain.x;
float maxs = _intensityDomain.y;
size_t numBuckets = 512;
_intensityHistogram = new IntensityHistogramType(&mins, &maxs, &numBuckets);
tbb::parallel_for(tbb::blocked_range<size_t>(0, idl->getNumElements()), IntensityHistogramGenerator(idl, _intensityHistogram));
const ImageData* id = dynamic_cast<const ImageData*>(_imageHandle.getData());
if (id != 0) {
if(const ImageRepresentationLocal* idl = id->getRepresentation<ImageRepresentationLocal>()) {
float mins = _intensityDomain.x;
float maxs = _intensityDomain.y;
size_t numBuckets = std::min(WeaklyTypedPointer::numBytes(idl->getWeaklyTypedPointer()._baseType) << 8, 512U);
_intensityHistogram = new IntensityHistogramType(&mins, &maxs, &numBuckets);
tbb::parallel_for(tbb::blocked_range<size_t>(0, idl->getNumElements()), IntensityHistogramGenerator(idl, _intensityHistogram));
}
}
}
......
......@@ -148,7 +148,7 @@ namespace campvis {
_arraySize *= _numBuckets[i];
}
_buckets = new tbb::atomic<size_t>[_arraySize];
_buckets = new tbb::atomic<size_t>[_arraySize + 1];
for (size_t i = 0; i < _arraySize; ++i)
_buckets[i] = 0;
_numSamples = 0;
......@@ -188,10 +188,14 @@ namespace campvis {
template<typename T, size_t ND>
size_t campvis::ConcurrentGenericHistogramND<T, ND>::getBucketNumber(size_t dimension, T sample) const {
tgtAssert(dimension < ND, "Dimension out of bounds.");
#ifdef CAMPVIS_DEBUG
if (sample < _min[dimension] || sample > _max[dimension])
if (sample < _min[dimension] || sample > _max[dimension]) {
return _numBuckets[dimension];
#ifdef CAMPVIS_DEBUG_NOTNOW
LWARNINGC("CAMPVis.core.tools.ConcurrentGenericHistogramND", "Added sample " << sample << " out of bounds for dimension " << dimension << ".");
#endif
}
double ratio = static_cast<double>(sample - _min[dimension]) / static_cast<double>(_max[dimension] - _min[dimension]);
return static_cast<size_t>(tgt::clamp(static_cast<int>(ratio * _numBuckets[dimension]), static_cast<int>(0), static_cast<int>(_numBuckets[dimension] - 1)));
}
......@@ -201,6 +205,9 @@ namespace campvis {
size_t index = 0;
size_t multiplier = 1;
for (size_t i = 0; i < ND; ++i) {
if (bucketNumbers[i] == _numBuckets[i])
return _arraySize;
index += multiplier * bucketNumbers[i];
multiplier *= _numBuckets[i];
}
......
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