]> Creatis software - clitk.git/blob - vv/vvToolStructureSetManager.cxx
- contours show/hide
[clitk.git] / vv / vvToolStructureSetManager.cxx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to:
5   - University of LYON              http://www.universite-lyon.fr/
6   - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
7   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
9   This software is distributed WITHOUT ANY WARRANTY; without even
10   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11   PURPOSE.  See the copyright notices for more information.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17   ======================================================================-====*/
18
19 #include "vvToolStructureSetManager.h"
20 #include "vvImageReader.h"
21 #include "vvStructureSetActor.h"
22 #include "vvSlicer.h"
23 #include "vvROIActor.h"
24
25 #include <QFileDialog>
26 #include <QMessageBox>
27 #include <QColorDialog>
28
29 #include <vtkLookupTable.h>
30 #include <vtkRenderWindow.h>
31
32 //------------------------------------------------------------------------------
33 // Create the tool and automagically (I like this word) insert it in
34 // the main window menu.
35 ADD_TOOL(vvToolStructureSetManager);
36 //------------------------------------------------------------------------------
37
38 //------------------------------------------------------------------------------
39 vvToolStructureSetManager::vvToolStructureSetManager(vvMainWindowBase * parent, Qt::WindowFlags f)
40   :vvToolWidgetBase(parent, f),
41    vvToolBase<vvToolStructureSetManager>(parent),
42    Ui::vvToolStructureSetManager()
43 {
44   // Setup the UI
45   Ui_vvToolStructureSetManager::setupUi(mToolWidget);
46   mTree->clear();
47   mCurrentStructureSet = NULL;
48   mCurrentStructureSetIndex = -1;
49   mGroupBoxROI->setEnabled(false);
50   mCurrentROIActor = NULL;
51   mIsAllVisibleEnabled = false;
52   mDefaultLUTColor = vtkLookupTable::New();
53   for(unsigned int i=0; i<mDefaultLUTColor->GetNumberOfTableValues(); i++) {
54     double r = (rand()/(RAND_MAX+1.0));
55     double v = (rand()/(RAND_MAX+1.0));
56     double b = (rand()/(RAND_MAX+1.0));
57     mDefaultLUTColor->SetTableValue(i, r, v, b);
58     //    std::cout << "mDefaultLUTColor->SetTableValue(" << i << ", " << r << ", " << v << ", " << b << ");" << std::endl;
59   }
60 #include "vvDefaultLut.h"
61
62   // Add input selector
63   AddInputSelector("Select image");
64 }
65 //------------------------------------------------------------------------------
66
67
68 //------------------------------------------------------------------------------
69 vvToolStructureSetManager::~vvToolStructureSetManager()
70 {
71   DD("vvToolStructureSetManager DESTRUCTOR");
72 }
73 //------------------------------------------------------------------------------
74
75
76 //------------------------------------------------------------------------------
77 void vvToolStructureSetManager::Initialize() {
78   SetToolName("ROIManager");
79   SetToolMenuName("Display ROI");
80   SetToolIconFilename(":/common/icons/ducky.png");
81   SetToolTip("Display ROI from label image.");
82   SetToolExperimental(true);
83 }
84 //------------------------------------------------------------------------------
85
86
87 //------------------------------------------------------------------------------
88 void vvToolStructureSetManager::InputIsSelected(vvSlicerManager *m)
89 {
90   // Hide the input selector
91   QList<int> s;
92   s.push_back(0);
93   s.push_back(1);
94   splitter->setSizes(s);
95   // Connect open menus
96   //  connect(mOpenComboBox, SIGNAL(activated(int)), this, SLOT(open(int)));
97   connect(mOpenBinaryButton, SIGNAL(clicked()), this, SLOT(OpenBinaryImage()));
98   DD(mCurrentImage->GetNumberOfDimensions());
99
100   // Seems that the following is not needed to refresh ...
101   //  connect(m, SIGNAL(LeftButtonReleaseSignal(int)), SLOT(LeftButtonReleaseEvent(int)));
102
103   connect(mTree, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItemChangedInTree()));
104   connect(mCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleROIToggled(bool)));
105   connect(mOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(OpacityChanged(int)));
106   connect(mChangeColorButton, SIGNAL(clicked()), this, SLOT(ChangeColor()));
107   connect(mContourCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleContourROIToggled(bool)));  
108   connect(mChangeContourColorButton, SIGNAL(clicked()), this, SLOT(ChangeContourColor()));
109   connect(mContourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeContourWidth(int)));
110
111   connect(mCheckBoxShowAll, SIGNAL(toggled(bool)), this, SLOT(AllVisibleROIToggled(bool)));
112   connect(mOpacitySliderAll, SIGNAL(valueChanged(int)), this, SLOT(AllOpacityChanged(int)));
113   connect(mContourCheckBoxShowAll, SIGNAL(toggled(bool)), this, SLOT(AllVisibleContourROIToggled(bool)));  
114 }
115 //------------------------------------------------------------------------------
116
117
118 //------------------------------------------------------------------------------
119 void vvToolStructureSetManager::LeftButtonReleaseEvent(int slicer)
120 {
121   DD("vvToolStructureSetManager::UpdateSlice");
122   //DD(slicer);
123   //DD(view);
124   //DD(slices);
125   for(int i=0; i<mCurrentSlicerManager->NumberOfSlicers(); i++) {
126     if (i != slicer);
127     mCurrentSlicerManager->GetSlicer(i)->GetRenderWindow()->Render();
128   }
129 }
130 //------------------------------------------------------------------------------
131
132
133 //------------------------------------------------------------------------------
134 void vvToolStructureSetManager::Open(int type) {
135   switch (type) {
136   case 0: OpenBinaryImage(); return; // Open binary image;
137   case 1: DD("TODO"); return; // Open DICOM RT
138   case 2: DD("TODO"); return; // Open mesh
139   default: std::cerr << "Error ????" << std::endl; exit(0);
140   }
141 }
142 //------------------------------------------------------------------------------
143
144
145 //------------------------------------------------------------------------------
146 void vvToolStructureSetManager::AddRoiInTreeWidget(clitk::DicomRT_ROI * roi, QTreeWidget * ww) {
147   QTreeWidgetItem * w = new QTreeWidgetItem(ww);
148   w->setText(0, QString("%1").arg(roi->GetROINumber()));
149   w->setText(1, QString("%1").arg(roi->GetName().c_str()));
150   //  w->setText(1, QString("%1").arg(roi->GetName().c_str()));
151   QBrush brush(QColor(roi->GetDisplayColor()[0]*255, roi->GetDisplayColor()[1]*255, roi->GetDisplayColor()[2]*255));
152   brush.setStyle(Qt::SolidPattern);
153   //  for(int i=0; i<w->columnCount (); i++) {
154   w->setBackground(2, brush);
155   //}
156   mMapROIToTreeWidget[roi] = w;
157   mMapTreeWidgetToROI[w] = roi;
158   // Connect ROI TreeWidget
159   // TODO
160 }
161 //------------------------------------------------------------------------------
162
163
164 //------------------------------------------------------------------------------
165 void vvToolStructureSetManager::UpdateStructureSetInTreeWidget(int index, clitk::DicomRT_StructureSet * s) {
166
167   /* ==> Please, keep this comment (if need several SS)
168      QTreeWidgetItem * ss;
169      if (mMapStructureSetIndexToTreeWidget.find(index) == mMapStructureSetIndexToTreeWidget.end()) {
170      // Main row item
171      ss = new QTreeWidgetItem(mTree);
172      //  ss->setFlags(Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsTristate);
173      ss->setText(0, QString("S%1").arg(index));
174      ss->setText(1, QString("%1").arg(s->GetLabel().c_str()));
175      // Insert in list
176      mMapStructureSetIndexToTreeWidget[index] = ss;
177     
178      // Connect Structure TreeWidget
179      // TODO
180      }
181      else ss = mMapStructureSetIndexToTreeWidget[index];
182   */
183
184   // Insert ROI
185   const std::vector<clitk::DicomRT_ROI*> & rois = s->GetListOfROI();
186   for(unsigned int i=0; i<rois.size(); i++) {
187     if (mMapROIToTreeWidget.find(rois[i]) == mMapROIToTreeWidget.end())
188       AddRoiInTreeWidget(rois[i], mTree); // replace mTree with ss if several SS
189   }
190 }
191 //------------------------------------------------------------------------------
192
193
194 //------------------------------------------------------------------------------
195 int vvToolStructureSetManager::AddStructureSet(clitk::DicomRT_StructureSet * mStructureSet) {
196
197   // Create actor for this SS
198   vvStructureSetActor * mStructureSetActor = new vvStructureSetActor;
199   mStructureSetActor->SetStructureSet(mStructureSet);
200   mStructureSetActor->SetSlicerManager(mCurrentSlicerManager);
201
202   // Insert in lists and get index
203   mStructureSetsList.push_back(mStructureSet);
204   mStructureSetActorsList.push_back(mStructureSetActor);
205   int index = mStructureSetsList.size()-1;
206
207   // Return index
208   return index;
209 }
210 //------------------------------------------------------------------------------
211
212
213 //------------------------------------------------------------------------------
214 void vvToolStructureSetManager::OpenBinaryImage() {
215   //  DD("openBinaryImage");
216   // Select current StructureSet (or create)
217   int index;
218   //  DD(mCurrentStructureSetIndex);
219   if (mCurrentStructureSet == NULL) {
220     if (mStructureSetsList.size() == 0) { // Create a default SS
221       clitk::DicomRT_StructureSet * mStructureSet = new clitk::DicomRT_StructureSet;
222       index = AddStructureSet(mStructureSet);
223       //DD(index);
224     }
225     else { // Get first SS
226       index = 0;
227     }
228   } else {
229     index = mCurrentStructureSetIndex;
230   }
231   //  DD(index);
232   // TODO -> SET THIS SS AS CURRENT
233   mCurrentStructureSet = mStructureSetsList[index];
234   mCurrentStructureSetActor = mStructureSetActorsList[index];
235   mCurrentStructureSetIndex = index;
236   //  DD(mCurrentStructureSetIndex);
237   //DD(mCurrentStructureSet->GetName());
238
239   // Open images
240   QString Extensions = "Images files ( *.mhd *.hdr *.his)";
241   Extensions += ";;All Files (*)";
242   QStringList filename =
243     QFileDialog::getOpenFileNames(this,tr("Open binary image"),
244                                   mMainWindowBase->GetInputPathName(),Extensions);
245   if (filename.size() == 0) return;
246
247   std::vector<int> mLoadedROIIndex;
248   for(int i=0; i<filename.size(); i++) {
249     //DD(filename[i].toStdString());
250
251     // Open Image
252     //init the progress events
253     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
254     vvImageReader * mReader = new vvImageReader;
255     std::vector<std::string> filenames;
256     filenames.push_back(filename[i].toStdString());
257     mReader->SetInputFilenames(filenames);
258     mReader->Update(IMAGE);
259     QApplication::restoreOverrideCursor();
260
261     if (mReader->GetLastError().size() != 0) {
262       std::cerr << "Error while reading " << filename[i].toStdString() << std::endl;
263       QString error = "Cannot open file \n";
264       error += mReader->GetLastError().c_str();
265       QMessageBox::information(this,tr("Reading problem"),error);
266       delete mReader;
267       return;
268     }
269     vvImage::Pointer binaryImage = mReader->GetOutput();
270     //  delete mReader;
271
272     // Check Dimension
273     int dim = mCurrentImage->GetNumberOfDimensions();
274     //DD(dim);
275     int bin_dim = binaryImage->GetNumberOfDimensions();
276     //DD(bin_dim);
277     if (dim < bin_dim) {  ////////// TO CHANGE FOR 3D/4D
278       std::ostringstream os;
279       os << "Error. Loaded binary image is " << bin_dim
280          << "D while selected image is " << dim << "D" << std::endl;
281       QMessageBox::information(this,tr("Reading problem"),os.str().c_str());
282       return;
283     }
284
285     // Add a new roi to the structure
286     int n = mCurrentStructureSet->AddBinaryImageAsNewROI(binaryImage, filename[i].toStdString());
287     //DD(n);
288     mLoadedROIIndex.push_back(n);
289
290     mCurrentStructureSet->GetROI(n)->SetBackgroundValueLabelImage(mBackgroundValueSpinBox->value());
291
292     // Change color NEED DEFAULT COLOR LIST
293     //DD(mDefaultLUTColor->GetNumberOfTableValues ());
294     if (n<mDefaultLUTColor->GetNumberOfTableValues ()) {
295       double * color = mDefaultLUTColor->GetTableValue(n % mDefaultLUTColor->GetNumberOfTableValues ());
296       //DD(color[0]);
297       //DD(color[1]);
298       //DD(color[2]);
299       mCurrentStructureSet->GetROI(n)->SetDisplayColor(color[0], color[1], color[2]);
300     }
301
302     // Add a new roi actor
303     mCurrentStructureSetActor->CreateNewROIActor(n);
304
305     // CheckBox for "All"
306     if (mCurrentStructureSetActor->GetROIActor(n)->IsVisible())
307       mNumberOfVisibleROI++;
308   } // end loop on n selected filenames
309
310   // Update the TreeWidget
311   UpdateStructureSetInTreeWidget(index, mCurrentStructureSet);
312   // Render loaded ROIs (the first is sufficient)
313   for(unsigned int i=0; i<mLoadedROIIndex.size(); i++) {
314     mCurrentStructureSetActor->GetROIActor(mLoadedROIIndex[i])->Update();
315   }
316   for(int i=0; i<mCurrentSlicerManager->NumberOfSlicers(); i++) {
317     mCurrentSlicerManager->GetSlicer(i)->Render();
318   }
319   
320 }
321 //------------------------------------------------------------------------------
322
323
324 //------------------------------------------------------------------------------
325 void vvToolStructureSetManager::apply() {
326   close();
327 }
328 //------------------------------------------------------------------------------
329
330
331 //------------------------------------------------------------------------------
332 // CURRENT ROI INTERACTION
333 //------------------------------------------------------------------------------
334
335
336 //------------------------------------------------------------------------------
337 void vvToolStructureSetManager::SelectedItemChangedInTree() {
338   // Search which roi is selected
339   QList<QTreeWidgetItem *> l = mTree->selectedItems();
340   if (l.size() == 0) return;
341   QTreeWidgetItem * w = l[0];
342   if (mMapTreeWidgetToROI.find(w) == mMapTreeWidgetToROI.end()) {
343     mCurrentROIActor = NULL;
344     mCurrentROI = NULL;
345     mGroupBoxROI->setEnabled(false);
346     return; // Search for SS (first)
347   }
348   clitk::DicomRT_ROI * roi = mMapTreeWidgetToROI[w];
349   //  DD(roi->GetName());
350
351   // Get selected roi actor
352   if (mCurrentROIActor != NULL) {
353     mCurrentROIActor->SetSelected(false);
354     mCurrentROIActor->Update();
355   }
356
357   vvROIActor * actor = mStructureSetActorsList[mCurrentStructureSetIndex]->GetROIActor(roi->GetROINumber());
358   mCurrentROI = roi;
359   mCurrentROIActor = actor;
360
361   // Update GUI
362   mGroupBoxROI->setEnabled(true);
363   mROInameLabel->setText(roi->GetName().c_str());
364   mCheckBoxShow->setChecked(actor->IsVisible());
365   mContourCheckBoxShow->setChecked(actor->IsContourVisible());
366   mContourWidthSpinBox->setValue(actor->GetContourWidth());
367   
368   // Warning -> avoir unuseful Render here by disconnect slider 
369   disconnect(mOpacitySlider, SIGNAL(valueChanged(int)), 
370              this, SLOT(OpacityChanged(int)));
371   mOpacitySlider->setValue((int)lrint(actor->GetOpacity()*100));
372   mOpacitySpinBox->setValue((int)lrint(actor->GetOpacity()*100));
373   connect(mOpacitySlider, SIGNAL(valueChanged(int)), 
374           this, SLOT(OpacityChanged(int)));
375
376   // Temporary disable selection
377   //  actor->SetSelected(true); // remove old selection  
378
379   // The following must not render !!
380   //  DD("before update");
381   actor->Update(); // To change in UpdateSelecte
382   //DD("after update");
383
384   mCurrentSlicerManager->Render();
385 }
386 //------------------------------------------------------------------------------
387
388
389 //------------------------------------------------------------------------------
390 void vvToolStructureSetManager::VisibleROIToggled(bool b) {
391   mCurrentROIActor->SetVisible(b);
392   if (b) mNumberOfVisibleROI++;
393   else mNumberOfVisibleROI--;
394   //mNumberOfVisibleROI;
395   //  if (mNumberOfVisibleROI == mCurrentStructureSetIndex
396 }
397 //------------------------------------------------------------------------------
398
399
400 //------------------------------------------------------------------------------
401 void vvToolStructureSetManager::VisibleContourROIToggled(bool b) {
402   mCurrentROIActor->SetContourVisible(b);
403   mCurrentROIActor->UpdateColor();
404   mCurrentSlicerManager->Render(); 
405 }
406 //------------------------------------------------------------------------------
407
408
409 //------------------------------------------------------------------------------
410 void vvToolStructureSetManager::OpacityChanged(int v) {
411   if (mCurrentROIActor == NULL) return;
412   mCurrentROIActor->SetOpacity((double)v/100.0);
413   mCurrentROIActor->UpdateColor();
414   mCurrentSlicerManager->Render(); 
415 }
416 //------------------------------------------------------------------------------
417
418
419 //------------------------------------------------------------------------------
420 void vvToolStructureSetManager::AllVisibleROIToggled(bool b) {
421   DD(b);
422   DD(mIsAllVisibleEnabled);
423   DD(mNumberOfVisibleROI);
424   if (b == mIsAllVisibleEnabled) return;
425   if (b) mCheckBoxShowAll->setCheckState(Qt::Checked);
426   else mCheckBoxShowAll->setCheckState(Qt::Unchecked);
427   mIsAllVisibleEnabled = b;
428   for(int i=0; i<mCurrentStructureSetActor->GetNumberOfROIs(); i++) {
429     mCurrentStructureSetActor->GetROIList()[i]->SetVisible(b);
430   }
431   // Update current selection
432   mCheckBoxShow->setChecked(b);
433 }
434 //------------------------------------------------------------------------------
435
436
437 //------------------------------------------------------------------------------
438 void vvToolStructureSetManager::AllVisibleContourROIToggled(bool b) {
439   /*mCurrentROIActor->SetContourVisible(b);
440     mCurrentROIActor->UpdateColor();
441     mCurrentSlicerManager->Render(); 
442   */
443 }
444 //------------------------------------------------------------------------------
445
446
447 //------------------------------------------------------------------------------
448 void vvToolStructureSetManager::AllOpacityChanged(int v) {
449   /*if (mCurrentROIActor == NULL) return;
450     mCurrentROIActor->SetOpacity((double)v/100.0);
451     mCurrentROIActor->UpdateColor();
452     mCurrentSlicerManager->Render(); 
453   */
454 }
455 //------------------------------------------------------------------------------
456
457
458 //------------------------------------------------------------------------------
459 void vvToolStructureSetManager::ChangeColor() {
460   QColor color;
461   color.setRgbF(mCurrentROIActor->GetROI()->GetDisplayColor()[0],
462                 mCurrentROIActor->GetROI()->GetDisplayColor()[1],
463                 mCurrentROIActor->GetROI()->GetDisplayColor()[2]);
464   QColor c = QColorDialog::getColor(color, this, "Choose the ROI color");
465   mCurrentROIActor->GetROI()->SetDisplayColor(c.redF(), c.greenF(), c.blueF());
466   mCurrentROIActor->UpdateColor();
467
468   QTreeWidgetItem * w = mMapROIToTreeWidget[mCurrentROI];
469   QBrush brush(QColor(mCurrentROI->GetDisplayColor()[0]*255,
470                       mCurrentROI->GetDisplayColor()[1]*255,
471                       mCurrentROI->GetDisplayColor()[2]*255));
472   brush.setStyle(Qt::SolidPattern);
473   //  for(int i=0; i<w->columnCount (); i++) {
474   w->setBackground(2, brush);
475   //}
476   
477   // Render
478   mCurrentSlicerManager->Render();
479 }
480 //------------------------------------------------------------------------------
481
482
483 //------------------------------------------------------------------------------
484 void vvToolStructureSetManager::ChangeContourColor() {
485   QColor color;
486   color.setRgbF(mCurrentROIActor->GetContourColor()[0], 
487                 mCurrentROIActor->GetContourColor()[1], 
488                 mCurrentROIActor->GetContourColor()[2]);
489   QColor c = QColorDialog::getColor(color, this, "Choose the contour color");
490   mCurrentROIActor->SetContourColor(c.redF(), c.greenF(), c.blueF());
491   mCurrentROIActor->UpdateColor();
492   mCurrentSlicerManager->Render();
493 }
494 //------------------------------------------------------------------------------
495
496
497 //------------------------------------------------------------------------------
498 void vvToolStructureSetManager::ChangeContourWidth(int n) {
499   mCurrentROIActor->SetContourWidth(n);
500   mCurrentROIActor->UpdateColor();
501   mCurrentSlicerManager->Render();
502 }
503 //------------------------------------------------------------------------------
504
505
506 //------------------------------------------------------------------------------
507 //void vvToolStructureSetManager::getActorFromROI() {
508 //  mStructureSetActorsList[mCurrentStructureSetIndex]->GetROIActor(n);
509 //}
510 //------------------------------------------------------------------------------
511
512