ctkVTKDiscretizableColorTransferWidget.cpp 28 KB

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