Ver código fonte

Add ctkVTKThresholdWidget

Convenient widget to control a threshold vtkPiecewiseFunction
just using a range slider (lower/upper) and a slider (opacity)
Julien Finet 14 anos atrás
pai
commit
33d7e54cc1

+ 4 - 0
Libs/Visualization/VTK/Widgets/CMakeLists.txt

@@ -38,6 +38,8 @@ SET(KIT_SRCS
   ctkVTKSurfaceMaterialPropertyWidget.h
   ctkVTKTextPropertyWidget.cpp
   ctkVTKTextPropertyWidget.h
+  ctkVTKThresholdWidget.cpp
+  ctkVTKThresholdWidget.h
   ctkVTKThumbnailView.cpp
   ctkVTKThumbnailView.h
   )
@@ -59,6 +61,7 @@ SET(KIT_MOC_SRCS
   ctkVTKSliceView_p.h
   ctkVTKSurfaceMaterialPropertyWidget.h
   ctkVTKTextPropertyWidget.h
+  ctkVTKThresholdWidget.h
   ctkVTKThumbnailView.h
   )
 
@@ -66,6 +69,7 @@ SET(KIT_MOC_SRCS
 SET(KIT_UI_FORMS
   Resources/UI/ctkVTKScalarBarWidget.ui
   Resources/UI/ctkVTKTextPropertyWidget.ui
+  Resources/UI/ctkVTKThresholdWidget.ui
 )
 
 # Resources

+ 3 - 0
Libs/Visualization/VTK/Widgets/Plugins/CMakeLists.txt

@@ -27,6 +27,8 @@ SET(PLUGIN_SRCS
   ctkVTKSurfaceMaterialPropertyWidgetPlugin.h
   ctkVTKTextPropertyWidgetPlugin.cpp
   ctkVTKTextPropertyWidgetPlugin.h
+  ctkVTKThresholdWidgetPlugin.cpp
+  ctkVTKThresholdWidgetPlugin.h
   )
 
 # Headers that should run through moc
@@ -40,6 +42,7 @@ SET(PLUGIN_MOC_SRCS
   ctkVTKSliceViewPlugin.h
   ctkVTKSurfaceMaterialPropertyWidgetPlugin.h
   ctkVTKTextPropertyWidgetPlugin.h
+  ctkVTKThresholdWidgetPlugin.h
   )
   
 IF(CTK_USE_CHARTS)

+ 64 - 0
Libs/Visualization/VTK/Widgets/Plugins/ctkVTKThresholdWidgetPlugin.cpp

@@ -0,0 +1,64 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// CTK includes
+#include "ctkVTKThresholdWidget.h"
+#include "ctkVTKThresholdWidgetPlugin.h"
+
+//-----------------------------------------------------------------------------
+ctkVTKThresholdWidgetPlugin
+::ctkVTKThresholdWidgetPlugin(QObject *parentObject)
+ : QObject(parentObject)
+{
+}
+
+//-----------------------------------------------------------------------------
+QWidget *ctkVTKThresholdWidgetPlugin::createWidget(QWidget *parentWidget)
+{
+  ctkVTKThresholdWidget* newWidget =
+    new ctkVTKThresholdWidget(parentWidget);
+  return newWidget;
+}
+
+//-----------------------------------------------------------------------------
+QString ctkVTKThresholdWidgetPlugin::domXml() const
+{
+  return "<widget class=\"ctkVTKThresholdWidget\" \
+          name=\"Threshold\">\n"
+          "</widget>\n";
+}
+
+//-----------------------------------------------------------------------------
+QString ctkVTKThresholdWidgetPlugin::includeFile() const
+{
+  return "ctkVTKThresholdWidget.h";
+}
+
+//-----------------------------------------------------------------------------
+bool ctkVTKThresholdWidgetPlugin::isContainer() const
+{
+  return false;
+}
+
+//-----------------------------------------------------------------------------
+QString ctkVTKThresholdWidgetPlugin::name() const
+{
+  return "ctkVTKThresholdWidget";
+}

+ 43 - 0
Libs/Visualization/VTK/Widgets/Plugins/ctkVTKThresholdWidgetPlugin.h

@@ -0,0 +1,43 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+#ifndef __ctkVTKThresholdWidgetPlugin_h
+#define __ctkVTKThresholdWidgetPlugin_h
+
+// CTK includes
+#include "ctkVTKWidgetsAbstractPlugin.h"
+
+class CTK_VISUALIZATION_VTK_WIDGETS_PLUGINS_EXPORT ctkVTKThresholdWidgetPlugin :
+  public QObject,
+  public ctkVTKWidgetsAbstractPlugin
+{
+  Q_OBJECT
+
+public:
+  ctkVTKThresholdWidgetPlugin(QObject *parent = 0);
+
+  QWidget *createWidget(QWidget *parent);
+  QString domXml() const;
+  QString includeFile() const;
+  bool isContainer() const;
+  QString name() const;
+};
+
+#endif

+ 2 - 0
Libs/Visualization/VTK/Widgets/Plugins/ctkVTKWidgetsPlugins.h

@@ -38,6 +38,7 @@
 #include "ctkVTKSliceViewPlugin.h"
 #include "ctkVTKSurfaceMaterialPropertyWidgetPlugin.h"
 #include "ctkVTKTextPropertyWidgetPlugin.h"
+#include "ctkVTKThresholdWidgetPlugin.h"
 
 /// \class Group the plugins in one library
 class CTK_VISUALIZATION_VTK_WIDGETS_PLUGINS_EXPORT ctkVTKWidgetsPlugins :
@@ -63,6 +64,7 @@ public:
     plugins << new ctkVTKSliceViewPlugin;
     plugins << new ctkVTKSurfaceMaterialPropertyWidgetPlugin;
     plugins << new ctkVTKTextPropertyWidgetPlugin;
+    plugins << new ctkVTKThresholdWidgetPlugin;
     return plugins;
     }
 };

