ctkVTKDiscretizableColorTransferWidget.cpp 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040
  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. #include "ctkVTKDiscretizableColorTransferWidget.h"
  15. // CTK includes
  16. #include "ctkColorPickerButton.h"
  17. #include "ctkDoubleSlider.h"
  18. #include "ctkVTKScalarsToColorsComboBox.h"
  19. #include "ctkVTKScalarsToColorsUtils.h"
  20. #include "ui_ctkVTKDiscretizableColorTransferWidget.h"
  21. #include "vtkScalarsToColorsContextItem.h"
  22. // Qt includes
  23. #include <QColorDialog>
  24. #include <QCheckBox>
  25. #include <QDebug>
  26. #include <QDoubleValidator>
  27. #include <QHBoxLayout>
  28. #include <QIcon>
  29. #include <QLineEdit>
  30. #include <QLabel>
  31. #include <QMenu>
  32. #include <QPushButton>
  33. #include <QSpinBox>
  34. #include <QTime>
  35. #include <QToolButton>
  36. #include <QVBoxLayout>
  37. #include <QWidgetAction>
  38. // VTK includes
  39. #ifdef CTK_USE_QVTKOPENGLWIDGET
  40. # ifdef CTK_HAS_QVTKOPENGLNATIVEWIDGET_H
  41. # include <QVTKOpenGLNativeWidget.h>
  42. # else
  43. # include <QVTKOpenGLWidget.h>
  44. # endif
  45. #else
  46. #include <QVTKWidget.h>
  47. #endif
  48. #include <vtkCallbackCommand.h>
  49. #include <vtkContextScene.h>
  50. #include <vtkContextView.h>
  51. #include <vtkControlPointsItem.h>
  52. #include <vtkDiscretizableColorTransferFunction.h>
  53. #include <vtkDoubleArray.h>
  54. #include <vtkEventQtSlotConnect.h>
  55. #include <vtkGenericOpenGLRenderWindow.h>
  56. #include <vtkIntArray.h>
  57. #include <vtkImageAccumulate.h>
  58. #include <vtkImageData.h>
  59. #include <vtkPiecewiseFunction.h>
  60. #include <vtkRenderer.h>
  61. #include <vtkRenderWindowInteractor.h>
  62. #include <vtkScalarsToColors.h>
  63. #include <vtkTable.h>
  64. //#define DEBUG_RANGE
  65. // ----------------------------------------------------------------------------
  66. class ctkVTKDiscretizableColorTransferWidgetPrivate :
  67. public Ui_ctkVTKDiscretizableColorTransferWidget
  68. {
  69. Q_DECLARE_PUBLIC(ctkVTKDiscretizableColorTransferWidget);
  70. protected:
  71. ctkVTKDiscretizableColorTransferWidget* const q_ptr;
  72. public:
  73. ctkVTKDiscretizableColorTransferWidgetPrivate(
  74. ctkVTKDiscretizableColorTransferWidget& object);
  75. struct Ranges
  76. {
  77. double CurrentRange[2];
  78. double VisibleRange[2];
  79. };
  80. void setupUi(QWidget* widget);
  81. void addRangesInHistory(double* currentRange, double* visibleRange);
  82. bool popRangesFromHistory(double* currentRange, double* visibleRange);
  83. void clearUndoHistory();
  84. #ifdef CTK_USE_QVTKOPENGLWIDGET
  85. # ifdef CTK_HAS_QVTKOPENGLNATIVEWIDGET_H
  86. QVTKOpenGLNativeWidget* ScalarsToColorsView;
  87. # else
  88. QVTKOpenGLWidget* ScalarsToColorsView;
  89. # endif
  90. #else
  91. QVTKWidget* ScalarsToColorsView;
  92. #endif
  93. vtkSmartPointer<vtkScalarsToColorsContextItem> scalarsToColorsContextItem;
  94. vtkSmartPointer<vtkContextView> scalarsToColorsContextView;
  95. vtkSmartPointer<vtkEventQtSlotConnect> eventLink;
  96. vtkSmartPointer<vtkImageAccumulate> histogramFilter;
  97. ///Option part
  98. ctkColorPickerButton* nanButton;
  99. QCheckBox* discretizeCheckBox;
  100. QSpinBox* nbOfDiscreteValuesSpinBox;
  101. /// Stores the range of the data.
  102. /// Extracted from the histogram
  103. double dataRange[2];
  104. double dataMean;
  105. double previousOpacityValue;
  106. /// History of ranges for undo feature
  107. QList<Ranges> rangesHistory;
  108. QTime historyUpdateTime;
  109. vtkSmartPointer<vtkCallbackCommand> colorTransferFunctionModified;
  110. static void colorTransferFunctionModifiedCallback(vtkObject *caller,
  111. unsigned long eid, void *clientdata, void *calldata);
  112. };
  113. // ----------------------------------------------------------------------------
  114. ctkVTKDiscretizableColorTransferWidgetPrivate
  115. ::ctkVTKDiscretizableColorTransferWidgetPrivate(
  116. ctkVTKDiscretizableColorTransferWidget& object)
  117. : q_ptr(&object)
  118. {
  119. this->scalarsToColorsSelector = CTK_NULLPTR;
  120. // Option menu
  121. this->nanButton = CTK_NULLPTR;
  122. this->discretizeCheckBox = CTK_NULLPTR;
  123. this->nbOfDiscreteValuesSpinBox = CTK_NULLPTR;
  124. this->dataRange[0] = VTK_DOUBLE_MAX;
  125. this->dataRange[1] = VTK_DOUBLE_MIN;
  126. this->dataMean = 0.;
  127. this->previousOpacityValue = 0.;
  128. this->historyUpdateTime = QTime::currentTime();
  129. this->colorTransferFunctionModified =
  130. vtkSmartPointer<vtkCallbackCommand>::New();
  131. this->colorTransferFunctionModified->SetClientData(this);
  132. this->colorTransferFunctionModified->SetCallback(
  133. this->colorTransferFunctionModifiedCallback);
  134. }
  135. //-----------------------------------------------------------------------------
  136. void ctkVTKDiscretizableColorTransferWidgetPrivate::setupUi(QWidget* widget)
  137. {
  138. Q_Q(ctkVTKDiscretizableColorTransferWidget);
  139. this->Ui_ctkVTKDiscretizableColorTransferWidget::setupUi(widget);
  140. #ifdef CTK_USE_QVTKOPENGLWIDGET
  141. # ifdef CTK_HAS_QVTKOPENGLNATIVEWIDGET_H
  142. this->ScalarsToColorsView = new QVTKOpenGLNativeWidget;
  143. # else
  144. this->ScalarsToColorsView = new QVTKOpenGLWidget;
  145. # endif
  146. #else
  147. this->ScalarsToColorsView = new QVTKWidget;
  148. #endif
  149. this->gridLayout->addWidget(this->ScalarsToColorsView, 2, 2, 5, 1);
  150. this->scalarsToColorsContextItem = vtkSmartPointer<vtkScalarsToColorsContextItem>::New();
  151. vtkDiscretizableColorTransferFunction* ctf = this->scalarsToColorsContextItem->GetDiscretizableColorTransferFunction();
  152. ctf->AddObserver(vtkCommand::ModifiedEvent, this->colorTransferFunctionModified);
  153. this->scalarsToColorsContextView = vtkSmartPointer<vtkContextView> ::New();
  154. #ifdef CTK_USE_QVTKOPENGLWIDGET
  155. vtkSmartPointer<vtkGenericOpenGLRenderWindow> renwin =
  156. vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
  157. this->ScalarsToColorsView->SetRenderWindow(renwin);
  158. #endif
  159. this->scalarsToColorsContextView->SetRenderWindow(
  160. this->ScalarsToColorsView->GetRenderWindow());
  161. this->scalarsToColorsContextView->SetInteractor(
  162. this->ScalarsToColorsView->GetInteractor());
  163. this->scalarsToColorsContextView->GetScene()->AddItem(
  164. this->scalarsToColorsContextItem.Get());
  165. q->setViewBackgroundColor(QColor(49, 54, 59));
  166. this->previousOpacityValue = opacitySlider->value();
  167. this->scalarsToColorsSelector->addScalarsToColors(CTK_NULLPTR, q->tr("Reset"));
  168. this->scalarsToColorsSelector->setCurrentIndex(-1);
  169. this->eventLink = vtkSmartPointer<vtkEventQtSlotConnect>::New();
  170. this->eventLink->Connect(scalarsToColorsContextItem.Get(),
  171. vtkControlPointsItem::CurrentPointEditEvent,
  172. q, SLOT(onCurrentPointEdit()));
  173. this->scalarsToColorsContextItem->AddObserver(vtkCommand::EndEvent,
  174. this->colorTransferFunctionModified);
  175. QObject::connect(this->scalarsToColorsSelector,
  176. SIGNAL(currentScalarsToColorsChanged(vtkScalarsToColors*)),
  177. q, SLOT(onPaletteIndexChanged(vtkScalarsToColors*)));
  178. QObject::connect(opacitySlider, SIGNAL(valueChanged(double)),
  179. q, SLOT(setGlobalOpacity(double)));
  180. QObject::connect(undoButton, SIGNAL(clicked()),
  181. q, SLOT(onUndoButtonClick()));
  182. QObject::connect(resetRangeButton, SIGNAL(clicked()),
  183. q, SLOT(onResetRangesButtonClick()));
  184. QObject::connect(shrinkRangeButton, SIGNAL(clicked()),
  185. q, SLOT(onShrinkRangeButtonClick()));
  186. QObject::connect(expandRangeButton, SIGNAL(clicked()),
  187. q, SLOT(onExpandRangeButtonClick()));
  188. QObject::connect(invertColorTransferFunctionButton, SIGNAL(clicked()),
  189. q, SLOT(invertColorTransferFunction()));
  190. QObject::connect(rangeSlider, SIGNAL(valuesChanged(double, double)),
  191. q, SLOT(onRangeSliderValueChange(double, double)));
  192. /// Option panel menu
  193. QWidget* nanColorWidget = new QWidget(optionButton);
  194. QHBoxLayout* nanColorLayout = new QHBoxLayout(nanColorWidget);
  195. QWidget* discretizeWidget = new QWidget(optionButton);
  196. QHBoxLayout* discretizeLayout = new QHBoxLayout(discretizeWidget);
  197. nanColorLayout->setContentsMargins(0, 0, 0, 0);
  198. discretizeLayout->setContentsMargins(0, 0, 0, 0);
  199. optionButton->setIcon(q->style()->standardIcon(
  200. QStyle::SP_FileDialogDetailedView, CTK_NULLPTR, optionButton));
  201. QLabel* nanLabel = new QLabel(q->tr("NaN values"));
  202. nanButton = new ctkColorPickerButton;
  203. nanButton->setToolTip(q->tr("NaN color"));
  204. nanColorLayout->addWidget(nanButton);
  205. nanColorLayout->addWidget(nanLabel);
  206. discretizeCheckBox = new QCheckBox;
  207. discretizeCheckBox->setText(q->tr("Discretize"));
  208. discretizeCheckBox->setToolTip(q->tr("Discretize color transfer function"));
  209. nbOfDiscreteValuesSpinBox = new QSpinBox;
  210. nbOfDiscreteValuesSpinBox->setMinimum(1);
  211. nbOfDiscreteValuesSpinBox->setMaximum(255);
  212. nbOfDiscreteValuesSpinBox->setToolTip(q->tr("Number of discrete values"));
  213. nbOfDiscreteValuesSpinBox->setEnabled(discretizeCheckBox->isChecked());
  214. discretizeLayout->addWidget(discretizeCheckBox);
  215. discretizeLayout->addWidget(nbOfDiscreteValuesSpinBox);
  216. QMenu* optionMenu = new QMenu(optionButton);
  217. QWidgetAction* nanColorAction = new QWidgetAction(optionButton);
  218. nanColorAction->setDefaultWidget(nanColorWidget);
  219. QWidgetAction* discretizeAction = new QWidgetAction(optionButton);
  220. discretizeAction->setDefaultWidget(discretizeWidget);
  221. optionMenu->addAction(nanColorAction);
  222. optionMenu->addSeparator();
  223. optionMenu->addAction(discretizeAction);
  224. optionButton->setMenu(optionMenu);
  225. optionButton->setPopupMode(QToolButton::InstantPopup);
  226. QObject::connect(nanButton, SIGNAL(clicked()), q, SLOT(setNaNColor()));
  227. QObject::connect(discretizeCheckBox, SIGNAL(toggled(bool)),
  228. q, SLOT(setDiscretize(bool)));
  229. QObject::connect(nbOfDiscreteValuesSpinBox, SIGNAL(valueChanged(int)),
  230. q, SLOT(setNumberOfDiscreteValues(int)));
  231. ///Enable nbOfValuesSpinBox only if we use discretize
  232. QObject::connect(discretizeCheckBox, SIGNAL(toggled(bool)),
  233. nbOfDiscreteValuesSpinBox, SLOT(setEnabled(bool)));
  234. }
  235. //-----------------------------------------------------------------------------
  236. void ctkVTKDiscretizableColorTransferWidgetPrivate::addRangesInHistory(
  237. double* currentRange, double* visibleRange)
  238. {
  239. Q_Q(ctkVTKDiscretizableColorTransferWidget);
  240. if (this->historyUpdateTime.msecsTo(QTime::currentTime()) < 500)
  241. {
  242. return;
  243. }
  244. Ranges ranges;
  245. ranges.CurrentRange[0] = currentRange[0];
  246. ranges.CurrentRange[1] = currentRange[1];
  247. ranges.VisibleRange[0] = visibleRange[0];
  248. ranges.VisibleRange[1] = visibleRange[1];
  249. this->rangesHistory.push_back(ranges);
  250. this->historyUpdateTime = QTime::currentTime();
  251. }
  252. //-----------------------------------------------------------------------------
  253. bool ctkVTKDiscretizableColorTransferWidgetPrivate::popRangesFromHistory(
  254. double* currentRange, double* visibleRange)
  255. {
  256. Q_Q(ctkVTKDiscretizableColorTransferWidget);
  257. if (this->rangesHistory.empty())
  258. {
  259. return false;
  260. }
  261. Ranges ranges = this->rangesHistory.back();
  262. currentRange[0] = ranges.CurrentRange[0];
  263. currentRange[1] = ranges.CurrentRange[1];
  264. visibleRange[0] = ranges.VisibleRange[0];
  265. visibleRange[1] = ranges.VisibleRange[1];
  266. this->rangesHistory.pop_back();
  267. this->historyUpdateTime = QTime::currentTime();
  268. return true;
  269. }
  270. //-----------------------------------------------------------------------------
  271. void ctkVTKDiscretizableColorTransferWidgetPrivate::clearUndoHistory()
  272. {
  273. this->rangesHistory.clear();
  274. }
  275. // ----------------------------------------------------------------------------
  276. void
  277. ctkVTKDiscretizableColorTransferWidgetPrivate::colorTransferFunctionModifiedCallback(
  278. vtkObject *caller, unsigned long eid, void *clientdata, void *calldata)
  279. {
  280. Q_UNUSED(caller);
  281. Q_UNUSED(eid);
  282. Q_UNUSED(calldata);
  283. ctkVTKDiscretizableColorTransferWidgetPrivate* self =
  284. reinterpret_cast<ctkVTKDiscretizableColorTransferWidgetPrivate*>(
  285. clientdata);
  286. vtkSmartPointer<vtkDiscretizableColorTransferFunction> dctf =
  287. self->scalarsToColorsContextItem->GetDiscretizableColorTransferFunction();
  288. if (dctf == CTK_NULLPTR)
  289. {
  290. return;
  291. }
  292. if (self->scalarsToColorsContextItem->IsProcessingColorTransferFunction())
  293. {
  294. return;
  295. }
  296. if (dctf->GetDiscretize())
  297. {
  298. dctf->Build();
  299. }
  300. self->discretizeCheckBox->setChecked(dctf->GetDiscretize());
  301. if (dctf->GetDiscretize())
  302. {
  303. self->nbOfDiscreteValuesSpinBox->setValue(dctf->GetNumberOfValues());
  304. }
  305. double* newRange = self->scalarsToColorsContextItem->GetCurrentRange();
  306. self->rangeSlider->setValues(newRange[0], newRange[1]);
  307. double r, g, b;
  308. self->scalarsToColorsContextItem->GetDiscretizableColorTransferFunction()->
  309. GetNanColor(r, g, b);
  310. QColor selected = QColor::fromRgbF(r, g, b);
  311. self->nanButton->setColor(selected);
  312. self->ScalarsToColorsView->GetInteractor()->Render();
  313. }
  314. // ----------------------------------------------------------------------------
  315. ctkVTKDiscretizableColorTransferWidget::ctkVTKDiscretizableColorTransferWidget(
  316. QWidget* parent)
  317. : QWidget(parent)
  318. , d_ptr(new ctkVTKDiscretizableColorTransferWidgetPrivate(*this))
  319. {
  320. Q_D(ctkVTKDiscretizableColorTransferWidget);
  321. d->setupUi(this);
  322. }
  323. // ----------------------------------------------------------------------------
  324. ctkVTKDiscretizableColorTransferWidget::~ctkVTKDiscretizableColorTransferWidget()
  325. {
  326. }
  327. // ----------------------------------------------------------------------------
  328. void ctkVTKDiscretizableColorTransferWidget::copyColorTransferFunction(
  329. vtkScalarsToColors* ctf, bool useCtfRange)
  330. {
  331. #ifdef DEBUG_RANGE
  332. if (ctf)
  333. {
  334. qDebug() << "DEBUG_RANGE ctf input range = " << ctf->GetRange()[0]
  335. << " " << ctf->GetRange()[1];
  336. }
  337. #endif
  338. Q_D(ctkVTKDiscretizableColorTransferWidget);
  339. if (useCtfRange)
  340. {
  341. // set cft, current range and visible range
  342. d->scalarsToColorsContextItem->CopyColorTransferFunction(ctf);
  343. emit(currentScalarsToColorsChanged(d->scalarsToColorsContextItem->GetDiscretizableColorTransferFunction()));
  344. }
  345. else
  346. {
  347. // save old ranges
  348. double ctfRange[2];
  349. ctfRange[0] = this->getColorTransferFunctionRange()[0];
  350. ctfRange[1] = this->getColorTransferFunctionRange()[1];
  351. double visibleRange[2];
  352. visibleRange[0] = this->getVisibleRange()[0];
  353. visibleRange[1] = this->getVisibleRange()[1];
  354. // set cft, current range and visible range
  355. d->scalarsToColorsContextItem->CopyColorTransferFunction(ctf);
  356. emit(currentScalarsToColorsChanged(d->scalarsToColorsContextItem->GetDiscretizableColorTransferFunction()));
  357. // set old ranges back
  358. if (visibleRange[0] < visibleRange[1])
  359. {
  360. this->setVisibleRange(visibleRange[0], visibleRange[1]);
  361. this->setColorTransferFunctionRange(ctfRange[0], ctfRange[1]);
  362. }
  363. }
  364. // todo should be replaced by callback when visible range changes
  365. this->updateCtfWidgets();
  366. d->colorTransferFunctionModified->Execute(ctf, vtkCommand::ModifiedEvent, this);
  367. }
  368. // ----------------------------------------------------------------------------
  369. vtkDiscretizableColorTransferFunction*
  370. ctkVTKDiscretizableColorTransferWidget::discretizableColorTransferFunction()
  371. const
  372. {
  373. Q_D(const ctkVTKDiscretizableColorTransferWidget);
  374. return d->scalarsToColorsContextItem->GetDiscretizableColorTransferFunction();
  375. }
  376. // ----------------------------------------------------------------------------
  377. void ctkVTKDiscretizableColorTransferWidget::setLeftAxisMode(int mode)
  378. {
  379. Q_D(ctkVTKDiscretizableColorTransferWidget);
  380. d->scalarsToColorsContextItem->SetLeftAxisMode(mode);
  381. }
  382. // ----------------------------------------------------------------------------
  383. int ctkVTKDiscretizableColorTransferWidget::leftAxisMode()
  384. {
  385. Q_D(ctkVTKDiscretizableColorTransferWidget);
  386. return d->scalarsToColorsContextItem->GetLeftAxisMode();
  387. }
  388. // ----------------------------------------------------------------------------
  389. void ctkVTKDiscretizableColorTransferWidget::setHistogramConnection(
  390. vtkAlgorithmOutput* input)
  391. {
  392. Q_D(ctkVTKDiscretizableColorTransferWidget);
  393. if (!input)
  394. {
  395. d->histogramFilter = CTK_NULLPTR;
  396. d->dataMean = 0.;
  397. return;
  398. }
  399. d->histogramFilter = vtkSmartPointer<vtkImageAccumulate>::New();
  400. d->histogramFilter->SetInputConnection(input);
  401. }
  402. // ----------------------------------------------------------------------------
  403. void ctkVTKDiscretizableColorTransferWidget::updateHistogram(
  404. bool updateDataRange)
  405. {
  406. Q_D(ctkVTKDiscretizableColorTransferWidget);
  407. this->updateHistogram();
  408. if (updateDataRange)
  409. {
  410. if (d->histogramFilter
  411. && d->histogramFilter->GetInputConnection(0, 0))
  412. {
  413. // get min max values from histogram
  414. this->setDataRange(d->histogramFilter->GetMin()[0],
  415. d->histogramFilter->GetMax()[0]);
  416. }
  417. else
  418. {
  419. this->setDataRange(VTK_DOUBLE_MAX, VTK_DOUBLE_MIN);
  420. }
  421. }
  422. }
  423. // ----------------------------------------------------------------------------
  424. void ctkVTKDiscretizableColorTransferWidget::resetColorTransferFunctionRange(
  425. ResetCTFRange resetMode)
  426. {
  427. Q_D(ctkVTKDiscretizableColorTransferWidget);
  428. double newRange[2];
  429. switch (resetMode)
  430. {
  431. case DATA:
  432. {
  433. double* dataRange = this->getDataRange();
  434. newRange[0] = dataRange[0];
  435. newRange[1] = dataRange[1];
  436. break;
  437. }
  438. case VISIBLE:
  439. {
  440. double* visibleRange = this->getVisibleRange();
  441. newRange[0] = visibleRange[0];
  442. newRange[1] = visibleRange[1];
  443. break;
  444. }
  445. default:
  446. return;
  447. }
  448. this->setColorTransferFunctionRange(newRange[0], newRange[1]);
  449. }
  450. // ----------------------------------------------------------------------------
  451. void ctkVTKDiscretizableColorTransferWidget::resetVisibleRange(
  452. ResetVisibleRange resetMode)
  453. {
  454. Q_D(ctkVTKDiscretizableColorTransferWidget);
  455. double newRange[2];
  456. switch (resetMode)
  457. {
  458. case UNION_DATA_AND_CTF:
  459. {
  460. double* ctfRange = this->getColorTransferFunctionRange();
  461. double* dataRange = this->getDataRange();
  462. newRange[0] = std::min(dataRange[0], ctfRange[0]);
  463. newRange[1] = std::max(dataRange[1], ctfRange[1]);
  464. break;
  465. }
  466. case UNION_DATA_AND_VISIBLE:
  467. {
  468. double* visibleRange = this->getVisibleRange();
  469. double* dataRange = this->getDataRange();
  470. newRange[0] = std::min(dataRange[0], visibleRange[0]);
  471. newRange[1] = std::max(dataRange[1], visibleRange[1]);
  472. break;
  473. }
  474. case ONLY_DATA:
  475. {
  476. double* dataRange = this->getDataRange();
  477. newRange[0] = dataRange[0];
  478. newRange[1] = dataRange[1];
  479. break;
  480. }
  481. case ONLY_CTF:
  482. {
  483. double* ctfRange = this->getColorTransferFunctionRange();
  484. newRange[0] = ctfRange[0];
  485. newRange[1] = ctfRange[1];
  486. break;
  487. }
  488. default:
  489. return;
  490. }
  491. this->setVisibleRange(newRange[0], newRange[1]);
  492. }
  493. // ----------------------------------------------------------------------------
  494. void ctkVTKDiscretizableColorTransferWidget::updateCtfWidgets()
  495. {
  496. Q_D(ctkVTKDiscretizableColorTransferWidget);
  497. if (this->discretizableColorTransferFunction() == CTK_NULLPTR)
  498. {
  499. this->disableCtfWidgets();
  500. }
  501. else
  502. {
  503. this->enableCtfWidgets();
  504. }
  505. }
  506. // ----------------------------------------------------------------------------
  507. void ctkVTKDiscretizableColorTransferWidget::disableCtfWidgets()
  508. {
  509. Q_D(ctkVTKDiscretizableColorTransferWidget);
  510. d->rangeSlider->setRange(0., 255.);
  511. d->rangeSlider->setValues(0., 1.);
  512. d->rangeSlider->setEnabled(false);
  513. d->previousOpacityValue = 0.0;
  514. d->opacitySlider->setValue(d->previousOpacityValue);
  515. d->opacitySlider->setEnabled(false);
  516. d->optionButton->setEnabled(false);
  517. d->undoButton->setEnabled(false);
  518. d->resetRangeButton->setEnabled(false);
  519. d->shrinkRangeButton->setEnabled(false);
  520. d->expandRangeButton->setEnabled(false);
  521. d->invertColorTransferFunctionButton->setEnabled(false);
  522. #ifdef DEBUG_RANGE
  523. qDebug() << "DEBUG_RANGE slider range = " << 0
  524. << " " << 255;
  525. qDebug() << "DEBUG_RANGE slider value = " << 0
  526. << " " << 1;
  527. #endif
  528. }
  529. // ----------------------------------------------------------------------------
  530. void ctkVTKDiscretizableColorTransferWidget::enableCtfWidgets()
  531. {
  532. Q_D(ctkVTKDiscretizableColorTransferWidget);
  533. d->rangeSlider->setEnabled(true);
  534. d->opacitySlider->setEnabled(true);
  535. d->optionButton->setEnabled(true);
  536. d->undoButton->setEnabled(true);
  537. d->resetRangeButton->setEnabled(true);
  538. d->shrinkRangeButton->setEnabled(true);
  539. d->expandRangeButton->setEnabled(true);
  540. d->invertColorTransferFunctionButton->setEnabled(true);
  541. d->previousOpacityValue = 1.0;
  542. d->opacitySlider->setValue(d->previousOpacityValue);
  543. double* visibleRange = this->getVisibleRange();
  544. double* ctfRange = this->getColorTransferFunctionRange();
  545. d->rangeSlider->setRange(visibleRange[0], visibleRange[1]);
  546. d->rangeSlider->setValues(ctfRange[0], ctfRange[1]);
  547. #ifdef DEBUG_RANGE
  548. qDebug() << "DEBUG_RANGE slider range = " << visibleRange[0]
  549. << " " << visibleRange[1];
  550. qDebug() << "DEBUG_RANGE slider value = " << ctfRange[0]
  551. << " " << ctfRange[1];
  552. #endif
  553. }
  554. // ----------------------------------------------------------------------------
  555. void ctkVTKDiscretizableColorTransferWidget::updateHistogram()
  556. {
  557. Q_D(ctkVTKDiscretizableColorTransferWidget);
  558. // convert histogram data into table
  559. std::string binsName = "image_extents";
  560. std::string frequenciesName = "Frequency";
  561. vtkSmartPointer<vtkDoubleArray> bins =
  562. vtkSmartPointer<vtkDoubleArray>::New();
  563. bins->SetNumberOfComponents(1);
  564. bins->SetName(binsName.c_str());
  565. vtkSmartPointer<vtkIntArray> frequencies =
  566. vtkSmartPointer<vtkIntArray>::New();
  567. frequencies->SetNumberOfComponents(1);
  568. frequencies->SetName(frequenciesName.c_str());
  569. vtkNew<vtkTable> table;
  570. table->AddColumn(bins);
  571. table->AddColumn(frequencies);
  572. // fill bins and frequencies
  573. if (d->histogramFilter == CTK_NULLPTR
  574. || d->histogramFilter->GetInputConnection(0, 0) == CTK_NULLPTR)
  575. {
  576. bins->SetNumberOfTuples(1);
  577. bins->SetTuple1(0, 0);
  578. frequencies->SetNumberOfTuples(1);
  579. frequencies->SetTuple1(0, 0);
  580. }
  581. else
  582. {
  583. double* visibleRange = d->scalarsToColorsContextItem->GetVisibleRange();
  584. int extent = d->histogramFilter->GetComponentExtent()[1];
  585. double origin = visibleRange[0] - std::numeric_limits<double>::epsilon();
  586. double spacing = (visibleRange[1] - visibleRange[0] + 2 * std::numeric_limits<double>::epsilon())
  587. / static_cast<double>(extent + 1);
  588. // recompute histogram in data range
  589. d->histogramFilter->SetComponentOrigin(origin, 0, 0);
  590. d->histogramFilter->SetComponentSpacing(spacing, 0, 0);
  591. d->histogramFilter->Update();
  592. // update data mean
  593. d->dataMean = d->histogramFilter->GetMean()[0];
  594. vtkImageData* histogram = d->histogramFilter->GetOutput();
  595. vtkIdType* output = static_cast<vtkIdType*>(histogram->GetScalarPointer());
  596. // set min and max of the slider widget
  597. vtkDataObject* input = d->histogramFilter->GetInputAlgorithm()->GetOutputDataObject(0);
  598. vtkImageData* inputImage = vtkImageData::SafeDownCast(input);
  599. d->rangeSlider->setCustomSpinBoxesLimits(inputImage->GetScalarTypeMin(),
  600. inputImage->GetScalarTypeMax());
  601. #ifdef DEBUG_RANGE
  602. qDebug() << "DEBUG_RANGE histo input range = " << origin
  603. << " " << origin + (extent + 1) * spacing;
  604. qDebug() << "DEBUG_RANGE histo real range = " << *d->histogramFilter->GetMin()
  605. << " " << *d->histogramFilter->GetMax();
  606. int dims[3];
  607. histogram->GetDimensions(dims);
  608. QDebug deb = qDebug();
  609. deb << "DEBUG_RANGE histo = ";
  610. for(vtkIdType i = 0; i < dims[0]; ++i)
  611. {
  612. deb << *(static_cast<vtkIdType*>(histogram->GetScalarPointer(i, 0, 0))) << " ";
  613. }
  614. #endif
  615. bins->SetNumberOfTuples(extent + 1);
  616. frequencies->SetNumberOfTuples(extent + 1);
  617. double bin = origin;
  618. for (int j = 0; j < extent + 1; ++j)
  619. {
  620. bins->SetTuple1(j, bin);
  621. bin += spacing;
  622. frequencies->SetTuple1(j, *output++);
  623. }
  624. }
  625. d->scalarsToColorsContextItem->SetHistogramTable(table.Get(),
  626. binsName.c_str(), frequenciesName.c_str());
  627. }
  628. // ----------------------------------------------------------------------------
  629. void ctkVTKDiscretizableColorTransferWidget::onPaletteIndexChanged(
  630. vtkScalarsToColors* ctf)
  631. {
  632. Q_D(ctkVTKDiscretizableColorTransferWidget);
  633. d->addRangesInHistory(this->getColorTransferFunctionRange(), this->getVisibleRange());
  634. this->copyColorTransferFunction(ctf);
  635. d->ScalarsToColorsView->GetInteractor()->Render();
  636. }
  637. // ----------------------------------------------------------------------------
  638. void ctkVTKDiscretizableColorTransferWidget::onResetRangesButtonClick()
  639. {
  640. Q_D(ctkVTKDiscretizableColorTransferWidget);
  641. d->addRangesInHistory(this->getColorTransferFunctionRange(), this->getVisibleRange());
  642. this->resetRangesToData();
  643. }
  644. // ----------------------------------------------------------------------------
  645. void ctkVTKDiscretizableColorTransferWidget::onShrinkRangeButtonClick()
  646. {
  647. Q_D(ctkVTKDiscretizableColorTransferWidget);
  648. d->addRangesInHistory(this->getColorTransferFunctionRange(), this->getVisibleRange());
  649. this->resetVisibleRangeToCTF();
  650. }
  651. // ----------------------------------------------------------------------------
  652. void ctkVTKDiscretizableColorTransferWidget::onExpandRangeButtonClick()
  653. {
  654. Q_D(ctkVTKDiscretizableColorTransferWidget);
  655. d->addRangesInHistory(this->getColorTransferFunctionRange(), this->getVisibleRange());
  656. this->resetCTFRangeToVisible();
  657. }
  658. // ----------------------------------------------------------------------------
  659. void ctkVTKDiscretizableColorTransferWidget::onUndoButtonClick()
  660. {
  661. Q_D(ctkVTKDiscretizableColorTransferWidget);
  662. double currentRange[2], visibleRange[2];
  663. if (d->popRangesFromHistory(currentRange, visibleRange))
  664. {
  665. this->setVisibleRange(visibleRange[0], visibleRange[1]);
  666. this->setColorTransferFunctionRange(currentRange[0], currentRange[1]);
  667. }
  668. }
  669. // ----------------------------------------------------------------------------
  670. void ctkVTKDiscretizableColorTransferWidget::onRangeSliderValueChange(
  671. double min, double max)
  672. {
  673. Q_D(ctkVTKDiscretizableColorTransferWidget);
  674. d->addRangesInHistory(this->getColorTransferFunctionRange(), this->getVisibleRange());
  675. this->setColorTransferFunctionRange(min, max);
  676. }
  677. // ----------------------------------------------------------------------------
  678. void ctkVTKDiscretizableColorTransferWidget::setGlobalOpacity(double value)
  679. {
  680. Q_D(ctkVTKDiscretizableColorTransferWidget);
  681. d->scalarsToColorsContextItem->SetGlobalOpacity(
  682. value / d->previousOpacityValue);
  683. d->previousOpacityValue = value;
  684. }
  685. // ----------------------------------------------------------------------------
  686. void ctkVTKDiscretizableColorTransferWidget::setNaNColor()
  687. {
  688. Q_D(ctkVTKDiscretizableColorTransferWidget);
  689. QColor selected = d->nanButton->color();
  690. d->scalarsToColorsContextItem->GetDiscretizableColorTransferFunction()->
  691. SetNanColor(selected.redF(), selected.greenF(), selected.blueF());
  692. }
  693. // ----------------------------------------------------------------------------
  694. void ctkVTKDiscretizableColorTransferWidget::setDiscretize(bool checked)
  695. {
  696. Q_D(ctkVTKDiscretizableColorTransferWidget);
  697. d->scalarsToColorsContextItem->GetDiscretizableColorTransferFunction()->
  698. SetDiscretize(checked);
  699. }
  700. // ----------------------------------------------------------------------------
  701. void ctkVTKDiscretizableColorTransferWidget::setNumberOfDiscreteValues(
  702. int value)
  703. {
  704. Q_D(ctkVTKDiscretizableColorTransferWidget);
  705. d->scalarsToColorsContextItem->GetDiscretizableColorTransferFunction()
  706. ->SetNumberOfValues(value);
  707. }
  708. // ----------------------------------------------------------------------------
  709. double* ctkVTKDiscretizableColorTransferWidget::getColorTransferFunctionRange()
  710. {
  711. Q_D(ctkVTKDiscretizableColorTransferWidget);
  712. return d->scalarsToColorsContextItem->GetCurrentRange();
  713. }
  714. // ----------------------------------------------------------------------------
  715. void ctkVTKDiscretizableColorTransferWidget::setColorTransferFunctionRange(
  716. double min, double max)
  717. {
  718. Q_D(ctkVTKDiscretizableColorTransferWidget);
  719. if (min == this->getColorTransferFunctionRange()[0]
  720. && max == this->getColorTransferFunctionRange()[1])
  721. {
  722. return;
  723. }
  724. if (max < min)
  725. {
  726. return;
  727. }
  728. double* visibleRange = this->getVisibleRange();
  729. if (min < visibleRange[0]
  730. || max > visibleRange[1])
  731. {
  732. double newRange[2] = { visibleRange[0], visibleRange[1] };
  733. if (min < visibleRange[0])
  734. {
  735. newRange[0] = min;
  736. }
  737. if (max > visibleRange[1])
  738. {
  739. newRange[1] = max;
  740. }
  741. this->setVisibleRange(newRange[0], newRange[1]);
  742. }
  743. d->scalarsToColorsContextItem->SetCurrentRange(min, max);
  744. }
  745. // ----------------------------------------------------------------------------
  746. double* ctkVTKDiscretizableColorTransferWidget::getVisibleRange()
  747. {
  748. Q_D(ctkVTKDiscretizableColorTransferWidget);
  749. return d->scalarsToColorsContextItem->GetVisibleRange();
  750. }
  751. // ----------------------------------------------------------------------------
  752. void ctkVTKDiscretizableColorTransferWidget::setVisibleRange(
  753. double min, double max)
  754. {
  755. Q_D(ctkVTKDiscretizableColorTransferWidget);
  756. if (min == this->getVisibleRange()[0]
  757. && max == this->getVisibleRange()[1])
  758. {
  759. return;
  760. }
  761. if (max < min)
  762. {
  763. return;
  764. }
  765. d->scalarsToColorsContextItem->SetVisibleRange(min, max);
  766. // todo should be replaced by callback when visible range changes
  767. this->updateHistogram();
  768. this->updateCtfWidgets();
  769. }
  770. // ----------------------------------------------------------------------------
  771. double* ctkVTKDiscretizableColorTransferWidget::getDataRange()
  772. {
  773. Q_D(ctkVTKDiscretizableColorTransferWidget);
  774. return d->scalarsToColorsContextItem->GetDataRange();
  775. }
  776. // ----------------------------------------------------------------------------
  777. void ctkVTKDiscretizableColorTransferWidget::setDataRange(
  778. double min, double max)
  779. {
  780. Q_D(ctkVTKDiscretizableColorTransferWidget);
  781. if (min == this->getDataRange()[0]
  782. && max == this->getDataRange()[1])
  783. {
  784. return;
  785. }
  786. d->scalarsToColorsContextItem->SetDataRange(min, max);
  787. }
  788. // ----------------------------------------------------------------------------
  789. void ctkVTKDiscretizableColorTransferWidget::onCurrentPointEdit()
  790. {
  791. Q_D(ctkVTKDiscretizableColorTransferWidget);
  792. double rgb[3];
  793. if (d->scalarsToColorsContextItem->GetCurrentControlPointColor(rgb))
  794. {
  795. QColor color = QColorDialog::getColor(
  796. QColor::fromRgbF(rgb[0], rgb[1], rgb[2]), this, "Select color at point",
  797. QColorDialog::DontUseNativeDialog);
  798. if (color.isValid())
  799. {
  800. rgb[0] = color.redF();
  801. rgb[1] = color.greenF();
  802. rgb[2] = color.blueF();
  803. d->scalarsToColorsContextItem->SetCurrentControlPointColor(rgb);
  804. }
  805. }
  806. }
  807. // ----------------------------------------------------------------------------
  808. void ctkVTKDiscretizableColorTransferWidget::resetRangesToData()
  809. {
  810. Q_D(ctkVTKDiscretizableColorTransferWidget);
  811. this->resetVisibleRange(ctkVTKDiscretizableColorTransferWidget::ONLY_DATA);
  812. this->resetColorTransferFunctionRange(ctkVTKDiscretizableColorTransferWidget::VISIBLE);
  813. }
  814. // ----------------------------------------------------------------------------
  815. void ctkVTKDiscretizableColorTransferWidget::clearUndoHistory()
  816. {
  817. Q_D(ctkVTKDiscretizableColorTransferWidget);
  818. d->clearUndoHistory();
  819. }
  820. // ----------------------------------------------------------------------------
  821. void ctkVTKDiscretizableColorTransferWidget::resetVisibleRangeToCTF()
  822. {
  823. Q_D(ctkVTKDiscretizableColorTransferWidget);
  824. this->resetVisibleRange(ctkVTKDiscretizableColorTransferWidget::ONLY_CTF);
  825. }
  826. // ----------------------------------------------------------------------------
  827. void ctkVTKDiscretizableColorTransferWidget::resetCTFRangeToVisible()
  828. {
  829. Q_D(ctkVTKDiscretizableColorTransferWidget);
  830. this->resetColorTransferFunctionRange(ctkVTKDiscretizableColorTransferWidget::VISIBLE);
  831. }
  832. // ----------------------------------------------------------------------------
  833. void ctkVTKDiscretizableColorTransferWidget::centerColorTransferFunctionRange()
  834. {
  835. Q_D(ctkVTKDiscretizableColorTransferWidget);
  836. d->scalarsToColorsContextItem->CenterRange(d->dataMean);
  837. }
  838. // ----------------------------------------------------------------------------
  839. void ctkVTKDiscretizableColorTransferWidget::invertColorTransferFunction()
  840. {
  841. Q_D(ctkVTKDiscretizableColorTransferWidget);
  842. d->scalarsToColorsContextItem->InvertColorTransferFunction();
  843. }
  844. // ----------------------------------------------------------------------------
  845. void ctkVTKDiscretizableColorTransferWidget::setViewBackgroundColor(
  846. const QColor& i_color)
  847. {
  848. Q_D(ctkVTKDiscretizableColorTransferWidget);
  849. d->scalarsToColorsContextView->GetRenderer()->SetBackground(
  850. i_color.redF(), i_color.greenF(), i_color.blueF());
  851. }
  852. // ----------------------------------------------------------------------------
  853. QColor ctkVTKDiscretizableColorTransferWidget::viewBackgroundColor() const
  854. {
  855. Q_D(const ctkVTKDiscretizableColorTransferWidget);
  856. double rgb[3];
  857. d->scalarsToColorsContextView->GetRenderer()->GetBackground(rgb);
  858. return QColor::fromRgbF(rgb[0], rgb[1], rgb[2]);
  859. }
  860. // ----------------------------------------------------------------------------
  861. ctkVTKScalarsToColorsComboBox*
  862. ctkVTKDiscretizableColorTransferWidget::scalarsToColorsSelector() const
  863. {
  864. Q_D(const ctkVTKDiscretizableColorTransferWidget);
  865. return d->scalarsToColorsSelector;
  866. }