ctkVTKCompositeFunction.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 "ctkVTKCompositeFunction.h"
00027 
00029 #include <vtkPiecewiseFunction.h>
00030 #include <vtkColorTransferFunction.h>
00031 #include <vtkSmartPointer.h>
00032 
00033 class ctkVTKCompositeFunctionPrivate: public ctkPrivate<ctkVTKCompositeFunction>
00034 {
00035 public:
00036   vtkSmartPointer<vtkPiecewiseFunction>     PiecewiseFunction;
00037   vtkSmartPointer<vtkColorTransferFunction> ColorTransferFunction;
00038 };
00039 
00040 //-----------------------------------------------------------------------------
00041 ctkVTKCompositeFunction::ctkVTKCompositeFunction(vtkPiecewiseFunction* piecewiseFunction,
00042                                                  vtkColorTransferFunction* colorTransferFunction,
00043                                                  QObject* parentObject)
00044   :ctkTransferFunction(parentObject)
00045 {
00046   CTK_INIT_PRIVATE(ctkVTKCompositeFunction);
00047   this->setPiecewiseFunction(piecewiseFunction);
00048   this->setColorTransferFunction(colorTransferFunction);
00049 }
00050 
00051 //-----------------------------------------------------------------------------
00052 ctkVTKCompositeFunction::~ctkVTKCompositeFunction()
00053 {
00054 }
00055 
00056 //-----------------------------------------------------------------------------
00057 int ctkVTKCompositeFunction::count()const
00058 {
00059   CTK_D(const ctkVTKCompositeFunction);
00060   // count points from piecewise
00061   // could be from color transfer function
00062   if (d->PiecewiseFunction.GetPointer() == 0)
00063     {
00064     Q_ASSERT(d->PiecewiseFunction.GetPointer());
00065     return -1;
00066     }
00067 
00068   if (d->ColorTransferFunction.GetPointer() == 0)
00069     {
00070     Q_ASSERT(d->ColorTransferFunction.GetPointer());
00071     return -1;
00072     }
00073   //qDebug() << "Piecewise: " << d->PiecewiseFunction->GetSize();
00074   //qDebug() << "Color Transfer: " << d->ColorTransferFunction->GetSize();
00075 
00076   // check if 2 tranfer function have same size
00077   Q_ASSERT( d->PiecewiseFunction->GetSize() == d->ColorTransferFunction->GetSize());
00078 
00079   return d->PiecewiseFunction->GetSize();
00080 }
00081 
00082 //-----------------------------------------------------------------------------
00083 bool ctkVTKCompositeFunction::isDiscrete()const
00084 {
00085   return false;
00086 }
00087 
00088 //-----------------------------------------------------------------------------
00089 bool ctkVTKCompositeFunction::isEditable()const
00090 {
00091   return true;
00092 }
00093 
00094 //-----------------------------------------------------------------------------
00095 void ctkVTKCompositeFunction::range(qreal& minRange, qreal& maxRange)const
00096 {
00097   CTK_D(const ctkVTKCompositeFunction);
00098   if (d->PiecewiseFunction.GetPointer() == 0)
00099     {
00100     Q_ASSERT(d->PiecewiseFunction.GetPointer());
00101     minRange = 1.;
00102     maxRange = 0.;
00103     return;
00104     }
00105   double rangeValues[2];
00106   d->PiecewiseFunction->GetRange(rangeValues);
00107   minRange = rangeValues[0];
00108   maxRange = rangeValues[1];
00109 }
00110 
00111 //-----------------------------------------------------------------------------
00112 QVariant ctkVTKCompositeFunction::minValue()const
00113 {
00114   CTK_D(const ctkVTKCompositeFunction);
00115   if (d->PiecewiseFunction.GetPointer() == 0)
00116     {
00117     Q_ASSERT(d->PiecewiseFunction.GetPointer());
00118     return -1;
00119     }
00120   //Initialize to max value
00121   double minValue = VTK_DOUBLE_MAX;
00122   for (int i = 0; i < this->count(); ++i)
00123     {
00124     double value[4];
00125     d->PiecewiseFunction->GetNodeValue(i, value);
00126     minValue = qMin(value[1], minValue);
00127     }
00128   return minValue;
00129 }
00130 
00131 //-----------------------------------------------------------------------------
00132 QVariant ctkVTKCompositeFunction::maxValue()const
00133 {
00134   CTK_D(const ctkVTKCompositeFunction);
00135   if (d->PiecewiseFunction.GetPointer() == 0)
00136     {
00137     Q_ASSERT(d->PiecewiseFunction.GetPointer());
00138     return -1;
00139     }
00140   //Initialize to min value
00141   double maxValue = VTK_DOUBLE_MIN;
00142   for (int i = 0; i < this->count(); ++i)
00143     {
00144     double value[4];
00145     d->PiecewiseFunction->GetNodeValue(i, value);
00146     maxValue = qMax(maxValue, value[1]);
00147     }
00148   return maxValue;
00149 }
00150 
00151 //-----------------------------------------------------------------------------
00152 ctkControlPoint* ctkVTKCompositeFunction::controlPoint(int index)const
00153 {
00154   CTK_D(const ctkVTKCompositeFunction);
00155   Q_ASSERT(index >= 0 && index < this->count());
00156 
00157   double valuesPWF[4];
00158   double valuesCTF[6];
00159   double* range = d->PiecewiseFunction->GetRange();
00160   d->PiecewiseFunction->GetNodeValue(index, valuesPWF);
00161   d->ColorTransferFunction->GetNodeValue(index, valuesCTF);
00162 
00163   QVariant rangeY[2];
00164   rangeY[0] = this->minValue();
00165   rangeY[1] = this->maxValue();
00166 
00167 // test piecewise
00168   Q_ASSERT(valuesPWF[0] >= range[0] && valuesPWF[0] <= range [1] &&  // X
00169     valuesPWF[1] >= rangeY[0].toDouble() && valuesPWF[1] <= rangeY[1].toDouble()  &&  // Y
00170     valuesPWF[2] >= 0. && valuesPWF[2] <= 1. &&                // Midpoint
00171     valuesPWF[3] >= 0. && valuesPWF[3] <= 1. );                // Sharpness
00172 
00173   // test color transfer
00174   Q_ASSERT(valuesCTF[0] >= d->ColorTransferFunction->GetRange()[0] &&
00175     valuesCTF[0] <= d->ColorTransferFunction->GetRange()[1] &&
00176     valuesCTF[1] >= 0. && valuesCTF[1] <= 1. &&  // Red
00177     valuesCTF[2] >= 0. && valuesCTF[2] <= 1. &&  // Green
00178     valuesCTF[3] >= 0. && valuesCTF[3] <= 1. &&  // Blue
00179     valuesCTF[4] >= 0. && valuesCTF[4] <= 1. &&  // MidPoint
00180     valuesCTF[5] >= 0. && valuesCTF[5] <= 1.);   // Sharpness
00181 
00182   // if only 2 points -> linear
00183   if (index + 1 >= this->count())
00184     {
00185     ctkControlPoint* cp = new ctkControlPoint();
00186     cp->P.X = valuesPWF[0];
00187     // update value of QVariant
00188     QColor compositeValue(valuesCTF[1], valuesCTF[2], valuesCTF[3], valuesPWF[1]);
00189     cp->P.Value = compositeValue;
00190     return cp;
00191     }
00192 
00193   //else
00194 
00195   ctkNonLinearControlPoint* cp = new ctkNonLinearControlPoint();
00196   cp->P.X = valuesPWF[0];
00197   // update value of QVariant
00198   QColor compositeValue(valuesCTF[1], valuesCTF[2], valuesCTF[3], valuesPWF[1]);
00199   cp->P.Value = compositeValue;
00200 
00201   d->PiecewiseFunction->GetNodeValue(index + 1, valuesPWF);
00202   d->ColorTransferFunction->GetNodeValue(index +1, valuesCTF);
00203 
00204   Q_ASSERT(valuesPWF[0] >= range[0] && valuesPWF[0] <= range[1]  &&  // X
00205     valuesPWF[1] >= rangeY[0].toDouble() && valuesPWF[1] <= rangeY[1].toDouble()  &&  // Y
00206     valuesPWF[2] >= 0. && valuesPWF[2] <= 1. &&                // Midpoint
00207     valuesPWF[3] >= 0. && valuesPWF[3] <= 1. );                // Sharpness
00208 
00209   Q_ASSERT(valuesCTF[0] >= d->ColorTransferFunction->GetRange()[0] &&
00210     valuesCTF[0] <= d->ColorTransferFunction->GetRange()[1] &&
00211     valuesCTF[1] >= 0. && valuesCTF[1] <= 1. &&  // Red
00212     valuesCTF[2] >= 0. && valuesCTF[2] <= 1. &&  // Green
00213     valuesCTF[3] >= 0. && valuesCTF[3] <= 1. &&  // Blue
00214     valuesCTF[4] >= 0. && valuesCTF[4] <= 1. &&  // MidPoint
00215     valuesCTF[5] >= 0. && valuesCTF[5] <= 1.);   // Sharpness
00216 
00217   double subPointsCTF[30];
00218   double subPointsPWF[10];
00219   d->ColorTransferFunction->GetTable(cp->x(), valuesCTF[0], 10, subPointsCTF);
00220   d->PiecewiseFunction->GetTable(cp->x(), valuesCTF[0], 10, subPointsPWF);
00221   qreal interval = (valuesCTF[0] - cp->x()) / 9.;
00222 
00223   for(int i = 0; i < 10; ++i)
00224   {
00225     qreal red =  subPointsCTF[3*i];
00226     qreal green =  subPointsCTF[3*i+1];
00227     qreal blue =  subPointsCTF[3*i+2];
00228     qreal alpha = subPointsPWF[i];
00229     QColor compositeValue = QColor::fromRgbF(red, green, blue, alpha );
00230     cp->SubPoints << ctkPoint(cp->x() + interval*i, compositeValue);
00231   }
00232   return cp;
00233 }
00234 
00235 //-----------------------------------------------------------------------------
00236 QVariant ctkVTKCompositeFunction::value(qreal pos)const
00237 {
00238   CTK_D(const ctkVTKCompositeFunction);
00239   Q_ASSERT(d->PiecewiseFunction.GetPointer());
00240   Q_ASSERT(d->ColorTransferFunction.GetPointer());
00241 
00242   // Get color
00243   double rgb[3];
00244   d->ColorTransferFunction->GetColor(pos, rgb);
00245 
00246   // Get Alpha
00247   qreal alpha;
00248   alpha = d->PiecewiseFunction->GetValue( pos );
00249 
00250   // returns RGBA
00251   QColor compositeValue(rgb[0], rgb[1], rgb[2], alpha);
00252   return compositeValue;
00253 }
00254 
00255 //-----------------------------------------------------------------------------
00256 int ctkVTKCompositeFunction::insertControlPoint(const ctkControlPoint& cp)
00257 {
00258   CTK_D(ctkVTKCompositeFunction);
00259   int index = -1;
00260   // check piecewise
00261   if (d->PiecewiseFunction.GetPointer() == 0)
00262     {
00263     return index;
00264     }
00265   // cp: x
00266   // value = rgba
00267   /*
00268   // check color tf
00269   qreal value = cp.value().value<qreal>();
00270   const ctkNonLinearControlPoint* nonLinearCp = dynamic_cast<const ctkNonLinearControlPoint*>(&cp);
00271   if (nonLinearCp)
00272     {
00273     // TODO retrieve midpoint & sharpness
00274     index = d->PiecewiseFunction->AddPoint(
00275       cp.x(), value);
00276     }
00277   else
00278     {
00279     index = d->PiecewiseFunction->AddPoint(
00280       cp.x(), value);
00281     }*/
00282   return index;
00283 }
00284 //-----------------------------------------------------------------------------
00285 int ctkVTKCompositeFunction::insertControlPoint(qreal pos)
00286 {
00287   CTK_D(ctkVTKCompositeFunction);
00288   int index = -1;
00289   // check piecewise
00290   if (d->PiecewiseFunction.GetPointer() == 0)
00291     {
00292     return index;
00293     }
00294   //check color tf
00295   if (d->ColorTransferFunction.GetPointer() == 0)
00296     {
00297     return index;
00298     }
00299 
00300   // Add color to CTF
00301   double color[3];
00302   d->ColorTransferFunction->GetColor( pos, color );
00303   int indexColor =
00304       d->ColorTransferFunction->AddRGBPoint( pos, color[0], color[1], color[2] );
00305 
00306   // Add point to piecewise
00307   int indexPiecewise =
00308       d->PiecewiseFunction->AddPoint( pos, 0);
00309 
00310   // check index
00311   Q_ASSERT(indexColor == indexPiecewise);
00312 
00313   index = indexColor;
00314 
00315   return index;
00316 }
00317 
00318 //-----------------------------------------------------------------------------
00319 void ctkVTKCompositeFunction::setControlPointPos(int index, qreal pos)
00320 {
00321   CTK_D(ctkVTKCompositeFunction);
00322 
00323   // update X pos in the CTF
00324   double valuesColor[6];
00325   d->ColorTransferFunction->GetNodeValue(index, valuesColor);
00326   valuesColor[0] = pos;
00327   // warning, a possible new range is not supported
00328   // SetNodeValue eventually fire the signal changed()
00329   d->ColorTransferFunction->SetNodeValue(index, valuesColor);
00330 
00331   // Update X pos in the PWF
00332   double valuesPiecewise[4];
00333   d->PiecewiseFunction->GetNodeValue(index, valuesPiecewise);
00334   // warning, a possible new range is not supported
00335   // SetNodeValue eventually fire the signal changed()
00336   valuesPiecewise[0] = pos;
00337   d->PiecewiseFunction->SetNodeValue(index, valuesPiecewise);
00338 }
00339 
00340 //-----------------------------------------------------------------------------
00341 void ctkVTKCompositeFunction::setControlPointValue(int index, const QVariant& value)
00342 {
00343   CTK_D(ctkVTKCompositeFunction);
00344   // QVariant = RGBA
00345 
00346   double values[4];
00347   d->PiecewiseFunction->GetNodeValue(index, values);
00348   values[1] = value.toDouble();
00349   // setNodeValue should eventually fired the signal changed()
00350   d->PiecewiseFunction->SetNodeValue(index, values);
00351 }
00352 
00353 //-----------------------------------------------------------------------------
00354 void ctkVTKCompositeFunction::setPiecewiseFunction(vtkPiecewiseFunction* piecewiseFunction)
00355 {
00356   CTK_D(ctkVTKCompositeFunction);
00357   d->PiecewiseFunction = piecewiseFunction;
00358   this->qvtkReconnect(d->PiecewiseFunction,vtkCommand::ModifiedEvent,
00359                       this, SIGNAL(changed()));
00360   emit changed();
00361 }
00362 //-----------------------------------------------------------------------------
00363 void ctkVTKCompositeFunction::setColorTransferFunction(vtkColorTransferFunction* colorTransferFunction)
00364 {
00365   CTK_D(ctkVTKCompositeFunction);
00366   d->ColorTransferFunction = colorTransferFunction;
00367   this->qvtkReconnect(d->ColorTransferFunction,vtkCommand::ModifiedEvent,
00368                       this, SIGNAL(changed()));
00369   emit changed();
00370 }
00371 
00372 //-----------------------------------------------------------------------------
00373 vtkPiecewiseFunction* ctkVTKCompositeFunction::piecewiseFunction()const
00374 {
00375   CTK_D(const ctkVTKCompositeFunction);
00376   return d->PiecewiseFunction;
00377 }
00378 //-----------------------------------------------------------------------------
00379 vtkColorTransferFunction* ctkVTKCompositeFunction::colorTransferFunction()const
00380 {
00381   CTK_D(const ctkVTKCompositeFunction);
00382   return d->ColorTransferFunction;
00383 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated on 21 May 2010 for CTK by  doxygen 1.6.1