ctkVTKPiecewiseFunction.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) Kitware Inc.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0.txt
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. =========================================================================*/
  14. /// Qt includes
  15. #include <QColor>
  16. #include <QDebug>
  17. /// CTK includes
  18. #include "ctkVTKPiecewiseFunction.h"
  19. /// VTK includes
  20. #include <vtkPiecewiseFunction.h>
  21. #include <vtkSmartPointer.h>
  22. class ctkVTKPiecewiseFunctionPrivate
  23. {
  24. public:
  25. vtkSmartPointer<vtkPiecewiseFunction> PiecewiseFunction;
  26. };
  27. //-----------------------------------------------------------------------------
  28. ctkVTKPiecewiseFunction::ctkVTKPiecewiseFunction(vtkPiecewiseFunction* piecewiseFunction,
  29. QObject* parentObject)
  30. :ctkTransferFunction(parentObject)
  31. , d_ptr(new ctkVTKPiecewiseFunctionPrivate)
  32. {
  33. this->setPiecewiseFunction(piecewiseFunction);
  34. }
  35. //-----------------------------------------------------------------------------
  36. ctkVTKPiecewiseFunction::~ctkVTKPiecewiseFunction()
  37. {
  38. }
  39. //-----------------------------------------------------------------------------
  40. int ctkVTKPiecewiseFunction::count()const
  41. {
  42. Q_D(const ctkVTKPiecewiseFunction);
  43. if (d->PiecewiseFunction.GetPointer() == 0)
  44. {
  45. Q_ASSERT(d->PiecewiseFunction.GetPointer());
  46. return -1;
  47. }
  48. return d->PiecewiseFunction->GetSize();
  49. }
  50. //-----------------------------------------------------------------------------
  51. bool ctkVTKPiecewiseFunction::isDiscrete()const
  52. {
  53. return false;
  54. }
  55. //-----------------------------------------------------------------------------
  56. bool ctkVTKPiecewiseFunction::isEditable()const
  57. {
  58. return true;
  59. }
  60. //-----------------------------------------------------------------------------
  61. void ctkVTKPiecewiseFunction::range(qreal& minRange, qreal& maxRange)const
  62. {
  63. Q_D(const ctkVTKPiecewiseFunction);
  64. if (d->PiecewiseFunction.GetPointer() == 0)
  65. {
  66. Q_ASSERT(d->PiecewiseFunction.GetPointer());
  67. minRange = 1.;
  68. maxRange = 0.;
  69. return;
  70. }
  71. double rangeValues[2];
  72. d->PiecewiseFunction->GetRange(rangeValues);
  73. minRange = rangeValues[0];
  74. maxRange = rangeValues[1];
  75. }
  76. //-----------------------------------------------------------------------------
  77. QVariant ctkVTKPiecewiseFunction::minValue()const
  78. {
  79. Q_D(const ctkVTKPiecewiseFunction);
  80. if (d->PiecewiseFunction.GetPointer() == 0)
  81. {
  82. Q_ASSERT(d->PiecewiseFunction.GetPointer());
  83. return -1;
  84. }
  85. //Initialize to max value
  86. /// TODO initialize with max value
  87. double minValue = VTK_DOUBLE_MAX;
  88. for (int i = 0; i < this->count(); ++i)
  89. {
  90. double value[4];
  91. d->PiecewiseFunction->GetNodeValue(i, value);
  92. minValue = qMin(value[1], minValue);
  93. }
  94. return minValue;
  95. }
  96. //-----------------------------------------------------------------------------
  97. QVariant ctkVTKPiecewiseFunction::maxValue()const
  98. {
  99. Q_D(const ctkVTKPiecewiseFunction);
  100. if (d->PiecewiseFunction.GetPointer() == 0)
  101. {
  102. Q_ASSERT(d->PiecewiseFunction.GetPointer());
  103. return -1;
  104. }
  105. //Initialize to max value
  106. /// TODO initialize with max value
  107. qreal maxValue = VTK_DOUBLE_MIN;
  108. for (int i = 0; i < this->count(); ++i)
  109. {
  110. double value[4];
  111. d->PiecewiseFunction->GetNodeValue(i, value);
  112. maxValue = qMax(maxValue, value[1]);
  113. }
  114. return maxValue;
  115. }
  116. //-----------------------------------------------------------------------------
  117. ctkControlPoint* ctkVTKPiecewiseFunction::controlPoint(int index)const
  118. {
  119. Q_D(const ctkVTKPiecewiseFunction);
  120. Q_ASSERT(index >= 0 && index < this->count());
  121. double values[4];
  122. #ifndef QT_NO_DEBUG
  123. double* range = d->PiecewiseFunction->GetRange();
  124. #endif
  125. d->PiecewiseFunction->GetNodeValue(index, values);
  126. QVariant rangeY[2];
  127. rangeY[0] = this->minValue();
  128. rangeY[1] = this->maxValue();
  129. // rangeYDiff /= rangeY[1].toReal() - rangeY[0].toReal();
  130. #ifndef QT_NO_DEBUG
  131. Q_ASSERT(values[0] >= range[0] && values[0] <= range [1] && // X
  132. values[1] >= rangeY[0].toDouble() && values[1] <= rangeY[1].toDouble() && // Y
  133. values[2] >= 0. && values[2] <= 1. && // Midpoint
  134. values[3] >= 0. && values[3] <= 1. ); // Sharpness
  135. #endif
  136. if (index + 1 >= this->count())
  137. {
  138. ctkControlPoint* cp = new ctkControlPoint();
  139. cp->P.X = values[0];
  140. cp->P.Value = values[1];
  141. return cp;
  142. }
  143. ctkNonLinearControlPoint* cp = new ctkNonLinearControlPoint();
  144. cp->P.X = values[0];
  145. cp->P.Value = values[1];
  146. // Optimization: don't use Subpoints if sharpness == 0
  147. if (values[3] == 0.)
  148. {
  149. cp->SubPoints << ctkPoint(values[0], values[1]);
  150. }
  151. double nextValues[4];
  152. d->PiecewiseFunction->GetNodeValue(index + 1, nextValues);
  153. #ifndef QT_NO_DEBUG
  154. Q_ASSERT(nextValues[0] >= range[0] && nextValues[0] <= range[1] && // X
  155. nextValues[1] >= rangeY[0].toDouble() && nextValues[1] <= rangeY[1].toDouble() && // Y
  156. nextValues[2] >= 0. && nextValues[2] <= 1. && // Midpoint
  157. nextValues[3] >= 0. && nextValues[3] <= 1. ); // Sharpness
  158. #endif
  159. // Optimization: Don't use Subpoints if sharpness == 0
  160. if (values[3] == 0.)
  161. {
  162. cp->SubPoints << ctkPoint(nextValues[0], nextValues[1]);
  163. return cp;
  164. }
  165. double subPoints[100];
  166. d->PiecewiseFunction->GetTable(cp->x(), nextValues[0], 100, subPoints);
  167. qreal interval = (nextValues[0] - cp->x()) / 99.;
  168. // subPoints[i] since value varies (not like in color transfer function widget)
  169. for(int i = 0; i < 100; ++i)
  170. {
  171. cp->SubPoints << ctkPoint(cp->x() + interval*i, subPoints[i]);
  172. }
  173. return cp;
  174. }
  175. //-----------------------------------------------------------------------------
  176. QVariant ctkVTKPiecewiseFunction::value(qreal pos)const
  177. {
  178. Q_D(const ctkVTKPiecewiseFunction);
  179. Q_ASSERT(d->PiecewiseFunction.GetPointer());
  180. qreal value;
  181. // get value for given x
  182. value = d->PiecewiseFunction->GetValue( pos );
  183. return value;
  184. }
  185. //-----------------------------------------------------------------------------
  186. int ctkVTKPiecewiseFunction::insertControlPoint(const ctkControlPoint& cp)
  187. {
  188. Q_D(ctkVTKPiecewiseFunction);
  189. int index = -1;
  190. if (d->PiecewiseFunction.GetPointer() == 0)
  191. {
  192. return index;
  193. }
  194. qreal value = cp.value().value<qreal>();
  195. const ctkNonLinearControlPoint* nonLinearCp = dynamic_cast<const ctkNonLinearControlPoint*>(&cp);
  196. if (nonLinearCp)
  197. {
  198. // TODO retrieve midpoint & sharpness
  199. index = d->PiecewiseFunction->AddPoint(
  200. cp.x(), value);
  201. }
  202. else
  203. {
  204. index = d->PiecewiseFunction->AddPoint(
  205. cp.x(), value);
  206. }
  207. return index;
  208. }
  209. //-----------------------------------------------------------------------------
  210. // insert point with value = 0
  211. int ctkVTKPiecewiseFunction::insertControlPoint(qreal pos)
  212. {
  213. Q_D(ctkVTKPiecewiseFunction);
  214. int index = -1;
  215. if (d->PiecewiseFunction.GetPointer() == 0)
  216. {
  217. return index;
  218. }
  219. index = d->PiecewiseFunction->AddPoint( pos, 0);
  220. qDebug() << "index of new point: " << index;
  221. return index;
  222. }
  223. //-----------------------------------------------------------------------------
  224. void ctkVTKPiecewiseFunction::setControlPointPos(int index, qreal pos)
  225. {
  226. Q_D(ctkVTKPiecewiseFunction);
  227. double values[4];
  228. d->PiecewiseFunction->GetNodeValue(index, values);
  229. // warning, a possible new range is not supported
  230. // SetNodeValue eventually fire the signal changed()
  231. values[0] = pos;
  232. d->PiecewiseFunction->SetNodeValue(index, values);
  233. }
  234. //-----------------------------------------------------------------------------
  235. void ctkVTKPiecewiseFunction::setControlPointValue(int index, const QVariant& value)
  236. {
  237. Q_D(ctkVTKPiecewiseFunction);
  238. double values[4];
  239. d->PiecewiseFunction->GetNodeValue(index, values);
  240. qDebug() << "old value: " << values[1];
  241. values[1] = value.toDouble();
  242. qDebug() << "new value: " << values[1];
  243. // setNodeValue should eventually fired the signal changed()
  244. d->PiecewiseFunction->SetNodeValue(index, values);
  245. }
  246. //-----------------------------------------------------------------------------
  247. void ctkVTKPiecewiseFunction::setPiecewiseFunction(vtkPiecewiseFunction* piecewiseFunction)
  248. {
  249. Q_D(ctkVTKPiecewiseFunction);
  250. d->PiecewiseFunction = piecewiseFunction;
  251. this->qvtkReconnect(d->PiecewiseFunction,vtkCommand::ModifiedEvent,
  252. this, SIGNAL(changed()));
  253. emit changed();
  254. }
  255. //-----------------------------------------------------------------------------
  256. vtkPiecewiseFunction* ctkVTKPiecewiseFunction::piecewiseFunction()const
  257. {
  258. Q_D(const ctkVTKPiecewiseFunction);
  259. return d->PiecewiseFunction;
  260. }
  261. //-----------------------------------------------------------------------------
  262. void ctkVTKPiecewiseFunction::removeControlPoint( qreal pos )
  263. {
  264. Q_D(ctkVTKPiecewiseFunction);
  265. if (d->PiecewiseFunction.GetPointer() == 0)
  266. {
  267. return;
  268. }
  269. d->PiecewiseFunction->RemovePoint( pos );
  270. }