+ 72 - 0
Libs/Visualization/VTK/Widgets/Resources/UI/ctkVTKThresholdWidget.ui

@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ctkVTKThresholdWidget</class>
+ <widget class="QWidget" name="ctkVTKThresholdWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>251</width>
+    <height>46</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Threshold</string>
+  </property>
+  <layout class="QFormLayout" name="formLayout">
+   <property name="fieldGrowthPolicy">
+    <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+   </property>
+   <property name="margin">
+    <number>0</number>
+   </property>
+   <item row="0" column="0">
+    <widget class="QLabel" name="ThresholdLabel">
+     <property name="text">
+      <string>Threshold:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="ctkRangeWidget" name="ThresholdSliderWidget"/>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="OpacityLabel">
+     <property name="text">
+      <string>Opacity:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="ctkSliderWidget" name="OpacitySliderWidget">
+     <property name="singleStep">
+      <double>0.010000000000000</double>
+     </property>
+     <property name="pageStep">
+      <double>0.100000000000000</double>
+     </property>
+     <property name="maximum">
+      <double>1.000000000000000</double>
+     </property>
+     <property name="value">
+      <double>1.000000000000000</double>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>ctkRangeWidget</class>
+   <extends>QWidget</extends>
+   <header>ctkRangeWidget.h</header>
+  </customwidget>
+  <customwidget>
+   <class>ctkSliderWidget</class>
+   <extends>QWidget</extends>
+   <header>ctkSliderWidget.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>

+ 9 - 1
Libs/Visualization/VTK/Widgets/Resources/UI/ctkVTKVolumePropertyWidget.ui

@@ -26,7 +26,10 @@
       <property name="margin">
        <number>0</number>
       </property>
-      <item>
+       <item>
+        <widget class="ctkVTKThresholdWidget" name="ScalarOpacityThresholdWidget"/>
+       </item>
+       <item>
        <widget class="ctkVTKScalarsToColorsWidget" name="ScalarOpacityWidget">
         <property name="minimumSize">
          <size>
@@ -147,6 +150,11 @@
  </widget>
  <customwidgets>
   <customwidget>
+   <class>ctkVTKThresholdWidget</class>
+   <extends>QWidget</extends>
+   <header>ctkVTKThresholdWidget.h</header>
+  </customwidget>
+  <customwidget>
    <class>ctkVTKScalarsToColorsWidget</class>
    <extends>QWidget</extends>
    <header>ctkVTKScalarsToColorsWidget.h</header>

+ 1 - 0
Libs/Visualization/VTK/Widgets/Testing/Cpp/ctkVTKVolumePropertyWidgetTest1.cpp

