123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367 |
- /*=========================================================================
- 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.apache.org/licenses/LICENSE-2.0.txt
- 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 <QColor>
- #include <QDebug>
- /// CTK includes
- #include "ctkVTKHistogram.h"
- #include "ctkLogger.h"
- /// VTK includes
- #include <vtkDataArray.h>
- #include <vtkIntArray.h>
- #include <vtkMath.h>
- #include <vtkSmartPointer.h>
- /// STL include
- #include <limits>
- //--------------------------------------------------------------------------
- static ctkLogger logger("org.commontk.libs.visualization.core.ctkVTKHistogram");
- //--------------------------------------------------------------------------
- //-----------------------------------------------------------------------------
- class ctkVTKHistogramPrivate
- {
- public:
- ctkVTKHistogramPrivate();
- vtkSmartPointer<vtkDataArray> DataArray;
- vtkSmartPointer<vtkIntArray> Bins;
- int UserNumberOfBins;
- int Component;
- mutable double Range[2];
- int MinBin;
- int MaxBin;
- int computeNumberOfBins()const;
- };
- //-----------------------------------------------------------------------------
- ctkVTKHistogramPrivate::ctkVTKHistogramPrivate()
- {
- this->Bins = vtkSmartPointer<vtkIntArray>::New();
- this->UserNumberOfBins = -1;
- this->Component = 0;
- this->Range[0] = this->Range[1] = 0.;
- this->MinBin = 0;
- this->MaxBin = 0;
- }
- //-----------------------------------------------------------------------------
- int ctkVTKHistogramPrivate::computeNumberOfBins()const
- {
- if (this->DataArray.GetPointer() == 0)
- {
- 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;
- }
- return static_cast<int>(this->Range[1] - this->Range[0]) + 1;
- }
- //-----------------------------------------------------------------------------
- ctkVTKHistogram::ctkVTKHistogram(QObject* parentObject)
- :ctkHistogram(parentObject)
- , d_ptr(new ctkVTKHistogramPrivate)
- {
- }
- //-----------------------------------------------------------------------------
- ctkVTKHistogram::ctkVTKHistogram(vtkDataArray* dataArray,
- QObject* parentObject)
- :ctkHistogram(parentObject)
- , d_ptr(new ctkVTKHistogramPrivate)
- {
- this->setDataArray(dataArray);
- }
- //-----------------------------------------------------------------------------
- ctkVTKHistogram::~ctkVTKHistogram()
- {
- }
- //-----------------------------------------------------------------------------
- int ctkVTKHistogram::count()const
- {
- Q_D(const ctkVTKHistogram);
- return d->Bins->GetNumberOfTuples();
- }
- //-----------------------------------------------------------------------------
- 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;
- }
- if (d->Range[0] == d->Range[1])
- {
- minRange = d->DataArray->GetDataTypeMin();
- maxRange = d->DataArray->GetDataTypeMax();
- return;
- }
- minRange = d->Range[0];
- maxRange = d->Range[1];
- }
- //-----------------------------------------------------------------------------
- QVariant ctkVTKHistogram::minValue()const
- {
- //Q_D(const ctkVTKHistogram);
- return 0;//d->MinBin;
- }
- //-----------------------------------------------------------------------------
- QVariant ctkVTKHistogram::maxValue()const
- {
- Q_D(const ctkVTKHistogram);
- return d->MaxBin;
- }
- //-----------------------------------------------------------------------------
- ctkControlPoint* ctkVTKHistogram::controlPoint(int index)const
- {
- Q_D(const ctkVTKHistogram);
- ctkHistogramBar* cp = new ctkHistogramBar();
- cp->P.X = this->indexToPos(index);
- cp->P.Value = d->Bins->GetValue(index);
- return cp;
- }
- //-----------------------------------------------------------------------------
- QVariant ctkVTKHistogram::value(qreal pos)const
- {
- QSharedPointer<ctkControlPoint> point(this->controlPoint(this->posToIndex(pos)));
- return point->value();
- }
- //-----------------------------------------------------------------------------
- qreal ctkVTKHistogram::indexToPos(int index)const
- {
- qreal posRange[2];
- this->range(posRange[0], posRange[1]);
- return posRange[0] + index * ((posRange[1] - posRange[0]) / (this->count() - 1));
- }
- //-----------------------------------------------------------------------------
- int ctkVTKHistogram::posToIndex(qreal pos)const
- {
- qreal posRange[2];
- this->range(posRange[0], posRange[1]);
- return (pos - posRange[0]) / ((posRange[1] - posRange[0]) / (this->count() - 1));
- }
- //-----------------------------------------------------------------------------
- void ctkVTKHistogram::setDataArray(vtkDataArray* newDataArray)
- {
- Q_D(ctkVTKHistogram);
- d->DataArray = newDataArray;
- this->qvtkReconnect(d->DataArray,vtkCommand::ModifiedEvent,
- this, SIGNAL(changed()));
- emit changed();
- }
- //-----------------------------------------------------------------------------
- vtkDataArray* ctkVTKHistogram::dataArray()const
- {
- Q_D(const ctkVTKHistogram);
- return d->DataArray;
- }
- //-----------------------------------------------------------------------------
- void ctkVTKHistogram::setComponent(int component)
- {
- Q_D(ctkVTKHistogram);
- d->Component = component;
- // need rebuild
- }
- //-----------------------------------------------------------------------------
- int ctkVTKHistogram::component()const
- {
- Q_D(const ctkVTKHistogram);
- return d->Component;
- }
- //-----------------------------------------------------------------------------
- void ctkVTKHistogram::setNumberOfBins(int number)
- {
- Q_D(ctkVTKHistogram);
- d->UserNumberOfBins = number;
- }
- //-----------------------------------------------------------------------------
- template <class T>
- void populateBins(vtkIntArray* bins, const ctkVTKHistogram* histogram)
- {
- vtkDataArray* scalars = histogram->dataArray();
- int* binsPtr = bins->WritePointer(0, bins->GetNumberOfTuples());
- // reset bins to 0
- memset(binsPtr, 0, bins->GetNumberOfComponents()*bins->GetNumberOfTuples()*sizeof(int));
- const vtkIdType componentNumber = scalars->GetNumberOfComponents();
- const vtkIdType tupleNumber = scalars->GetNumberOfTuples();
- int component = histogram->component();
- double range[2];
- histogram->range(range[0], range[1]);
- T offset = static_cast<T>(range[0]);
- T* ptr = static_cast<T*>(scalars->WriteVoidPointer(0, tupleNumber));
- T* endPtr = ptr + tupleNumber * componentNumber;
- ptr += component;
- for (; ptr < endPtr; ptr += componentNumber)
- {
- Q_ASSERT( (static_cast<long long>(*ptr) - offset) ==
- (static_cast<int>(*ptr) - offset));
- binsPtr[static_cast<int>(*ptr - offset)]++;
- }
- }
- //-----------------------------------------------------------------------------
- template <class T>
- void populateIrregularBins(vtkIntArray* bins, const ctkVTKHistogram* histogram)
- {
- vtkDataArray* scalars = histogram->dataArray();
- int* binsPtr = bins->WritePointer(0, bins->GetNumberOfComponents()*bins->GetNumberOfTuples());
- // reset bins to 0
- memset(binsPtr, 0, bins->GetNumberOfTuples() * sizeof(int));
- const vtkIdType componentNumber = scalars->GetNumberOfComponents();
- const vtkIdType tupleNumber = scalars->GetNumberOfTuples();
- int component = histogram->component();
- double range[2];
- histogram->range(range[0], range[1]);
- double offset = range[0];
- double binWidth = 1.;
- if (range[1] != range[0])
- {
- binWidth = static_cast<double>(bins->GetNumberOfTuples()) / (range[1] - range[0]);
- }
- T* ptr = static_cast<T*>(scalars->WriteVoidPointer(0, tupleNumber));
- T* endPtr = ptr + tupleNumber * componentNumber;
- ptr += component;
- for (; ptr < endPtr; ptr += componentNumber)
- {
- if (std::numeric_limits<T>::has_quiet_NaN &&
- vtkMath::IsNan(*ptr))
- {
- continue;
- }
- binsPtr[vtkMath::Floor((static_cast<double>(*ptr) - offset) * binWidth)]++;
- }
- }
- //-----------------------------------------------------------------------------
- void ctkVTKHistogram::build()
- {
- Q_D(ctkVTKHistogram);
- if (d->DataArray.GetPointer() == 0)
- {
- d->MinBin = 0;
- d->MaxBin = 0;
- d->Bins->SetNumberOfTuples(0);
- return;
- }
- const int binCount = d->computeNumberOfBins();
- d->Bins->SetNumberOfComponents(1);
- d->Bins->SetNumberOfTuples(binCount);
- if (binCount <= 0)
- {
- d->MinBin = 0;
- d->MaxBin = 0;
- return;
- }
- // What is the type of the array, discrete or reals
- if (static_cast<double>(binCount) != (d->Range[1] - d->Range[0] + 1))
- {
- switch(d->DataArray->GetDataType())
- {
- vtkTemplateMacro(populateIrregularBins<VTK_TT>(d->Bins, this));
- }
- }
- else
- {
- switch(d->DataArray->GetDataType())
- {
- vtkTemplateMacro(populateBins<VTK_TT>(d->Bins, this));
- }
- }
- // update Min/Max values
- int* binPtr = d->Bins->GetPointer(0);
- int* endPtr = d->Bins->GetPointer(binCount-1);
- d->MinBin = *endPtr;
- d->MaxBin = *endPtr;
- for (;binPtr < endPtr; ++binPtr)
- {
- d->MinBin = qMin(*binPtr, d->MinBin);
- d->MaxBin = qMax(*binPtr, d->MaxBin);
- }
- emit changed();
- }
- //-----------------------------------------------------------------------------
- void ctkVTKHistogram::removeControlPoint( qreal pos )
- {
- Q_UNUSED(pos);
- // TO BE IMPLEMENTED
- }
|