Kaynağa Gözat

ENH: Better chart bound and extent handling

- Added function to set chart extent (i.e. axis range) in ctkVTKChartView and ctkVTKVolumePropertyWidget
- Removed unnecessary update call from ctkVTKScalarsToColorsView::onBoundsChanged. It caused a reset of extent, which is undesired when only the transfer function is being shifted. This should not cause issues as the bounds already cover the data range, so the extent can be set to whatever needed, and at the same time it does not override what the user set
- Added python compatibility functions to ctkVTKVolumePropertyWidget
Csaba Pinter 7 yıl önce
ebeveyn
işleme
dfa9fabbc7

+ 43 - 33
Libs/Visualization/VTK/Widgets/ctkVTKChartView.cpp

@@ -110,6 +110,10 @@ void ctkVTKChartViewPrivate::init()
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 void ctkVTKChartViewPrivate::chartBounds(double* bounds)const
 void ctkVTKChartViewPrivate::chartBounds(double* bounds)const
 {
 {
+  if (!bounds)
+    {
+    return;
+    }
   Q_Q(const ctkVTKChartView);
   Q_Q(const ctkVTKChartView);
   bounds[0] = bounds[2] = bounds[4] = bounds[6] = VTK_DOUBLE_MAX;
   bounds[0] = bounds[2] = bounds[4] = bounds[6] = VTK_DOUBLE_MAX;
   bounds[1] = bounds[3] = bounds[5] = bounds[7] = VTK_DOUBLE_MIN;
   bounds[1] = bounds[3] = bounds[5] = bounds[7] = VTK_DOUBLE_MIN;
@@ -127,54 +131,38 @@ void ctkVTKChartViewPrivate::chartBounds(double* bounds)const
       // bottom left
       // bottom left
       case 0:
       case 0:
         // x
         // x
-        bounds[2] = bounds[2] > plotBounds[0] ?
-          plotBounds[0] : bounds[2];
-        bounds[3] = bounds[3] < plotBounds[1] ?
-          plotBounds[1] : bounds[3];
+        bounds[2] = bounds[2] > plotBounds[0] ? plotBounds[0] : bounds[2];
+        bounds[3] = bounds[3] < plotBounds[1] ? plotBounds[1] : bounds[3];
         // y
         // y
-        bounds[0] = bounds[0] > plotBounds[2] ?
-          plotBounds[2] : bounds[0];
-        bounds[1] = bounds[1] < plotBounds[3] ?
-          plotBounds[3] : bounds[1];
+        bounds[0] = bounds[0] > plotBounds[2] ? plotBounds[2] : bounds[0];
+        bounds[1] = bounds[1] < plotBounds[3] ? plotBounds[3] : bounds[1];
         break;
         break;
       // bottom right
       // bottom right
       case 1:
       case 1:
         // x
         // x
-        bounds[2] = bounds[2] > plotBounds[0] ?
-          plotBounds[0] : bounds[2];
-        bounds[3] = bounds[3] < plotBounds[1] ?
-          plotBounds[1] : bounds[3];
+        bounds[2] = bounds[2] > plotBounds[0] ? plotBounds[0] : bounds[2];
+        bounds[3] = bounds[3] < plotBounds[1] ? plotBounds[1] : bounds[3];
         // y
         // y
-        bounds[4] = bounds[4] > plotBounds[2] ?
-          plotBounds[2] : bounds[4];
-        bounds[5] = bounds[5] < plotBounds[3] ?
-          plotBounds[3] : bounds[5];
+        bounds[4] = bounds[4] > plotBounds[2] ? plotBounds[2] : bounds[4];
+        bounds[5] = bounds[5] < plotBounds[3] ? plotBounds[3] : bounds[5];
         break;
         break;
       // top right
       // top right
       case 2:
       case 2:
         // x
         // x
-        bounds[6] = bounds[6] > plotBounds[0] ?
-          plotBounds[0] : bounds[6];
-        bounds[7] = bounds[7] < plotBounds[1] ?
-          plotBounds[1] : bounds[7];
+        bounds[6] = bounds[6] > plotBounds[0] ? plotBounds[0] : bounds[6];
+        bounds[7] = bounds[7] < plotBounds[1] ? plotBounds[1] : bounds[7];
         // y
         // y
-        bounds[4] = bounds[4] > plotBounds[2] ?
-          plotBounds[2] : bounds[4];
-        bounds[5] = bounds[5] < plotBounds[3] ?
-          plotBounds[3] : bounds[5];
+        bounds[4] = bounds[4] > plotBounds[2] ? plotBounds[2] : bounds[4];
+        bounds[5] = bounds[5] < plotBounds[3] ? plotBounds[3] : bounds[5];
         break;
         break;
       // top left
       // top left
       case 3:
       case 3:
         // x
         // x
-        bounds[6] = bounds[6] > plotBounds[0] ?
-          plotBounds[0] : bounds[6];
-        bounds[7] = bounds[7] < plotBounds[1] ?
-          plotBounds[1] : bounds[7];
+        bounds[6] = bounds[6] > plotBounds[0] ? plotBounds[0] : bounds[6];
+        bounds[7] = bounds[7] < plotBounds[1] ? plotBounds[1] : bounds[7];
         // y
         // y
-        bounds[0] = bounds[0] > plotBounds[2] ?
-          plotBounds[2] : bounds[1];
-        bounds[1] = bounds[0] < plotBounds[3] ?
-          plotBounds[3] : bounds[1];
+        bounds[0] = bounds[0] > plotBounds[2] ? plotBounds[2] : bounds[1];
+        bounds[1] = bounds[0] < plotBounds[3] ? plotBounds[3] : bounds[1];
         break;
         break;
       }
       }
     }
     }
