ctkVTKThresholdWidget.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  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 <QDebug>
  16. // CTK includes
  17. #include "ctkLogger.h"
  18. #include "ctkVTKThresholdWidget.h"
  19. #include "ctkUtils.h"
  20. #include "ui_ctkVTKThresholdWidget.h"
  21. // VTK includes
  22. #include <vtkPiecewiseFunction.h>
  23. //----------------------------------------------------------------------------
  24. static ctkLogger logger("org.commontk.visualization.vtk.widgets.ctkVTKThresholdWidget");
  25. //----------------------------------------------------------------------------
  26. class ctkVTKThresholdWidgetPrivate:
  27. public Ui_ctkVTKThresholdWidget
  28. {
  29. Q_DECLARE_PUBLIC(ctkVTKThresholdWidget);
  30. protected:
  31. ctkVTKThresholdWidget* const q_ptr;
  32. public:
  33. ctkVTKThresholdWidgetPrivate(ctkVTKThresholdWidget& object);
  34. void setupUi(QWidget* widget);
  35. void setThreshold(double min, double max, double opacity);
  36. void setRange(double min, double max);
  37. void guessThreshold(double& min, double& max, double& opacity);
  38. vtkPiecewiseFunction* PiecewiseFunction;
  39. bool UserRange;
  40. };
  41. // ----------------------------------------------------------------------------
  42. // ctkVTKThresholdWidgetPrivate methods
  43. // ----------------------------------------------------------------------------
  44. ctkVTKThresholdWidgetPrivate::ctkVTKThresholdWidgetPrivate(
  45. ctkVTKThresholdWidget& object)
  46. : q_ptr(&object)
  47. {
  48. this->PiecewiseFunction = 0;
  49. this->UserRange = false;
  50. }
  51. // ----------------------------------------------------------------------------
  52. void ctkVTKThresholdWidgetPrivate::setupUi(QWidget* widget)
  53. {
  54. Q_Q(ctkVTKThresholdWidget);
  55. Q_ASSERT(q == widget);
  56. this->Ui_ctkVTKThresholdWidget::setupUi(widget);
  57. QObject::connect(this->ThresholdSliderWidget, SIGNAL(valuesChanged(double, double)),
  58. q, SLOT(setThresholdValues(double, double)));
  59. QObject::connect(this->OpacitySliderWidget, SIGNAL(valueChanged(double)),
  60. q, SLOT(setOpacity(double)));
  61. }
  62. // ----------------------------------------------------------------------------
  63. void ctkVTKThresholdWidgetPrivate::guessThreshold(double& min, double& max, double& opacity)
  64. {
  65. min = this->ThresholdSliderWidget->minimum();
  66. max = this->ThresholdSliderWidget->maximum();
  67. opacity = 1.;
  68. if (!this->PiecewiseFunction || this->PiecewiseFunction->GetSize() == 0)
  69. {
  70. return;
  71. }
  72. int minIndex;
  73. for (minIndex=0; minIndex < this->PiecewiseFunction->GetSize(); ++minIndex)
  74. {
  75. double node[4];
  76. this->PiecewiseFunction->GetNodeValue(minIndex, node);
  77. if (node[1] > 0.)
  78. {
  79. min = node[0];
  80. opacity = node[1];
  81. break;
  82. }
  83. }
  84. if (minIndex == this->PiecewiseFunction->GetSize())
  85. {
  86. return;
  87. }
  88. int maxIndex;
  89. for (maxIndex = minIndex + 1;
  90. maxIndex < this->PiecewiseFunction->GetSize();
  91. ++maxIndex)
  92. {
  93. double node[4];
  94. this->PiecewiseFunction->GetNodeValue(maxIndex, node);
  95. // average the opacities
  96. opacity += node[1];
  97. if (node[1] == 0.)
  98. {
  99. max = node[0];
  100. opacity /= maxIndex - minIndex + 1;
  101. break;
  102. }
  103. }
  104. // couldn't find the upper threshold value, use the upper range
  105. if (maxIndex == this->PiecewiseFunction->GetSize())
  106. {
  107. opacity /= maxIndex - minIndex;
  108. }
  109. }
  110. // ----------------------------------------------------------------------------
  111. void ctkVTKThresholdWidgetPrivate::setRange(double min, double max)
  112. {
  113. bool wasBlocking = this->ThresholdSliderWidget->blockSignals(true);
  114. int decimals = qMax(0, -ctk::orderOfMagnitude(max - min) + 2);
  115. this->ThresholdSliderWidget->setDecimals(decimals);
  116. this->ThresholdSliderWidget->setSingleStep(pow(10., -decimals));
  117. this->ThresholdSliderWidget->setRange(min, max);
  118. this->ThresholdSliderWidget->blockSignals(wasBlocking);
  119. }
  120. // ----------------------------------------------------------------------------
  121. void ctkVTKThresholdWidgetPrivate::setThreshold(double min, double max, double opacity)
  122. {
  123. if (!this->PiecewiseFunction)
  124. {
  125. return;
  126. }
  127. double range[2];
  128. this->ThresholdSliderWidget->range(range);
  129. double node[4];
  130. node[0] = range[0];
  131. node[1] = 0.;
  132. node[2] = 0.5;
  133. node[3] = 0.;
  134. if (this->PiecewiseFunction->GetSize() < 1)
  135. {
  136. this->PiecewiseFunction->AddPoint(node[0], node[1], node[2], node[3]);
  137. }
  138. else
  139. {
  140. this->PiecewiseFunction->SetNodeValue(0, node);
  141. }
  142. node[0] = min;
  143. node[1] = 0.;
  144. node[2] = 0.;
  145. node[3] = 1.;
  146. if (this->PiecewiseFunction->GetSize() < 2)
  147. {
  148. this->PiecewiseFunction->AddPoint(node[0], node[1], node[2], node[3]);
  149. }
  150. else
  151. {
  152. this->PiecewiseFunction->SetNodeValue(1, node);
  153. }
  154. node[0] = max;
  155. node[1] = opacity;
  156. if (this->PiecewiseFunction->GetSize() < 3)
  157. {
  158. this->PiecewiseFunction->AddPoint(node[0], node[1], node[2], node[3]);
  159. }
  160. else
  161. {
  162. this->PiecewiseFunction->SetNodeValue(2, node);
  163. }
  164. node[0] = (max == range[1]) ? range[1] + 0.00000000000001 : range[1];
  165. node[1] = 0.;
  166. node[2] = 0.5;
  167. node[3] = 0.;
  168. if (this->PiecewiseFunction->GetSize() < 4)
  169. {
  170. this->PiecewiseFunction->AddPoint(node[0], node[1], node[2], node[3]);
  171. }
  172. else
  173. {
  174. this->PiecewiseFunction->SetNodeValue(3, node);
  175. }
  176. }
  177. // ----------------------------------------------------------------------------
  178. // ctkVTKThresholdWidget methods
  179. // ----------------------------------------------------------------------------
  180. ctkVTKThresholdWidget::ctkVTKThresholdWidget(QWidget* parentWidget)
  181. :QWidget(parentWidget)
  182. , d_ptr(new ctkVTKThresholdWidgetPrivate(*this))
  183. {
  184. Q_D(ctkVTKThresholdWidget);
  185. d->setupUi(this);
  186. }
  187. // ----------------------------------------------------------------------------
  188. ctkVTKThresholdWidget::~ctkVTKThresholdWidget()
  189. {
  190. }
  191. // ----------------------------------------------------------------------------
  192. vtkPiecewiseFunction* ctkVTKThresholdWidget::piecewiseFunction()const
  193. {
  194. Q_D(const ctkVTKThresholdWidget);
  195. return d->PiecewiseFunction;
  196. }
  197. // ----------------------------------------------------------------------------
  198. void ctkVTKThresholdWidget
  199. ::setPiecewiseFunction(vtkPiecewiseFunction* newFunction)
  200. {
  201. Q_D(ctkVTKThresholdWidget);
  202. if (d->PiecewiseFunction == newFunction)
  203. {
  204. return;
  205. }
  206. this->qvtkReconnect(d->PiecewiseFunction, newFunction, vtkCommand::ModifiedEvent,
  207. this, SLOT(updateFromPiecewiseFunction()));
  208. d->PiecewiseFunction = newFunction;
  209. if (!d->UserRange)
  210. {
  211. double range[2] = {0., 1.};
  212. if (d->PiecewiseFunction)
  213. {
  214. d->PiecewiseFunction->GetRange(range);
  215. }
  216. d->setRange(range[0], range[1]);
  217. }
  218. if (d->PiecewiseFunction)
  219. {
  220. double min, max, value;
  221. d->guessThreshold(min, max, value);
  222. d->setThreshold(min, max, value);
  223. }
  224. }
  225. // ----------------------------------------------------------------------------
  226. void ctkVTKThresholdWidget::updateFromPiecewiseFunction()
  227. {
  228. Q_D(ctkVTKThresholdWidget);
  229. if (!d->PiecewiseFunction)
  230. {
  231. return;
  232. }
  233. double range[2];
  234. d->ThresholdSliderWidget->range(range);
  235. double minThreshold = range[0];
  236. double maxThreshold = range[1];
  237. double opacity = 1.;
  238. double node[4];
  239. if (d->PiecewiseFunction->GetSize() > 1)
  240. {
  241. d->PiecewiseFunction->GetNodeValue(1, node);
  242. minThreshold = node[0];
  243. }
  244. if (d->PiecewiseFunction->GetSize() > 2)
  245. {
  246. d->PiecewiseFunction->GetNodeValue(2, node);
  247. maxThreshold = node[0];
  248. opacity = node[1];
  249. }
  250. bool wasBlocking = d->ThresholdSliderWidget->blockSignals(true);
  251. d->ThresholdSliderWidget->setValues(minThreshold, maxThreshold);
  252. d->ThresholdSliderWidget->blockSignals(wasBlocking);
  253. d->OpacitySliderWidget->blockSignals(true);
  254. d->OpacitySliderWidget->setValue(opacity);
  255. d->OpacitySliderWidget->blockSignals(wasBlocking);
  256. }
  257. // ----------------------------------------------------------------------------
  258. void ctkVTKThresholdWidget::setThresholdValues(double min, double max)
  259. {
  260. Q_D(ctkVTKThresholdWidget);
  261. d->setThreshold(min, max, d->OpacitySliderWidget->value());
  262. }
  263. // ----------------------------------------------------------------------------
  264. void ctkVTKThresholdWidget::setOpacity(double opacity)
  265. {
  266. Q_D(ctkVTKThresholdWidget);
  267. d->setThreshold(d->ThresholdSliderWidget->minimumValue(),
  268. d->ThresholdSliderWidget->maximumValue(), opacity);
  269. }
  270. // ----------------------------------------------------------------------------
  271. void ctkVTKThresholdWidget::range(double* range)const
  272. {
  273. Q_D(const ctkVTKThresholdWidget);
  274. d->ThresholdSliderWidget->range(range);
  275. }
  276. // ----------------------------------------------------------------------------
  277. void ctkVTKThresholdWidget::setRange(double min, double max)
  278. {
  279. Q_D(ctkVTKThresholdWidget);
  280. d->UserRange = true;
  281. d->setRange(min, max);
  282. }