Started refactoring the TransferFunctionProperty: The optional ImageData...

Started refactoring the TransferFunctionProperty: The optional ImageData handle will be stored in the TF property instead of the TF itself. Furthermore, the property now supports automatically fitting the TF window to the image data.
parent b77f179e
......@@ -34,6 +34,7 @@
#include <QGridLayout>
#include <QLabel>
#include <QPushButton>
#include <QCheckBox>
namespace campvis {
TransferFunctionPropertyWidget::TransferFunctionPropertyWidget(TransferFunctionProperty* property, QWidget* parent /*= 0*/)
......@@ -43,6 +44,8 @@ namespace campvis {
, _lblDomain(0)
, _spinDomainLeft(0)
, _spinDomainRight(0)
, _cbAutoFitDomainToImage(0)
, _btnFitDomainToImage(0)
, _btnEditTF(0)
, _dockWidget(0)
, _editor(0)
......@@ -51,7 +54,7 @@ namespace campvis {
_gridLayout = new QGridLayout(_widget);
_widget->setLayout(_gridLayout);
_lblDomain = new QLabel("Intensity Domain: ", _widget);
_lblDomain = new QLabel("Window:", _widget);
_gridLayout->addWidget(_lblDomain, 0, 0);
......@@ -70,38 +73,30 @@ namespace campvis {
_btnFitDomainToImage = new QPushButton("Fit", _widget);
_gridLayout->addWidget(_btnFitDomainToImage, 0, 3);
_cbAutoFitDomainToImage = new QCheckBox("Auto", _widget);
_gridLayout->addWidget(_cbAutoFitDomainToImage, 0, 4);
_btnEditTF = new QPushButton("Edit Transfer Function", _widget);
_gridLayout->addWidget(_btnEditTF, 1, 1, 1, 3);
_gridLayout->addWidget(_btnEditTF, 1, 1, 1, 4);
addWidget(_widget);
onTransferFunctionImageHandleChanged();
updateWidgetFromProperty();
property->getTF()->s_imageHandleChanged.connect(this, &TransferFunctionPropertyWidget::onTransferFunctionImageHandleChanged);
connect(_spinDomainLeft, SIGNAL(valueChanged(double)), this, SLOT(onDomainChanged(double)));
connect(_spinDomainRight, SIGNAL(valueChanged(double)), this, SLOT(onDomainChanged(double)));
connect(_btnEditTF, SIGNAL(clicked(bool)), this, SLOT(onEditClicked(bool)));
connect(_btnFitDomainToImage, SIGNAL(clicked(bool)), this, SLOT(onFitClicked(bool)));
connect(_cbAutoFitDomainToImage, SIGNAL(stateChanged(int)), this, SLOT(onAutoFitDomainToImageChanged(int)));
property->s_autoFitWindowToDataChanged.connect(this, &TransferFunctionPropertyWidget::onTransferFunctionAutoFitWindowToDataChanged);
}
TransferFunctionPropertyWidget::~TransferFunctionPropertyWidget() {
static_cast<TransferFunctionProperty*>(_property)->getTF()->s_imageHandleChanged.disconnect(this);
static_cast<TransferFunctionProperty*>(_property)->s_autoFitWindowToDataChanged.disconnect(this);
delete _dockWidget;
}
void TransferFunctionPropertyWidget::onTransferFunctionImageHandleChanged() {
DataHandle dh = static_cast<TransferFunctionProperty*>(_property)->getTF()->getImageHandle();
if (dh.getData() != 0) {
const ImageRepresentationLocal* idl = dynamic_cast<const ImageRepresentationLocal*>(dh.getData());
if (idl != 0) {
Interval<float> intensityInterval = idl->getNormalizedIntensityRange();
// _spinDomainLeft->setMinimum(intensityInterval.getLeft());
// _spinDomainRight->setMaximum(intensityInterval.getRight());
}
}
}
void TransferFunctionPropertyWidget::updateWidgetFromProperty() {
TransferFunctionProperty* prop = static_cast<TransferFunctionProperty*>(_property);
AbstractTransferFunction* tf = prop->getTF();
......@@ -116,6 +111,10 @@ namespace campvis {
_spinDomainRight->setMinimum(domain.x);
_spinDomainRight->setValue(domain.y);
_spinDomainRight->blockSignals(false);
_cbAutoFitDomainToImage->blockSignals(true);
_cbAutoFitDomainToImage->setChecked(prop->getAutoFitWindowToData());
_cbAutoFitDomainToImage->blockSignals(false);
}
void TransferFunctionPropertyWidget::onDomainChanged(double value) {
......@@ -156,5 +155,14 @@ namespace campvis {
}
}
void TransferFunctionPropertyWidget::onAutoFitDomainToImageChanged(int state) {
TransferFunctionProperty* prop = static_cast<TransferFunctionProperty*>(_property);
prop->setAutoFitWindowToData(state != Qt::Unchecked);
}
void TransferFunctionPropertyWidget::onTransferFunctionAutoFitWindowToDataChanged() {
emit s_propertyChanged(_property);
}
}
\ No newline at end of file
......@@ -33,6 +33,7 @@ class QDoubleSpinBox;
class QGridLayout;
class QLabel;
class QPushButton;
class QCheckBox;
namespace campvis {
class AbstractTransferFunctionEditor;
......@@ -56,17 +57,17 @@ namespace campvis {
*/
virtual ~TransferFunctionPropertyWidget();
/**
* Slot to be called when the propertie's TF changed its image DataHandle.
* Resets the intensity domain borders.
*/
void onTransferFunctionImageHandleChanged();
protected:
/**
* Gets called when the property has changed, so that widget can update its state.
*/
virtual void updateWidgetFromProperty();
/**
* Slot to be called from property when the property's flag whether to auto fit the TF window has changed.
*/
void onTransferFunctionAutoFitWindowToDataChanged();
private slots:
/// slot called when one of the intensity domain spin edits has changed
......@@ -75,6 +76,8 @@ namespace campvis {
void onEditClicked(bool checked);
/// slot called when _btnFitDomainToImage clicked
void onFitClicked(bool checked);
/// slot called when _cbAutoFitDomainToImage changed
void onAutoFitDomainToImageChanged(int state);
private:
QWidget* _widget; ///< Widget grouping the widgets together
......@@ -83,6 +86,7 @@ namespace campvis {
QLabel* _lblDomain; ///< intensity domain label
QDoubleSpinBox* _spinDomainLeft; ///< spin edit for intensity domain lower bound
QDoubleSpinBox* _spinDomainRight; ///< spin edit for intensity domain upper bound
QCheckBox* _cbAutoFitDomainToImage; ///< Checkbox for the flag whether to automatically fit the TF domain to new image data
QPushButton* _btnFitDomainToImage; ///< button for fitting the intensity domain to the image
QPushButton* _btnEditTF; ///< button for showing the TF editor widget
......
......@@ -38,7 +38,7 @@ namespace campvis {
RaycastingProcessor::RaycastingProcessor(IVec2Property* viewportSizeProp, const std::string& fragmentShaderFileName, bool bindEntryExitDepthTextures)
: VisualizationProcessor(viewportSizeProp)
, p_sourceImageID("sourceImageID", "Input Image", "", DataNameProperty::READ)
, p_sourceImageID("sourceImageID", "Input Image", "", DataNameProperty::READ, AbstractProcessor::INVALID_RESULT | AbstractProcessor::INVALID_PROPERTIES)
, p_entryImageID("entryImageID", "Input Entry Points Image", "", DataNameProperty::READ)
, p_exitImageID("exitImageID", "Input Exit Points Image", "", DataNameProperty::READ)
, p_camera("camera", "Camera")
......@@ -152,4 +152,11 @@ namespace campvis {
return toReturn;
}
void RaycastingProcessor::updateProperties(DataContainer& dc) {
ScopedTypedData<ImageData> img(dc, p_sourceImageID.getValue());
p_transferFunction.setImageHandle(img.getDataHandle());
validate(AbstractProcessor::INVALID_PROPERTIES);
}
}
......@@ -95,6 +95,9 @@ namespace campvis {
*/
virtual void process(DataContainer& data);
/// \see AbstractProcessor::updateProperties
virtual void updateProperties(DataContainer& dc);
DataNameProperty p_sourceImageID; ///< image ID for input image
DataNameProperty p_entryImageID; ///< image ID for output entry points image
DataNameProperty p_exitImageID; ///< image ID for output exit points image
......
......@@ -23,6 +23,8 @@
// ================================================================================================
#include "transferfunctionproperty.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagerepresentationlocal.h"
namespace campvis {
......@@ -31,6 +33,8 @@ namespace campvis {
TransferFunctionProperty::TransferFunctionProperty(const std::string& name, const std::string& title, AbstractTransferFunction* tf, int invalidationLevel /*= AbstractProcessor::INVALID_RESULT*/)
: AbstractProperty(name, title, invalidationLevel)
, _transferFunction(tf)
, _imageHandle(0)
, _autoFitWindowToData(true)
{
tgtAssert(tf != 0, "Assigned transfer function must not be 0.");
tf->s_changed.connect(this, &TransferFunctionProperty::onTFChanged);
......@@ -51,6 +55,7 @@ namespace campvis {
void TransferFunctionProperty::deinit() {
_transferFunction->deinit();
_imageHandle = DataHandle(0);
}
void TransferFunctionProperty::replaceTF(AbstractTransferFunction* tf) {
......@@ -75,4 +80,36 @@ namespace campvis {
tgtAssert(false, "Sharing of TF properties not supported!");
}
campvis::DataHandle TransferFunctionProperty::getImageHandle() const {
return _imageHandle;
}
void TransferFunctionProperty::setImageHandle(DataHandle imageHandle) {
tgtAssert(
imageHandle.getData() == 0 || dynamic_cast<const ImageData*>(imageHandle.getData()) != 0,
"The data in the image handle must either be 0 or point to a valid ImageData object!");
if (_autoFitWindowToData && imageHandle.getData() != 0) {
if (const ImageData* id = dynamic_cast<const ImageData*>(imageHandle.getData())) {
const ImageRepresentationLocal* localRep = id->getRepresentation<ImageRepresentationLocal>();
if (localRep != 0) {
const Interval<float>& ii = localRep->getNormalizedIntensityRange();
_transferFunction->setIntensityDomain(tgt::vec2(ii.getLeft(), ii.getRight()));
}
}
}
_imageHandle = imageHandle;
s_imageHandleChanged();
}
void TransferFunctionProperty::setAutoFitWindowToData(bool newValue) {
_autoFitWindowToData = newValue;
s_autoFitWindowToDataChanged();
}
bool TransferFunctionProperty::getAutoFitWindowToData() const {
return _autoFitWindowToData;
}
}
......@@ -76,13 +76,48 @@ namespace campvis {
* Slot being called when \a _transferFunction has changed.
*/
void onTFChanged();
/**
* Returns a DataHandle to the image for this transfer function, its pointer may be 0.
* \note If the data in \a imageHandle is not 0, it points to a valid ImageData object.
* \return _imageHandle, its pointer may be 0.
*/
DataHandle getImageHandle() const;
/**
* Sets the DataHandle for this transfer function, its pointer may be 0.
* \note If the data in \a imageHandle is not 0, it must point to a valid ImageData object.
* \param imageHandle The new DataHandle for this transfer function, if its pointer is
* not 0 it must point to a valid ImageData object.
*/
void setImageHandle(DataHandle imageHandle);
/**
* Returns the flag whether to automatically fit the TF window to the data in the image handle.
* \return _autoFitWindowToData
*/
bool getAutoFitWindowToData() const;
/**
* Sets the flag whether to automatically fit the TF window to the data in the image handle.
* \param newValue New value of the flag whether to automatically fit the TF window to the data in the image handle.
*/
void setAutoFitWindowToData(bool newValue);
/// Signal emmitted directly before replacing the entire transfer function
sigslot::signal1<AbstractTransferFunction*> s_BeforeTFReplace;
/// Signal emmitted directly after replacing the entire transfer function
sigslot::signal1<AbstractTransferFunction*> s_AfterTFReplace;
/// Signal emitted when the image DataHandle for this TF has changed.
sigslot::signal0<> s_imageHandleChanged;
/// Signal emitted when the flag whether to automatically fit the TF window to the data in the image handle.
sigslot::signal0<> s_autoFitWindowToDataChanged;
protected:
AbstractTransferFunction* _transferFunction; ///< Transfer function of this property
DataHandle _imageHandle; ///< DataHandle to the image for this transfer function. May be 0.
bool _autoFitWindowToData; ///< Flag whether to automatically fit the TF window to the data in the image handle.
static const std::string loggerCat_;
};
......
......@@ -254,7 +254,7 @@ namespace campvis {
void SliceExtractor::updateProperties(DataContainer& dc) {
ScopedTypedData<ImageData> img(dc, p_sourceImageID.getValue());
p_transferFunction.getTF()->setImageHandle(img.getDataHandle());
p_transferFunction.setImageHandle(img.getDataHandle());
if (img != 0) {
tgt::ivec3 imgSize = img->getSize();
......
......@@ -83,6 +83,8 @@ namespace campvis {
/// \see AbstractProcessor::getProcessorState()
virtual ProcessorState getProcessorState() const { return AbstractProcessor::EXPERIMENTAL; };
/// \see AbstractProcessor::updateProperties
virtual void updateProperties(DataContainer& dc);
/// \see AbstractProcessor::process()
virtual void process(DataContainer& data);
......@@ -99,10 +101,6 @@ namespace campvis {
TransferFunctionProperty p_transferFunction; ///< Transfer function
protected:
/// adapts the range of the p_xSliceNumber property to the image
/// \see AbstractPro#::updateProperties
virtual void updateProperties(DataContainer& dc);
void updateBorderGeometry();
tgt::Shader* _shader; ///< Shader for slice rendering
......
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