Просмотр исходного кода

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
Родитель
Сommit
dfa9fabbc7

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

@@ -110,6 +110,10 @@ void ctkVTKChartViewPrivate::init()
 // ----------------------------------------------------------------------------
 void ctkVTKChartViewPrivate::chartBounds(double* bounds)const
 {
+  if (!bounds)
+    {
+    return;
+    }
   Q_Q(const ctkVTKChartView);
   bounds[0] = bounds[2] = bounds[4] = bounds[6] = VTK_DOUBLE_MAX;
   bounds[1] = bounds[3] = bounds[5] = bounds[7] = VTK_DOUBLE_MIN;
@@ -127,54 +131,38 @@ void ctkVTKChartViewPrivate::chartBounds(double* bounds)const
       // bottom left
       case 0:
         // 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
-        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;
       // bottom right
       case 1:
         // 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
-        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;
       // top right
       case 2:
         // 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
-        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;
       // top left
       case 3:
         // 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
-        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;
       }
     }
@@ -295,10 +283,13 @@ void ctkVTKChartView::onChartUpdated()
     }
 }
 
-
 // ----------------------------------------------------------------------------
 void ctkVTKChartView::chartExtent(double* extent)const
 {
+  if (!extent)
+    {
+    return;
+    }
   extent[0] = extent[2] = extent[4] = extent[6] = VTK_DOUBLE_MAX;
   extent[1] = extent[3] = extent[5] = extent[7] = VTK_DOUBLE_MIN;
   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
 {
   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.
   /// it is equivalent to the Minimum/Maximum of the axes
   void chartExtent(double bounds[8])const;
+  void setChartUserExtent(double* userExtent);
 
   /// Return the chart bounds for the 4 chart axes.
   /// 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()
 {
   this->boundAxesToChartBounds();
-  this->setAxesToChartBounds();
   this->Superclass::onChartUpdated();
 }
 

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

@@ -260,16 +260,11 @@ void ctkVTKVolumePropertyWidget::updateFromVolumeProperty()
     {
     d->InterpolationComboBox->setCurrentIndex(
       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();
 }
@@ -279,11 +274,13 @@ void ctkVTKVolumePropertyWidget::updateRange()
 {
   Q_D(ctkVTKVolumePropertyWidget);
 
-  double range[2];
+  double range[2] = {0.0};
   d->computeRange(range);
   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);
   chartBounds[2] = range[0];
   chartBounds[3] = range[1];
@@ -307,38 +304,97 @@ void ctkVTKVolumePropertyWidget::updateRange()
 void ctkVTKVolumePropertyWidget::chartsBounds(double bounds[4])const
 {
   Q_D(const ctkVTKVolumePropertyWidget);
-  double chartBounds[4];
+
+  double chartBounds[8] = {0.0};
   d->ScalarOpacityWidget->view()->chartBounds(chartBounds);
   memcpy(bounds, chartBounds, 4*sizeof(double));
+
   d->ScalarColorWidget->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]);
+
+  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
 {
   Q_D(const ctkVTKVolumePropertyWidget);
-  double chartExtent[8];
+
+  double chartExtent[8] = {0.0};
   d->ScalarOpacityWidget->view()->chartExtent(chartExtent);
   memcpy(extent, chartExtent, 4*sizeof(double));
+
   d->ScalarColorWidget->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]);
-  //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
   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
   Q_PROPERTY(bool thresholdEnabled READ isThresholdEnabled WRITE setThresholdEnabled NOTIFY thresholdEnabledChanged)
 
@@ -60,7 +60,9 @@ public:
   void setThresholdToggleVisible(bool showToggle);
 
   void chartsBounds(double bounds[4])const;
+  Q_INVOKABLE QList<double> chartsBounds()const;
   void chartsExtent(double extent[4])const;
+  Q_INVOKABLE QList<double> chartsExtent()const;
 
 public Q_SLOTS:
   void setVolumeProperty(vtkVolumeProperty* volumeProperty);
@@ -81,6 +83,10 @@ public Q_SLOTS:
 
   void setThresholdEnabled(bool enable);
 
+  /// Set chart extent
+  void setChartsExtent(double extent[2]);
+  void setChartsExtent(double min, double max);
+
 Q_SIGNALS:
   void thresholdEnabledChanged(bool enable);
   void chartsExtentChanged();