ctkVTKDiscretizableColorTransferWidget.cpp 28 KB

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