|
@@ -0,0 +1,255 @@
|
|
|
+/*=========================================================================
|
|
|
+
|
|
|
+ Library: CTK
|
|
|
+
|
|
|
+ Copyright (c) 2010 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 <QColor>
|
|
|
+#include <QDebug>
|
|
|
+
|
|
|
+/// CTK includes
|
|
|
+#include "ctkVTKPiecewiseFunction.h"
|
|
|
+
|
|
|
+/// VTK includes
|
|
|
+#include <vtkPiecewiseFunction.h>
|
|
|
+#include <vtkSmartPointer.h>
|
|
|
+
|
|
|
+class ctkVTKPiecewiseFunctionPrivate: public ctkPrivate<ctkVTKPiecewiseFunction>
|
|
|
+{
|
|
|
+public:
|
|
|
+ vtkSmartPointer<vtkPiecewiseFunction> PiecewiseFunction;
|
|
|
+};
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+ctkVTKPiecewiseFunction::ctkVTKPiecewiseFunction(vtkPiecewiseFunction* piecewiseFunction,
|
|
|
+ QObject* parentObject)
|
|
|
+ :ctkTransferFunction(parentObject)
|
|
|
+{
|
|
|
+ CTK_INIT_PRIVATE(ctkVTKPiecewiseFunction);
|
|
|
+ this->setPiecewiseFunction(piecewiseFunction);
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+ctkVTKPiecewiseFunction::~ctkVTKPiecewiseFunction()
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+int ctkVTKPiecewiseFunction::count()const
|
|
|
+{
|
|
|
+ CTK_D(const ctkVTKPiecewiseFunction);
|
|
|
+ if (d->PiecewiseFunction.GetPointer() == 0)
|
|
|
+ {
|
|
|
+ Q_ASSERT(d->PiecewiseFunction.GetPointer());
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ return d->PiecewiseFunction->GetSize();
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+void ctkVTKPiecewiseFunction::range(qreal& minRange, qreal& maxRange)const
|
|
|
+{
|
|
|
+ CTK_D(const ctkVTKPiecewiseFunction);
|
|
|
+ if (d->PiecewiseFunction.GetPointer() == 0)
|
|
|
+ {
|
|
|
+ Q_ASSERT(d->PiecewiseFunction.GetPointer());
|
|
|
+ minRange = 1.;
|
|
|
+ maxRange = 0.;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ double rangeValues[2];
|
|
|
+ d->PiecewiseFunction->GetRange(rangeValues);
|
|
|
+ minRange = rangeValues[0];
|
|
|
+ maxRange = rangeValues[1];
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+QVariant ctkVTKPiecewiseFunction::minValue()const
|
|
|
+{
|
|
|
+ CTK_D(const ctkVTKPiecewiseFunction);
|
|
|
+ if (d->PiecewiseFunction.GetPointer() == 0)
|
|
|
+ {
|
|
|
+ Q_ASSERT(d->PiecewiseFunction.GetPointer());
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ //Initialize to max value
|
|
|
+ /// TODO initialize with max value
|
|
|
+ double minValue = 9999.99;
|
|
|
+ for (int i = 0; i < this->count(); ++i)
|
|
|
+ {
|
|
|
+ double value[4];
|
|
|
+ d->PiecewiseFunction->GetNodeValue(i, value);
|
|
|
+ if ( value[1] < minValue)
|
|
|
+ {
|
|
|
+ minValue = value[1];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return minValue;
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+QVariant ctkVTKPiecewiseFunction::maxValue()const
|
|
|
+{
|
|
|
+ CTK_D(const ctkVTKPiecewiseFunction);
|
|
|
+ if (d->PiecewiseFunction.GetPointer() == 0)
|
|
|
+ {
|
|
|
+ Q_ASSERT(d->PiecewiseFunction.GetPointer());
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ //Initialize to max value
|
|
|
+ /// TODO initialize with max value
|
|
|
+ qreal maxValue = 0.;
|
|
|
+ for (int i = 0; i < this->count(); ++i)
|
|
|
+ {
|
|
|
+ double value[4];
|
|
|
+ d->PiecewiseFunction->GetNodeValue(i, value);
|
|
|
+ if ( maxValue < value[1])
|
|
|
+ {
|
|
|
+ maxValue = value[1];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return maxValue;
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+ctkControlPoint* ctkVTKPiecewiseFunction::controlPoint(int index)const
|
|
|
+{
|
|
|
+ CTK_D(const ctkVTKPiecewiseFunction);
|
|
|
+ Q_ASSERT(index >= 0 && index < this->count());
|
|
|
+
|
|
|
+ double values[4];
|
|
|
+ double* range = d->PiecewiseFunction->GetRange();
|
|
|
+ d->PiecewiseFunction->GetNodeValue(index, values);
|
|
|
+
|
|
|
+ QVariant rangeY[2];
|
|
|
+ rangeY[0] = this->minValue();
|
|
|
+ rangeY[1] = this->maxValue();
|
|
|
+ // rangeYDiff /= rangeY[1].toReal() - rangeY[0].toReal();
|
|
|
+
|
|
|
+
|
|
|
+ Q_ASSERT(values[0] >= range[0] && values[0] <= range [1] && // X
|
|
|
+ values[1] >= rangeY[0].toDouble() && values[1] <= rangeY[1].toDouble() && // Y
|
|
|
+ values[2] >= 0. && values[2] <= 1. && // Midpoint
|
|
|
+ values[3] >= 0. && values[3] <= 1. ); // Sharpness
|
|
|
+
|
|
|
+ if (index + 1 >= this->count())
|
|
|
+ {
|
|
|
+ ctkControlPoint* cp = new ctkControlPoint();
|
|
|
+ cp->P.X = values[0];
|
|
|
+ cp->P.Value = values[1];
|
|
|
+ return cp;
|
|
|
+ }
|
|
|
+ ctkNonLinearControlPoint* cp = new ctkNonLinearControlPoint();
|
|
|
+ cp->P.X = values[0];
|
|
|
+ cp->P.Value = values[1];
|
|
|
+ d->PiecewiseFunction->GetNodeValue(index + 1, values);
|
|
|
+
|
|
|
+
|
|
|
+ Q_ASSERT(values[0] >= range[0] && values[0] <= range[1] && // X
|
|
|
+ values[1] >= rangeY[0].toDouble() && values[1] <= rangeY[1].toDouble() && // Y
|
|
|
+ values[2] >= 0. && values[2] <= 1. && // Midpoint
|
|
|
+ values[3] >= 0. && values[3] <= 1. ); // Sharpness
|
|
|
+
|
|
|
+ double subPoints[30];
|
|
|
+ d->PiecewiseFunction->GetTable(cp->x(), values[0], 10, subPoints);
|
|
|
+ qreal interval = (values[0] - cp->x()) / 9.;
|
|
|
+
|
|
|
+ // subPoints[i] since value varies (not like in color transfer function widget)
|
|
|
+ for(int i = 0; i < 10; ++i)
|
|
|
+ {
|
|
|
+ cp->SubPoints << ctkPoint(cp->x() + interval*i, subPoints[i]);
|
|
|
+ }
|
|
|
+ return cp;
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+QVariant ctkVTKPiecewiseFunction::value(qreal pos)const
|
|
|
+{
|
|
|
+ CTK_D(const ctkVTKPiecewiseFunction);
|
|
|
+ Q_ASSERT(d->PiecewiseFunction.GetPointer());
|
|
|
+ qreal value;
|
|
|
+ // get value for given x
|
|
|
+ value = d->PiecewiseFunction->GetValue( pos );
|
|
|
+ return value;
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+int ctkVTKPiecewiseFunction::insertControlPoint(const ctkControlPoint& cp)
|
|
|
+{
|
|
|
+ CTK_D(ctkVTKPiecewiseFunction);
|
|
|
+ int index = -1;
|
|
|
+ if (d->PiecewiseFunction.GetPointer() == 0)
|
|
|
+ {
|
|
|
+ return index;
|
|
|
+ }
|
|
|
+ qreal value = cp.value().value<qreal>();
|
|
|
+ const ctkNonLinearControlPoint* nonLinearCp = dynamic_cast<const ctkNonLinearControlPoint*>(&cp);
|
|
|
+ if (nonLinearCp)
|
|
|
+ {
|
|
|
+ // TODO retrieve midpoint & sharpness
|
|
|
+ index = d->PiecewiseFunction->AddPoint(
|
|
|
+ cp.x(), value);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ index = d->PiecewiseFunction->AddPoint(
|
|
|
+ cp.x(), value);
|
|
|
+ }
|
|
|
+ return index;
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+void ctkVTKPiecewiseFunction::setControlPointPos(int index, qreal pos)
|
|
|
+{
|
|
|
+ CTK_D(ctkVTKPiecewiseFunction);
|
|
|
+ double values[4];
|
|
|
+ d->PiecewiseFunction->GetNodeValue(index, values);
|
|
|
+ // warning, a possible new range is not supported
|
|
|
+ // SetNodeValue eventually fire the signal changed()
|
|
|
+ values[0] = pos;
|
|
|
+ d->PiecewiseFunction->SetNodeValue(index, values);
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+void ctkVTKPiecewiseFunction::setControlPointValue(int index, const QVariant& value)
|
|
|
+{
|
|
|
+ CTK_D(ctkVTKPiecewiseFunction);
|
|
|
+ Q_ASSERT(value.value<QColor>().isValid());
|
|
|
+ QColor rgb = value.value<QColor>();
|
|
|
+ double values[4];
|
|
|
+ d->PiecewiseFunction->GetNodeValue(index, values);
|
|
|
+ // setNodeValue should eventually fired the signal changed()
|
|
|
+ d->PiecewiseFunction->SetNodeValue(index, values);
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+void ctkVTKPiecewiseFunction::setPiecewiseFunction(vtkPiecewiseFunction* piecewiseFunction)
|
|
|
+{
|
|
|
+ CTK_D(ctkVTKPiecewiseFunction);
|
|
|
+ d->PiecewiseFunction = piecewiseFunction;
|
|
|
+ this->qvtkReconnect(d->PiecewiseFunction,vtkCommand::ModifiedEvent,
|
|
|
+ this, SIGNAL(changed()));
|
|
|
+ emit changed();
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+vtkPiecewiseFunction* ctkVTKPiecewiseFunction::piecewiseFunction()const
|
|
|
+{
|
|
|
+ CTK_D(const ctkVTKPiecewiseFunction);
|
|
|
+ return d->PiecewiseFunction;
|
|
|
+}
|