ctkVTKPiecewiseFunction.cpp

Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Library:   CTK
00004 
00005   Copyright (c) 2010  Kitware Inc.
00006 
00007   Licensed under the Apache License, Version 2.0 (the "License");
00008   you may not use this file except in compliance with the License.
00009   You may obtain a copy of the License at
00010 
00011       http://www.commontk.org/LICENSE
00012 
00013   Unless required by applicable law or agreed to in writing, software
00014   distributed under the License is distributed on an "AS IS" BASIS,
00015   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016   See the License for the specific language governing permissions and
00017   limitations under the License.
00018 
00019 =========================================================================*/
00020 
00022 #include <QColor>
00023 #include <QDebug>
00024 
00026 #include "ctkVTKPiecewiseFunction.h"
00027 
00029 #include <vtkPiecewiseFunction.h>
00030 #include <vtkSmartPointer.h>
00031 
00032 class ctkVTKPiecewiseFunctionPrivate: public ctkPrivate<ctkVTKPiecewiseFunction>
00033 {
00034 public:
00035   vtkSmartPointer<vtkPiecewiseFunction> PiecewiseFunction;
00036 };
00037 
00038 //-----------------------------------------------------------------------------
00039 ctkVTKPiecewiseFunction::ctkVTKPiecewiseFunction(vtkPiecewiseFunction* piecewiseFunction,
00040                                                          QObject* parentObject)
00041   :ctkTransferFunction(parentObject)
00042 {
00043   CTK_INIT_PRIVATE(ctkVTKPiecewiseFunction);
00044   this->setPiecewiseFunction(piecewiseFunction);
00045 }
00046 
00047 //-----------------------------------------------------------------------------
00048 ctkVTKPiecewiseFunction::~ctkVTKPiecewiseFunction()
00049 {
00050 }
00051 
00052 //-----------------------------------------------------------------------------
00053 int ctkVTKPiecewiseFunction::count()const
00054 {
00055   CTK_D(const ctkVTKPiecewiseFunction);
00056   if (d->PiecewiseFunction.GetPointer() == 0)
00057     {
00058     Q_ASSERT(d->PiecewiseFunction.GetPointer());
00059     return -1;
00060     }
00061   return d->PiecewiseFunction->GetSize();
00062 }
00063 
00064 //-----------------------------------------------------------------------------
00065 bool ctkVTKPiecewiseFunction::isDiscrete()const
00066 {
00067   return false;
00068 }
00069 
00070 //-----------------------------------------------------------------------------
00071 bool ctkVTKPiecewiseFunction::isEditable()const
00072 {
00073   return true;
00074 }
00075 
00076 //-----------------------------------------------------------------------------
00077 void ctkVTKPiecewiseFunction::range(qreal& minRange, qreal& maxRange)const
00078 {
00079   CTK_D(const ctkVTKPiecewiseFunction);
00080   if (d->PiecewiseFunction.GetPointer() == 0)
00081     {
00082     Q_ASSERT(d->PiecewiseFunction.GetPointer());
00083     minRange = 1.;
00084     maxRange = 0.;
00085     return;
00086     }
00087   double rangeValues[2];
00088   d->PiecewiseFunction->GetRange(rangeValues);
00089   minRange = rangeValues[0];
00090   maxRange = rangeValues[1];
00091 }
00092 
00093 //-----------------------------------------------------------------------------
00094 QVariant ctkVTKPiecewiseFunction::minValue()const
00095 {
00096   CTK_D(const ctkVTKPiecewiseFunction);
00097   if (d->PiecewiseFunction.GetPointer() == 0)
00098     {
00099     Q_ASSERT(d->PiecewiseFunction.GetPointer());
00100     return -1;
00101     }
00102   //Initialize to max value
00104   double minValue = VTK_DOUBLE_MAX;
00105   for (int i = 0; i < this->count(); ++i)
00106     {
00107     double value[4];
00108     d->PiecewiseFunction->GetNodeValue(i, value);
00109     minValue = qMin(value[1], minValue);
00110     }
00111   return minValue;
00112 }
00113 
00114 //-----------------------------------------------------------------------------
00115 QVariant ctkVTKPiecewiseFunction::maxValue()const
00116 {
00117   CTK_D(const ctkVTKPiecewiseFunction);
00118   if (d->PiecewiseFunction.GetPointer() == 0)
00119     {
00120     Q_ASSERT(d->PiecewiseFunction.GetPointer());
00121     return -1;
00122     }
00123   //Initialize to max value
00125   qreal maxValue = VTK_DOUBLE_MIN;
00126   for (int i = 0; i < this->count(); ++i)
00127     {
00128     double value[4];
00129     d->PiecewiseFunction->GetNodeValue(i, value);
00130     maxValue = qMax(maxValue, value[1]);
00131     }
00132   return maxValue;
00133 }
00134 
00135 //-----------------------------------------------------------------------------
00136 ctkControlPoint* ctkVTKPiecewiseFunction::controlPoint(int index)const
00137 {
00138   CTK_D(const ctkVTKPiecewiseFunction);
00139   Q_ASSERT(index >= 0 && index < this->count());
00140 
00141   double values[4];
00142   double* range = d->PiecewiseFunction->GetRange();
00143   d->PiecewiseFunction->GetNodeValue(index, values);
00144 
00145   QVariant rangeY[2];
00146   rangeY[0] = this->minValue();
00147   rangeY[1] = this->maxValue();
00148   //    rangeYDiff /= rangeY[1].toReal() - rangeY[0].toReal();
00149 
00150 
00151   Q_ASSERT(values[0] >= range[0] && values[0] <= range [1] &&  // X
00152            values[1] >= rangeY[0].toDouble() && values[1] <= rangeY[1].toDouble()  &&  // Y
00153            values[2] >= 0. && values[2] <= 1. &&                // Midpoint
00154            values[3] >= 0. && values[3] <= 1. );                // Sharpness
00155 
00156   if (index + 1 >= this->count())
00157     {
00158     ctkControlPoint* cp = new ctkControlPoint();
00159     cp->P.X = values[0];
00160     cp->P.Value = values[1];
00161     return cp;
00162     }
00163   ctkNonLinearControlPoint* cp = new ctkNonLinearControlPoint();
00164   cp->P.X = values[0];
00165   cp->P.Value = values[1];
00166   // Optimization: don't use Subpoints if sharpness == 0
00167   if (values[3] == 0.)
00168     {
00169     cp->SubPoints << ctkPoint(values[0], values[1]);
00170     } 
00171   double nextValues[4];
00172   d->PiecewiseFunction->GetNodeValue(index + 1, nextValues);
00173 
00174   Q_ASSERT(nextValues[0] >= range[0] && nextValues[0] <= range[1]  &&  // X
00175            nextValues[1] >= rangeY[0].toDouble() && nextValues[1] <= rangeY[1].toDouble()  &&  // Y
00176            nextValues[2] >= 0. && nextValues[2] <= 1. &&                // Midpoint
00177            nextValues[3] >= 0. && nextValues[3] <= 1. );                // Sharpness
00178   // Optimization: Don't use Subpoints if sharpness == 0
00179   if (values[3] == 0.)
00180     {
00181     cp->SubPoints << ctkPoint(nextValues[0], nextValues[1]);
00182     return cp;
00183     }
00184   double subPoints[100];
00185   d->PiecewiseFunction->GetTable(cp->x(), nextValues[0], 100, subPoints);
00186   qreal interval = (nextValues[0] - cp->x()) / 99.;
00187 
00188   // subPoints[i] since value varies (not like in color transfer function widget)
00189   for(int i = 0; i < 100; ++i)
00190     {
00191     cp->SubPoints << ctkPoint(cp->x() + interval*i, subPoints[i]);
00192     }
00193   return cp;
00194 }
00195 
00196 //-----------------------------------------------------------------------------
00197 QVariant ctkVTKPiecewiseFunction::value(qreal pos)const
00198 {
00199   CTK_D(const ctkVTKPiecewiseFunction);
00200   Q_ASSERT(d->PiecewiseFunction.GetPointer());
00201   qreal value;
00202   // get value for given x
00203   value = d->PiecewiseFunction->GetValue( pos );
00204   return value;
00205 }
00206 
00207 //-----------------------------------------------------------------------------
00208 int ctkVTKPiecewiseFunction::insertControlPoint(const ctkControlPoint& cp)
00209 {
00210   CTK_D(ctkVTKPiecewiseFunction);
00211   int index = -1;
00212   if (d->PiecewiseFunction.GetPointer() == 0)
00213     {
00214     return index;
00215     }
00216   qreal value = cp.value().value<qreal>();
00217   const ctkNonLinearControlPoint* nonLinearCp = dynamic_cast<const ctkNonLinearControlPoint*>(&cp);
00218   if (nonLinearCp)
00219     {
00220     // TODO retrieve midpoint & sharpness
00221     index = d->PiecewiseFunction->AddPoint(
00222       cp.x(), value);
00223     }
00224   else
00225     {
00226     index = d->PiecewiseFunction->AddPoint(
00227       cp.x(), value);
00228     }
00229   return index;
00230 }
00231 //-----------------------------------------------------------------------------
00232 // insert point with value = 0
00233 int ctkVTKPiecewiseFunction::insertControlPoint(qreal pos)
00234 {
00235   CTK_D(ctkVTKPiecewiseFunction);
00236   int index = -1;
00237   if (d->PiecewiseFunction.GetPointer() == 0)
00238     {
00239     return index;
00240     }
00241   index = d->PiecewiseFunction->AddPoint( pos, 0);
00242   qDebug() << "index of new point: " << index;
00243   return index;
00244 }
00245 
00246 //-----------------------------------------------------------------------------
00247 void ctkVTKPiecewiseFunction::setControlPointPos(int index, qreal pos)
00248 {
00249   CTK_D(ctkVTKPiecewiseFunction);
00250   double values[4];
00251   d->PiecewiseFunction->GetNodeValue(index, values);
00252   // warning, a possible new range is not supported
00253   // SetNodeValue eventually fire the signal changed()
00254   values[0] = pos;
00255   d->PiecewiseFunction->SetNodeValue(index, values);
00256 }
00257 
00258 //-----------------------------------------------------------------------------
00259 void ctkVTKPiecewiseFunction::setControlPointValue(int index, const QVariant& value)
00260 {
00261   CTK_D(ctkVTKPiecewiseFunction);
00262   double values[4];
00263   d->PiecewiseFunction->GetNodeValue(index, values);
00264   qDebug() << "old value: " << values[1];
00265   values[1] = value.toDouble();
00266   qDebug() << "new value: " << values[1];
00267   // setNodeValue should eventually fired the signal changed()
00268   d->PiecewiseFunction->SetNodeValue(index, values);
00269 }
00270 
00271 //-----------------------------------------------------------------------------
00272 void ctkVTKPiecewiseFunction::setPiecewiseFunction(vtkPiecewiseFunction* piecewiseFunction)
00273 {
00274   CTK_D(ctkVTKPiecewiseFunction);
00275   d->PiecewiseFunction = piecewiseFunction;
00276   this->qvtkReconnect(d->PiecewiseFunction,vtkCommand::ModifiedEvent,
00277                       this, SIGNAL(changed()));
00278   emit changed();
00279 }
00280 
00281 //-----------------------------------------------------------------------------
00282 vtkPiecewiseFunction* ctkVTKPiecewiseFunction::piecewiseFunction()const
00283 {
00284   CTK_D(const ctkVTKPiecewiseFunction);
00285   return d->PiecewiseFunction;
00286 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated on 21 May 2010 for CTK by  doxygen 1.6.1