@@ -295,10 +283,13 @@ void ctkVTKChartView::onChartUpdated()
     }
     }
 }
 }
 
 
-
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 void ctkVTKChartView::chartExtent(double* extent)const
 void ctkVTKChartView::chartExtent(double* extent)const
 {
 {
+  if (!extent)
+    {
+    return;
+    }
   extent[0] = extent[2] = extent[4] = extent[6] = VTK_DOUBLE_MAX;
   extent[0] = extent[2] = extent[4] = extent[6] = VTK_DOUBLE_MAX;
   extent[1] = extent[3] = extent[5] = extent[7] = VTK_DOUBLE_MIN;
   extent[1] = extent[3] = extent[5] = extent[7] = VTK_DOUBLE_MIN;
   vtkChartXY* chart = this->chart();
   vtkChartXY* chart = this->chart();
@@ -317,6 +308,25 @@ void ctkVTKChartView::chartExtent(double* extent)const
 }
 }
 
 
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
+void ctkVTKChartView::setChartUserExtent(double* userExtent)
+{
+  if (!userExtent)
+    {
+    qCritical() << Q_FUNC_INFO << ": Invalid user extent";
+    return;
+    }
+  vtkChartXY* chart = this->chart();
+  vtkAxis* axis = chart->GetAxis(vtkAxis::BOTTOM);
+  axis->SetRange(userExtent[0], userExtent[1]);
+  axis = chart->GetAxis(vtkAxis::LEFT);
+  axis->SetRange(userExtent[2], userExtent[3]);
+  axis = chart->GetAxis(vtkAxis::TOP);
+  axis->SetRange(userExtent[4], userExtent[5]);
+  axis = chart->GetAxis(vtkAxis::RIGHT);
+  axis->SetRange(userExtent[6], userExtent[7]);
+}
+
+// ----------------------------------------------------------------------------
 void ctkVTKChartView::chartBounds(double* bounds)const
 void ctkVTKChartView::chartBounds(double* bounds)const
 {
 {
   Q_D(const ctkVTKChartView);
   Q_D(const ctkVTKChartView);

+ 1 - 0
Libs/Visualization/VTK/Widgets/ctkVTKChartView.h

@@ -83,6 +83,7 @@ public:
   /// The current extent is the visible area on the chart.
   /// The current extent is the visible area on the chart.
   /// it is equivalent to the Minimum/Maximum of the axes
   /// it is equivalent to the Minimum/Maximum of the axes
   void chartExtent(double bounds[8])const;
   void chartExtent(double bounds[8])const;
+  void setChartUserExtent(double* userExtent);
 
 
   /// Return the chart bounds for the 4 chart axes.
   /// Return the chart bounds for the 4 chart axes.
   /// bounds must be an array of 8 doubles.
   /// bounds must be an array of 8 doubles.

+ 0 - 1
Libs/Visualization/VTK/Widgets/ctkVTKScalarsToColorsView.cpp

@@ -139,7 +139,6 @@ void ctkVTKScalarsToColorsView::addPlot(vtkPlot* plot)
 void ctkVTKScalarsToColorsView::onBoundsChanged()
 void ctkVTKScalarsToColorsView::onBoundsChanged()
 {
 {
   this->boundAxesToChartBounds();
   this->boundAxesToChartBounds();
-  this->setAxesToChartBounds();
   this->Superclass::onChartUpdated();
   this->Superclass::onChartUpdated();
 }
 }
 
 

+ 80 - 24
Libs/Visualization/VTK/Widgets/ctkVTKVolumePropertyWidget.cpp

@@ -260,16 +260,11 @@ void ctkVTKVolumePropertyWidget::updateFromVolumeProperty()
     {
     {
     d->InterpolationComboBox->setCurrentIndex(
     d->InterpolationComboBox->setCurrentIndex(
       d->VolumeProperty->GetInterpolationType() == VTK_NEAREST_INTERPOLATION ? 0 : 1);
       d->VolumeProperty->GetInterpolationType() == VTK_NEAREST_INTERPOLATION ? 0 : 1);
-    d->ShadeCheckBox->setChecked(
-      d->VolumeProperty->GetShade(d->CurrentComponent));
-    d->MaterialPropertyWidget->setAmbient(
-      d->VolumeProperty->GetAmbient(d->CurrentComponent));
-    d->MaterialPropertyWidget->setDiffuse(
-      d->VolumeProperty->GetDiffuse(d->CurrentComponent));
-    d->MaterialPropertyWidget->setSpecular(
-      d->VolumeProperty->GetSpecular(d->CurrentComponent));
-    d->MaterialPropertyWidget->setSpecularPower(
-      d->VolumeProperty->GetSpecularPower(d->CurrentComponent));
+    d->ShadeCheckBox->setChecked(d->VolumeProperty->GetShade(d->CurrentComponent));
+    d->MaterialPropertyWidget->setAmbient(d->VolumeProperty->GetAmbient(d->CurrentComponent));
+    d->MaterialPropertyWidget->setDiffuse(d->VolumeProperty->GetDiffuse(d->CurrentComponent));
+    d->MaterialPropertyWidget->setSpecular(d->VolumeProperty->GetSpecular(d->CurrentComponent));
+    d->MaterialPropertyWidget->setSpecularPower(d->VolumeProperty->GetSpecularPower(d->CurrentComponent));
     }
     }
   this->updateRange();
   this->updateRange();
 }
 }