@@ -64,6 +64,7 @@ int ctkVTKVolumePropertyWidgetTest1(int argc, char * argv [] )
   volumeProperty->SetScalarOpacity(otf);
 
   ctkVTKVolumePropertyWidget widget;
+  //widget.setUseThresholdSlider(true);
   widget.setVolumeProperty(volumeProperty);
 
   volumeProperty->SetScalarOpacity(otf2);

+ 299 - 0
Libs/Visualization/VTK/Widgets/ctkVTKThresholdWidget.cpp

@@ -0,0 +1,299 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// Qt includes
+#include <QDebug>
+
+// CTK includes
+#include "ctkLogger.h"
+#include "ctkVTKThresholdWidget.h"
+#include "ctkUtils.h"
+#include "ui_ctkVTKThresholdWidget.h"
+
+// VTK includes
+#include <vtkPiecewiseFunction.h>
+
+//----------------------------------------------------------------------------
+static ctkLogger logger("org.commontk.visualization.vtk.widgets.ctkVTKThresholdWidget");
+//----------------------------------------------------------------------------
+
+class ctkVTKThresholdWidgetPrivate:
+  public Ui_ctkVTKThresholdWidget
+{
+   Q_DECLARE_PUBLIC(ctkVTKThresholdWidget);
+protected:
+  ctkVTKThresholdWidget* const q_ptr;
+public:
+  ctkVTKThresholdWidgetPrivate(ctkVTKThresholdWidget& object);
+  void setupUi(QWidget* widget);
+  void setThreshold(double min, double max, double opacity);
+  void guessThreshold(double& min, double& max, double& opacity);
+  
+  vtkPiecewiseFunction* PiecewiseFunction;
+};
+
+// ----------------------------------------------------------------------------
+// ctkVTKThresholdWidgetPrivate methods
+
+// ----------------------------------------------------------------------------
+ctkVTKThresholdWidgetPrivate::ctkVTKThresholdWidgetPrivate(
+  ctkVTKThresholdWidget& object)
+  : q_ptr(&object)
+{
+  this->PiecewiseFunction = 0;
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKThresholdWidgetPrivate::setupUi(QWidget* widget)
+{
+  Q_Q(ctkVTKThresholdWidget);
+  Q_ASSERT(q == widget);
+  this->Ui_ctkVTKThresholdWidget::setupUi(widget);
+
+  QObject::connect(this->ThresholdSliderWidget, SIGNAL(valuesChanged(double, double)),
+                   q, SLOT(setThresholdValues(double, double)));
+  QObject::connect(this->OpacitySliderWidget, SIGNAL(valueChanged(double)),
+                   q, SLOT(setOpacity(double)));
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKThresholdWidgetPrivate::guessThreshold(double& min, double& max, double& opacity)
+{
+  min = this->ThresholdSliderWidget->minimum();
+  max = this->ThresholdSliderWidget->maximum();
+  opacity = 1.;
+  if (!this->PiecewiseFunction || this->PiecewiseFunction->GetSize() == 0)
+    {
+    return;
+    }
+  int minIndex; 
+  for (minIndex=0; minIndex < this->PiecewiseFunction->GetSize(); ++minIndex)
+    {
+    double node[4];
+    this->PiecewiseFunction->GetNodeValue(minIndex, node);
+    if (node[1] > 0.)
+      {
+      min = node[0];
+      opacity = node[1];
+      break;
+      }
+    }
+  if (minIndex == this->PiecewiseFunction->GetSize())
+    {
+    return;
+    }
+  int maxIndex;
+  for (maxIndex = minIndex + 1;
+       maxIndex < this->PiecewiseFunction->GetSize();
+       ++maxIndex)
+    {
+    double node[4];
+    this->PiecewiseFunction->GetNodeValue(maxIndex, node);
+    // average the opacities
+    opacity += node[1];
+    if (node[1] == 0.)
+      {
+      max = node[0];
+      opacity /= maxIndex - minIndex + 1;
+      break;
+      }
+    }
+  // couldn't find the upper threshold value, use the upper range
+  if (maxIndex == this->PiecewiseFunction->GetSize())
+    {
+    opacity /= maxIndex - minIndex;
+    }
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKThresholdWidgetPrivate::setThreshold(double min, double max, double opacity)
+{
+  if (!this->PiecewiseFunction)
+    {
+    return;
+    }
+  double range[2];
+  this->ThresholdSliderWidget->range(range);
+ 
+  double node[4];
+  node[0] = range[0];
+  node[1] = 0.;
+  node[2] = 0.5;
+  node[3] = 0.;
+  if (this->PiecewiseFunction->GetSize() < 1)
+    {
+    this->PiecewiseFunction->AddPoint(node[0], node[1], node[2], node[3]);
+    }
+  else
+    {
+    this->PiecewiseFunction->SetNodeValue(0, node);
+    }
+
+  node[0] = min;
+  node[1] = 0.;
+  node[2] = 0.;
+  node[3] = 1.;
+  if (this->PiecewiseFunction->GetSize() < 2)
+    {
+    this->PiecewiseFunction->AddPoint(node[0], node[1], node[2], node[3]);
+    }
+  else
+    {
+    this->PiecewiseFunction->SetNodeValue(1, node);
+    }
+  node[0] = max;
+  node[1] = opacity;
+  if (this->PiecewiseFunction->GetSize() < 3)
+    {
+    this->PiecewiseFunction->AddPoint(node[0], node[1], node[2], node[3]);
+    }
+  else
+    {
+    this->PiecewiseFunction->SetNodeValue(2, node);
+    }
+  node[0] = (max == range[1]) ? range[1] + 0.00000000000001 : range[1];
+  node[1] = 0.;
+  node[2] = 0.5;
+  node[3] = 0.;
+  if (this->PiecewiseFunction->GetSize() < 4)
+    {
+    this->PiecewiseFunction->AddPoint(node[0], node[1], node[2], node[3]);
+    }
+  else
+    {
+    this->PiecewiseFunction->SetNodeValue(3, node);
+    }
+
+}
+
+// ----------------------------------------------------------------------------
+// ctkVTKThresholdWidget methods
+
+// ----------------------------------------------------------------------------
+ctkVTKThresholdWidget::ctkVTKThresholdWidget(QWidget* parentWidget)
+  :QWidget(parentWidget)
+   , d_ptr(new ctkVTKThresholdWidgetPrivate(*this))
+{
+  Q_D(ctkVTKThresholdWidget);
+  d->setupUi(this);
+}
+
+// ----------------------------------------------------------------------------
+ctkVTKThresholdWidget::~ctkVTKThresholdWidget()
+{
+}
+
+// ----------------------------------------------------------------------------
+vtkPiecewiseFunction* ctkVTKThresholdWidget::piecewiseFunction()const
+{
+  Q_D(const ctkVTKThresholdWidget);
+  return d->PiecewiseFunction;
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKThresholdWidget
+::setPiecewiseFunction(vtkPiecewiseFunction* newFunction)
+{
+  Q_D(ctkVTKThresholdWidget);
+  this->qvtkReconnect(d->PiecewiseFunction, newFunction, vtkCommand::ModifiedEvent,
+                      this, SLOT(updateFromPiecewiseFunction()));
+  d->PiecewiseFunction = newFunction;
+  
+  double range[2] = {0., 1.};
+  if (d->PiecewiseFunction)
+    {
+    d->PiecewiseFunction->GetRange(range);
+    }
+  this->setRange(range[0], range[1]);
+  if (d->PiecewiseFunction)
+    {
+    double min, max, value;
+    d->guessThreshold(min, max, value);
+    d->setThreshold(min, max, value);
+    }
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKThresholdWidget::updateFromPiecewiseFunction()
+{
+  Q_D(ctkVTKThresholdWidget);
+  
+  if (!d->PiecewiseFunction)
+    {
+    return;
+    }
+  double range[2];
+  d->ThresholdSliderWidget->range(range);
+  double minThreshold = range[0];
+  double maxThreshold = range[1];
+  double opacity = 1.;
+  double node[4];
+  if (d->PiecewiseFunction->GetSize() > 1)
+    {
+    d->PiecewiseFunction->GetNodeValue(1, node);
+    minThreshold = node[0];
+    }
+  if (d->PiecewiseFunction->GetSize() > 2)
+    {
+    d->PiecewiseFunction->GetNodeValue(2, node);
+    maxThreshold = node[0];
+    opacity = node[1];
+    }
+  bool wasBlocking = d->ThresholdSliderWidget->blockSignals(true);
+  d->ThresholdSliderWidget->setValues(minThreshold, maxThreshold);
+  d->ThresholdSliderWidget->blockSignals(wasBlocking);
+  d->OpacitySliderWidget->blockSignals(true);
+  d->OpacitySliderWidget->setValue(opacity);
+  d->OpacitySliderWidget->blockSignals(wasBlocking);
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKThresholdWidget::setThresholdValues(double min, double max)
+{
+  Q_D(ctkVTKThresholdWidget);
+  d->setThreshold(min, max, d->OpacitySliderWidget->value());
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKThresholdWidget::setOpacity(double opacity)
+{
+  Q_D(ctkVTKThresholdWidget);
+  d->setThreshold(d->ThresholdSliderWidget->minimumValue(),
+                  d->ThresholdSliderWidget->maximumValue(), opacity);
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKThresholdWidget::range(double* range)const
+{
+  Q_D(const ctkVTKThresholdWidget);
+  d->ThresholdSliderWidget->range(range);
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKThresholdWidget::setRange(double min, double max)
+{
+  Q_D(ctkVTKThresholdWidget);
+  bool wasBlocking = d->ThresholdSliderWidget->blockSignals(true);
+  int decimals = qMax(0, -ctk::orderOfMagnitude(max - min) + 2);
+  d->ThresholdSliderWidget->setDecimals(decimals);
+  d->ThresholdSliderWidget->setSingleStep(pow(10., -decimals));
+  d->ThresholdSliderWidget->setRange(min, max);
+  d->ThresholdSliderWidget->blockSignals(wasBlocking);
+}

+ 65 - 0
Libs/Visualization/VTK/Widgets/ctkVTKThresholdWidget.h

@@ -0,0 +1,65 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+#ifndef __ctkVTKThresholdWidget_h
+#define __ctkVTKThresholdWidget_h
+
+//Qt includes
+#include <QWidget>
+
+// CTK includes
+#include <ctkVTKObject.h>
+#include "ctkVisualizationVTKWidgetsExport.h"
+class ctkVTKThresholdWidgetPrivate;
+
+// VTK includes
+class vtkPiecewiseFunction;
+
+class CTK_VISUALIZATION_VTK_WIDGETS_EXPORT ctkVTKThresholdWidget
+  : public QWidget
+{
+  Q_OBJECT
+  QVTK_OBJECT
+
+public:
+  ctkVTKThresholdWidget(QWidget* parent = 0);
+  virtual ~ctkVTKThresholdWidget();
+
+  vtkPiecewiseFunction* piecewiseFunction()const;
+  void range(double* range)const;
+
+public slots:
+  void setPiecewiseFunction(vtkPiecewiseFunction* function);
+  void setRange(double min, double max);
+
+protected slots:
+  void updateFromPiecewiseFunction();
+  void setThresholdValues(double min, double max);
+  void setOpacity(double opacity);
+
+protected:
+  QScopedPointer<ctkVTKThresholdWidgetPrivate> d_ptr;
+
+private:
+  Q_DECLARE_PRIVATE(ctkVTKThresholdWidget);
+  Q_DISABLE_COPY(ctkVTKThresholdWidget);
+};
+
+#endif

+ 22 - 1
Libs/Visualization/VTK/Widgets/ctkVTKVolumePropertyWidget.cpp

@@ -25,6 +25,7 @@
 #include "ctkLogger.h"
 #include "ctkVTKScalarsToColorsView.h"
 #include "ctkVTKVolumePropertyWidget.h"
+#include "ctkUtils.h"
 #include "ui_ctkVTKVolumePropertyWidget.h"
 
 // VTK includes
@@ -54,7 +55,9 @@ protected:
 public:
   ctkVTKVolumePropertyWidgetPrivate(ctkVTKVolumePropertyWidget& object);
   void setupUi(QWidget* widget);
-
+  void updateThresholdSlider(vtkPiecewiseFunction* opacityFunction);
+  void setThreshold(double min, double max, double opacity);
+  
   vtkVolumeProperty* VolumeProperty;
   int                CurrentComponent;
 };
@@ -81,6 +84,7 @@ void ctkVTKVolumePropertyWidgetPrivate::setupUi(QWidget* widget)
   this->ScalarOpacityWidget->view()->addCompositeFunction(0, 0, false, true);
   this->ScalarColorWidget->view()->addColorTransferFunction(0);
   this->GradientWidget->view()->addPiecewiseFunction(0);
+  this->ScalarOpacityThresholdWidget->setVisible(false);
 
   this->GradientGroupBox->setCollapsed(true);
   this->AdvancedGroupBox->setCollapsed(true);
@@ -154,6 +158,8 @@ void ctkVTKVolumePropertyWidget::updateFromVolumeProperty()
       d->VolumeProperty->GetGradientOpacity() : 0;
     }
 
+  d->ScalarOpacityThresholdWidget->setPiecewiseFunction(this->useThresholdSlider() ? opacityFunction : 0);
+  
   d->ScalarOpacityWidget->view()->setOpacityFunctionToPlots(opacityFunction);
   d->ScalarOpacityWidget->view()->setColorTransferFunctionToPlots(colorTransferFunction);
   d->ScalarColorWidget->view()->setColorTransferFunctionToPlots(colorTransferFunction);
@@ -242,4 +248,19 @@ void ctkVTKVolumePropertyWidget::setSpecularPower(double value)
   d->VolumeProperty->SetSpecularPower(d->CurrentComponent, value);
 }
 
+// ----------------------------------------------------------------------------
+bool ctkVTKVolumePropertyWidget::useThresholdSlider()const
+{
+  Q_D(const ctkVTKVolumePropertyWidget);
+  return d->ScalarOpacityThresholdWidget->isVisibleTo(
+    const_cast<ctkVTKVolumePropertyWidget*>(this));
+}
 
+// ----------------------------------------------------------------------------
+void ctkVTKVolumePropertyWidget::setUseThresholdSlider(bool enable)
+{
+  Q_D(ctkVTKVolumePropertyWidget);
+  d->ScalarOpacityThresholdWidget->setVisible(enable);
+  d->ScalarOpacityWidget->setVisible(!enable);
+  this->updateFromVolumeProperty();
+}

+ 7 - 0
Libs/Visualization/VTK/Widgets/ctkVTKVolumePropertyWidget.h

@@ -37,6 +37,10 @@ class CTK_VISUALIZATION_VTK_WIDGETS_EXPORT ctkVTKVolumePropertyWidget
 {
   Q_OBJECT
   QVTK_OBJECT
+  ///
+  /// Control wether a range slider widget is used to edit the opacity
+  /// function instead of a chart editor. False by default
+  Q_PROPERTY(bool useThresholdSlider READ useThresholdSlider WRITE setUseThresholdSlider)
 
 public:
   ctkVTKVolumePropertyWidget(QWidget* parent = 0);
@@ -44,6 +48,9 @@ public:
 
   vtkVolumeProperty* volumeProperty()const;
 
+  bool useThresholdSlider()const;
+  void setUseThresholdSlider(bool enable);
+
 public slots:
   void setVolumeProperty(vtkVolumeProperty* volumeProperty);
 

+ 10 - 0
Libs/Widgets/ctkRangeWidget.cpp

@@ -236,6 +236,16 @@ double ctkRangeWidget::maximum()const
 }
 
 // --------------------------------------------------------------------------
+void ctkRangeWidget::range(double* range)const
+{
+  Q_D(const ctkRangeWidget);
+  Q_ASSERT(d->equal(d->MinimumSpinBox->minimum(),d->Slider->minimum()));
+  Q_ASSERT(d->equal(d->MaximumSpinBox->maximum(), d->Slider->maximum()));
+  range[0] = d->Slider->minimum();
+  range[1] = d->Slider->maximum();
+}
+
+// --------------------------------------------------------------------------
 void ctkRangeWidget::setMinimum(double min)
 {
   Q_D(ctkRangeWidget);

+ 3 - 0
Libs/Widgets/ctkRangeWidget.h

@@ -86,6 +86,9 @@ public:
   /// Description
   /// Utility function that set the min/max in once
   void setRange(double min, double max);
+  /// Description
+  /// Return the range of the slider
+  void range(double* range)const;
 
   ///
   /// This property holds the slider and spinbox minimum value.