Browse Source

Allow user to set/reset the range in ctkVTKHistogram

Previously, the range was tied to the data array range. Now with the new
method, the user can change the range of the histogram easily.
When the range is changed, the histogram will be recomputed if the number
of bins changes.
Johan Andruejol 9 years ago
parent
commit
b21c94b894

+ 12 - 2
Libs/Visualization/VTK/Widgets/Testing/Cpp/ctkVTKHistogramTest2.cpp

@@ -32,6 +32,9 @@ int ctkVTKHistogramTest2( int argc, char * argv [])
   rgbDataArray->InsertNextTuple3(1000, 143, -1412);
   rgbDataArray->InsertNextTuple3(-543, 210,   151);
   rgbDataArray->InsertNextTuple3(  -1, 210,    10);
+
+  // Generate histogram on the Green values
+  rgbHistogram.setComponent(1);
   rgbHistogram.setDataArray(rgbDataArray);
   if (rgbHistogram.dataArray() != rgbDataArray)
     {
@@ -41,8 +44,15 @@ int ctkVTKHistogramTest2( int argc, char * argv [])
     return EXIT_FAILURE;
     }
 
-  // Generate histogram on the Green values
-  rgbHistogram.setComponent(1);
+  double range[2], expectedRange[2] = {50.0, 211.0};
+  rgbHistogram.range(range[0], range[1]);
+  if (range[0] != expectedRange[0] && range[1] != expectedRange[1])
+    {
+    std::cerr << "Bad range: " << range[0] << " " << range[1] << std::endl
+              << " expected: " << expectedRange[0] << " " << expectedRange[1]
+              << std::endl;
+    return EXIT_FAILURE;
+    }
 
   //------Test build---------------------------------
   rgbHistogram.build();

+ 72 - 27
Libs/Visualization/VTK/Widgets/ctkVTKHistogram.cpp

@@ -73,27 +73,7 @@ int ctkVTKHistogramPrivate::computeNumberOfBins()const
     {
     return -1;
     }
-  
-  if (this->DataArray->GetDataType() == VTK_CHAR ||
-      this->DataArray->GetDataType() == VTK_SIGNED_CHAR ||
-      this->DataArray->GetDataType() == VTK_UNSIGNED_CHAR)
-    {
-    this->Range[0] = this->DataArray->GetDataTypeMin();
-    this->Range[1] = this->DataArray->GetDataTypeMax();
-    }
-  else
-    {
-    this->DataArray->GetRange(this->Range, this->Component);
-    if (this->DataArray->GetDataType() == VTK_FLOAT ||
-        this->DataArray->GetDataType() == VTK_DOUBLE)
-      {
-      this->Range[1] += 0.01;
-      }
-    //else
-    //  {
-    //  this->Range[1] += 1;
-    //  }
-    }
+
   if (this->UserNumberOfBins > 0)
     {
     return this->UserNumberOfBins;
@@ -131,26 +111,85 @@ int ctkVTKHistogram::count()const
 }
 
 //-----------------------------------------------------------------------------
-void ctkVTKHistogram::range(qreal& minRange, qreal& maxRange)const
+void ctkVTKHistogram::setRange(qreal minRange, qreal maxRange)
 {
   Q_D(const ctkVTKHistogram);
   if (d->DataArray.GetPointer() == 0)
     {
     //Q_ASSERT(d->DataArray.GetPointer());
-    logger.warn("no dataArray");
+    logger.warn("no data array. range will be reset when setting array.");
     minRange = 1.; // set incorrect values
     maxRange = 0.;
     return;
     }
-  if (d->Range[0] == d->Range[1])
+  if (minRange >= maxRange)
+    {
+    //Q_ASSERT(d->DataArray.GetPointer());
+    logger.warn("minRange >= maxRange");
+    qreal pivot = minRange;
+    minRange = maxRange;
+    maxRange = pivot;
+    }
+
+  int numberOfBinsBefore = d->computeNumberOfBins();
+  d->Range[0] = minRange;
+  d->Range[1] = maxRange;
+  if (d->computeNumberOfBins() != numberOfBinsBefore)
     {
-    minRange = d->DataArray->GetDataTypeMin();
-    maxRange = d->DataArray->GetDataTypeMax();
+    this->build();
+    }
+}
+
+//-----------------------------------------------------------------------------
+void ctkVTKHistogram::range(qreal& minRange, qreal& maxRange)const
+{
+  Q_D(const ctkVTKHistogram);
+  if (d->DataArray.GetPointer() == 0)
+    {
+    //Q_ASSERT(d->DataArray.GetPointer());
+    logger.warn("no dataArray");
+    minRange = 1.; // set incorrect values
+    maxRange = 0.;
     return;
     }
   minRange = d->Range[0];
   maxRange = d->Range[1];
-} 
+}
+
+//-----------------------------------------------------------------------------
+void ctkVTKHistogram::resetRange()
+{
+  Q_D(ctkVTKHistogram);
+  if (d->DataArray.GetPointer() == 0)
+    {
+    //Q_ASSERT(d->DataArray.GetPointer());
+    logger.warn("no dataArray");
+    d->Range[0] = 1.; // set incorrect values
+    d->Range[1] = 0.;
+    return;
+    }
+
+  if (d->DataArray->GetDataType() == VTK_CHAR ||
+      d->DataArray->GetDataType() == VTK_SIGNED_CHAR ||
+      d->DataArray->GetDataType() == VTK_UNSIGNED_CHAR)
+    {
+    d->Range[0] = d->DataArray->GetDataTypeMin();
+    d->Range[1] = d->DataArray->GetDataTypeMax();
+    }
+  else
+    {
+    d->DataArray->GetRange(d->Range, d->Component);
+    if (d->DataArray->GetDataType() == VTK_FLOAT ||
+        d->DataArray->GetDataType() == VTK_DOUBLE)
+      {
+      d->Range[1] += 0.01;
+      }
+    //else
+    //  {
+    //  this->Range[1] += 1;
+    //  }
+    }
+}
 
 //-----------------------------------------------------------------------------
 QVariant ctkVTKHistogram::minValue()const
@@ -203,7 +242,13 @@ int ctkVTKHistogram::posToIndex(qreal pos)const
 void ctkVTKHistogram::setDataArray(vtkDataArray* newDataArray)
 {
   Q_D(ctkVTKHistogram);
+  if (newDataArray == d->DataArray)
+    {
+    return;
+    }
+
   d->DataArray = newDataArray;
+  this->resetRange();
   this->qvtkReconnect(d->DataArray,vtkCommand::ModifiedEvent,
                       this, SIGNAL(changed()));
   emit changed();

+ 10 - 1
Libs/Visualization/VTK/Widgets/ctkVTKHistogram.h

@@ -52,8 +52,15 @@ public:
   /// Returns the number of bins. Returns 0 until build() is called.
   virtual int count()const;
 
-  /// Please note that range only works if you have at least set an array.
+  // Set/Get the range of the histogram.
+  // Please note that after an array is set, the range will be reset.
+  // \sa resetRange()
+  virtual void setRange(qreal minRang, qreal maxRange);
   virtual void range(qreal& minRange, qreal& maxRange)const;
+
+  // Reset the range to the array's range.
+  virtual void resetRange();
+
   virtual QVariant minValue()const;
   virtual QVariant maxValue()const;
 
@@ -63,6 +70,8 @@ public:
   void setComponent(int component);
   int component()const;
 
+  // Set the number of bins to use in the histogram. If this is set,
+  // the range will be ignored.
   int numberOfBins()const;
   void setNumberOfBins(int number);