@@ -279,11 +274,13 @@ void ctkVTKVolumePropertyWidget::updateRange()
 {
 {
   Q_D(ctkVTKVolumePropertyWidget);
   Q_D(ctkVTKVolumePropertyWidget);
 
 
-  double range[2];
+  double range[2] = {0.0};
   d->computeRange(range);
   d->computeRange(range);
   d->ScalarOpacityThresholdWidget->setRange(range[0], range[1]);
   d->ScalarOpacityThresholdWidget->setRange(range[0], range[1]);
 
 
-  double chartBounds[8];
+  // Elements: {leftMin, leftMax, bottomMin, bottomMax, rightMin, rightMax, topMin, topMax}
+  // (probably according to vtkAxis::Location)
+  double chartBounds[8] = {0.0};
   d->ScalarOpacityWidget->view()->chartBounds(chartBounds);
   d->ScalarOpacityWidget->view()->chartBounds(chartBounds);
   chartBounds[2] = range[0];
   chartBounds[2] = range[0];
   chartBounds[3] = range[1];
   chartBounds[3] = range[1];
@@ -307,38 +304,97 @@ void ctkVTKVolumePropertyWidget::updateRange()
 void ctkVTKVolumePropertyWidget::chartsBounds(double bounds[4])const
 void ctkVTKVolumePropertyWidget::chartsBounds(double bounds[4])const
 {
 {
   Q_D(const ctkVTKVolumePropertyWidget);
   Q_D(const ctkVTKVolumePropertyWidget);
-  double chartBounds[4];
+
+  double chartBounds[8] = {0.0};
   d->ScalarOpacityWidget->view()->chartBounds(chartBounds);
   d->ScalarOpacityWidget->view()->chartBounds(chartBounds);
   memcpy(bounds, chartBounds, 4*sizeof(double));
   memcpy(bounds, chartBounds, 4*sizeof(double));
+
   d->ScalarColorWidget->view()->chartBounds(chartBounds);
   d->ScalarColorWidget->view()->chartBounds(chartBounds);
   bounds[0] = qMin(bounds[0], chartBounds[0]);
   bounds[0] = qMin(bounds[0], chartBounds[0]);
   bounds[1] = qMax(bounds[1], chartBounds[1]);
   bounds[1] = qMax(bounds[1], chartBounds[1]);
   bounds[2] = qMin(bounds[2], chartBounds[2]);
   bounds[2] = qMin(bounds[2], chartBounds[2]);
   bounds[3] = qMax(bounds[3], chartBounds[3]);
   bounds[3] = qMax(bounds[3], chartBounds[3]);
-  //d->GradientWidget->view()->chartBounds(chartBounds);
-  //bounds[0] = qMin(bounds[0], chartBounds[0]);
-  //bounds[1] = qMax(bounds[1], chartBounds[1]);
-  //bounds[2] = qMin(bounds[2], chartBounds[2]);
-  //bounds[3] = qMax(bounds[3], chartBounds[3]);
+
+  d->GradientWidget->view()->chartBounds(chartBounds);
+  bounds[0] = qMin(bounds[0], chartBounds[0]);
+  bounds[1] = qMax(bounds[1], chartBounds[1]);
+  bounds[2] = qMin(bounds[2], chartBounds[2]);
+  bounds[3] = qMax(bounds[3], chartBounds[3]);
+}
+
+// ----------------------------------------------------------------------------
+QList<double> ctkVTKVolumePropertyWidget::chartsBounds()const
+{
+  double boundsArray[4] = {0.0};
+  this->chartsBounds(boundsArray);
+
+  QList<double> bounds;
+  bounds << boundsArray[0] << boundsArray[1] << boundsArray[2] << boundsArray[3];
+  return bounds;
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKVolumePropertyWidget::setChartsExtent(double extent[2])
+{
+  this->setChartsExtent(extent[0], extent[1]);
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKVolumePropertyWidget::setChartsExtent(double min, double max)
+{
+  Q_D(ctkVTKVolumePropertyWidget);
+
+  double chartExtent[8] = {0.0};
+  d->ScalarOpacityWidget->view()->chartExtent(chartExtent);
+  chartExtent[0] = min;
+  chartExtent[1] = max;
+  d->ScalarOpacityWidget->view()->setChartUserExtent(chartExtent);
+  d->ScalarOpacityWidget->view()->update();
+
+  d->ScalarColorWidget->view()->chartExtent(chartExtent);
+  chartExtent[0] = min;
+  chartExtent[1] = max;
+  d->ScalarColorWidget->view()->setChartUserExtent(chartExtent);
+  d->ScalarColorWidget->view()->update();
+
+  d->GradientWidget->view()->chartExtent(chartExtent);
+  chartExtent[0] = min;
+  chartExtent[1] = max;
+  d->GradientWidget->view()->setChartUserExtent(chartExtent);
+  d->GradientWidget->view()->update();
 }
 }
 
 
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 void ctkVTKVolumePropertyWidget::chartsExtent(double extent[4])const
 void ctkVTKVolumePropertyWidget::chartsExtent(double extent[4])const
 {
 {
   Q_D(const ctkVTKVolumePropertyWidget);
   Q_D(const ctkVTKVolumePropertyWidget);
-  double chartExtent[8];
+
+  double chartExtent[8] = {0.0};
   d->ScalarOpacityWidget->view()->chartExtent(chartExtent);
   d->ScalarOpacityWidget->view()->chartExtent(chartExtent);
   memcpy(extent, chartExtent, 4*sizeof(double));
   memcpy(extent, chartExtent, 4*sizeof(double));
+
   d->ScalarColorWidget->view()->chartExtent(chartExtent);
   d->ScalarColorWidget->view()->chartExtent(chartExtent);
   extent[0] = qMin(extent[0], chartExtent[0]);
   extent[0] = qMin(extent[0], chartExtent[0]);
   extent[1] = qMax(extent[1], chartExtent[1]);
   extent[1] = qMax(extent[1], chartExtent[1]);
   extent[2] = qMin(extent[2], chartExtent[2]);
   extent[2] = qMin(extent[2], chartExtent[2]);
   extent[3] = qMax(extent[3], chartExtent[3]);
   extent[3] = qMax(extent[3], chartExtent[3]);
-  //d->GradientWidget->view()->chartExtent(chartExtent);
-  //extent[0] = qMin(extent[0], chartExtent[0]);
-  //extent[1] = qMin(extent[1], chartExtent[1]);
-  //extent[2] = qMin(extent[2], chartExtent[2]);
-  //extent[3] = qMin(extent[3], chartExtent[3]);
+
+  d->GradientWidget->view()->chartExtent(chartExtent);
+  extent[0] = qMin(extent[0], chartExtent[0]);
+  extent[1] = qMax(extent[1], chartExtent[1]);
+  extent[2] = qMin(extent[2], chartExtent[2]);
+  extent[3] = qMax(extent[3], chartExtent[3]);
+}
+
+// ----------------------------------------------------------------------------
+QList<double> ctkVTKVolumePropertyWidget::chartsExtent()const
+{
+  double extentArray[4] = {0.0};
+  this->chartsExtent(extentArray);
+
+  QList<double> extent;
+  extent << extentArray[0] << extentArray[1] << extentArray[2] << extentArray[3];
+  return extent;
 }
 }
 
 
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------

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

@@ -39,7 +39,7 @@ class CTK_VISUALIZATION_VTK_WIDGETS_EXPORT ctkVTKVolumePropertyWidget
   Q_OBJECT
   Q_OBJECT
   QVTK_OBJECT
   QVTK_OBJECT
   ///
   ///
-  /// Control wether a range slider widget is used to edit the opacity
+  /// Control whether a range slider widget is used to edit the opacity
   /// function instead of a chart editor. False by default
   /// function instead of a chart editor. False by default
   Q_PROPERTY(bool thresholdEnabled READ isThresholdEnabled WRITE setThresholdEnabled NOTIFY thresholdEnabledChanged)
   Q_PROPERTY(bool thresholdEnabled READ isThresholdEnabled WRITE setThresholdEnabled NOTIFY thresholdEnabledChanged)
 
 
@@ -60,7 +60,9 @@ public:
   void setThresholdToggleVisible(bool showToggle);
   void setThresholdToggleVisible(bool showToggle);
 
 
   void chartsBounds(double bounds[4])const;
   void chartsBounds(double bounds[4])const;
+  Q_INVOKABLE QList<double> chartsBounds()const;
   void chartsExtent(double extent[4])const;
   void chartsExtent(double extent[4])const;
+  Q_INVOKABLE QList<double> chartsExtent()const;
 
 
 public Q_SLOTS:
 public Q_SLOTS:
   void setVolumeProperty(vtkVolumeProperty* volumeProperty);
   void setVolumeProperty(vtkVolumeProperty* volumeProperty);
@@ -81,6 +83,10 @@ public Q_SLOTS:
 
 
   void setThresholdEnabled(bool enable);
   void setThresholdEnabled(bool enable);
 
 
+  /// Set chart extent
+  void setChartsExtent(double extent[2]);
+  void setChartsExtent(double min, double max);
+
 Q_SIGNALS:
 Q_SIGNALS:
   void thresholdEnabledChanged(bool enable);
   void thresholdEnabledChanged(bool enable);
   void chartsExtentChanged();
   void chartsExtentChanged();