]> Creatis software - creaMaracasVisu.git/blob - lib/Kernel/VTKObjects/VolumeRenderer/volumerenderermanager.cxx
changes in qt for volume rendering with gpu support, if you are working with volume...
[creaMaracasVisu.git] / lib / Kernel / VTKObjects / VolumeRenderer / volumerenderermanager.cxx
1 #include "volumerenderermanager.h"
2
3 /*=========================================================================
4
5   Program:   wxMaracas
6   Module:    $RCSfile: volumerenderermanager.cxx,v $
7   Language:  C++
8   Date:      $Date: 2011/10/05 16:27:04 $
9   Version:   $Revision: 1.2 $
10
11   Copyright: (c) 2002, 2003
12   License:
13
14      This software is distributed WITHOUT ANY WARRANTY; without even
15      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16      PURPOSE.  See the above copyright notice for more information.
17
18 =========================================================================*/
19
20 #include <vtkMetaImageReader.h>
21 #include <vtkImageCast.h>
22
23 #include "vtkImageLuminance.h"
24 #include "vtkImageAppendComponents.h"
25 #include "vtkSmartPointer.h"
26
27 #include <map>
28
29 using namespace std;
30
31 /**
32 **      Start of the manager class
33 **/
34 VolumeRendererManager::VolumeRendererManager(){
35         _renderer = NULL;
36         _idCount=0;
37 }
38 VolumeRendererManager::~VolumeRendererManager(){
39     _renderer = 0;
40     _idCount=0;
41     image = 0;
42     for(unsigned i = 0; i < prop3Dvect.size();i++){
43         prop3Dvect[i]->Delete();
44     }
45     prop3Dvect.clear();
46 }
47
48 /**
49 **      Sets the renderer to manage the prop3D from the view
50 **/
51 void VolumeRendererManager::setRenderer(vtkRenderer*  renderer){
52         _renderer = renderer;
53 }
54
55 /**
56 ** Gets the renderer which manage the prop3D from the view
57 **/
58 vtkRenderer* VolumeRendererManager::getRenderer(){
59         return _renderer;
60 }
61
62 /**
63 ** Updates Volume
64 **/
65 void VolumeRendererManager::Update(int ppid){
66         VolumeRendererManagerData* data = this->getViewData(ppid);
67         data->Update();
68         _renderer->Render();
69 }
70
71 /**
72 * @pre   The image can have one or multiple components per voxel, and volume rendering is performed seprately over the
73          three of them. If the image has multiple components and the separate components flag is set to false, then
74          the vtkImageAppendComponents is used to create a single image.
75 * @post  The volume rendering is performed over the image vol
76 * @param vtkImageData* the image volume
77 * @param bool separatecomponents, if the image has multiple components, then a mapper is used for each of the channels
78               if this flag is set to false and the volume has multiple components, vtkImageAppendComponents is used to create
79               a single representation of the image.
80 */
81 int VolumeRendererManager::addVolume(vtkImageData* img, vtkRenderWindowInteractor* interactor, bool independentcomponents){
82     if(img->GetNumberOfScalarComponents() > 1 && !independentcomponents){
83
84
85         image = img;
86
87
88         vtkSmartPointer< vtkImageLuminance > luminance = vtkSmartPointer< vtkImageLuminance >::New();
89         luminance->SetInput(img);
90         luminance->Update();
91
92         vtkSmartPointer< vtkImageAppendComponents > append = vtkSmartPointer< vtkImageAppendComponents >::New();
93         append->SetInput(0, img);
94         append->SetInput(1, luminance->GetOutput());
95         append->Update();
96
97
98
99         VolumeRendererManagerData* data = new VolumeRendererManagerData(append->GetOutput(), true);
100         data->SetIndependentComponents(independentcomponents);
101
102
103         prop3Dvect.push_back(data);
104
105         data->setId(_idCount);
106         _idCount++;
107
108         return _idCount-1;
109
110
111         /*image = img;
112
113         vector< vtkImageData* > vectimg;
114         GetImages(img, vectimg);
115         vtkBoxWidget* boxw = 0;
116         for(unsigned i = 0; i < vectimg.size(); i++){
117             VolumeRendererManagerData* data = new VolumeRendererManagerData(vectimg[i], "");
118
119             vtkColorTransferFunction* colorf = data->GetColorFunction();
120             colorf->RemoveAllPoints();
121             double r = 0, g = 0, b = 0;
122             for(unsigned j = 0; j < 255; j++){
123
124                 if(i == 0){
125                     r = j/255.0;
126                     g = 0;
127                     b = 0;
128                 }else if(i == 1){
129                     r = 0;
130                     g = j/255.0;
131                     b = 0;
132                 }else if(i == 2){
133                     r = 0;
134                     g = 0;
135                     b = j/255.0;
136                 }
137
138                 colorf->AddRGBPoint(j, r, g, b);
139             }
140
141             prop3Dvect.push_back(data);
142
143             data->setId(_idCount);
144             _idCount++;
145
146             if(!boxw){
147                 EnableBoundingBox(interactor, data->getId());
148                 DisableBoundingBox(data->getId());
149                 boxw = data->GetBoxWidget();
150             }else{
151                 data->SetBoxWidget(boxw);
152             }
153         }
154
155         boxw->RemoveAllObservers();
156
157         vtkBoxWidgetCallback *callback = vtkBoxWidgetCallback::New();
158
159         for(unsigned i = 0; i < prop3Dvect.size(); i++){
160             VolumeRendererManagerData* data = prop3Dvect[i];
161             callback->AddMapper(data->GetVolumeMapper());
162         }
163
164         boxw->AddObserver(vtkCommand::InteractionEvent, callback);
165         callback->Delete();
166
167         return _idCount-1;*/
168
169         /*vtkImageData* imgshort = 0;
170         imgshort = vtkImageData::New();
171         imgshort->SetNumberOfScalarComponents(1);
172         imgshort->SetExtent(img->GetExtent());
173         imgshort->SetSpacing(img->GetSpacing());
174         imgshort->SetOrigin(img->GetOrigin());
175         imgshort->SetScalarTypeToUnsignedShort();
176         imgshort->AllocateScalars();
177         GetImageDouble(img, imgshort);
178
179         VolumeRendererManagerData* data = new VolumeRendererManagerData(imgshort, "");
180
181         vtkColorTransferFunction* colorf = data->GetColorFunction();
182         colorf->RemoveAllPoints();
183
184         map< unsigned short, vector< double > > colormap;
185
186         int *extent = img->GetExtent();
187
188         for(unsigned i = extent[0]; i < extent[1]; i++){
189             for(unsigned j = extent[2]; j < extent[3]; j++){
190                 for(unsigned k = extent[4]; k < extent[5]; k++){
191
192                     unsigned char *imgpoint = ((unsigned char*)img->GetScalarPointer(i, j, k));
193                     double temp = (double)(0.299*imgpoint[0] + 0.587*imgpoint[1] + 0.114*imgpoint[2]);
194                     unsigned short val = temp*255.0;
195
196                     vector< double > rgb;
197                     rgb.push_back(0.299*imgpoint[0]);
198                     rgb.push_back(0.587*imgpoint[1]);
199                     rgb.push_back(0.114*imgpoint[2]);
200
201                     colormap[val] = rgb;
202                 }
203             }
204         }
205
206
207
208         map< unsigned short, vector< double > >::iterator it;
209         for(it = colormap.begin(); it != colormap.end(); ++it){
210
211             colorf->AddRGBPoint((*it).first, (*it).second[0] / 255.0, (*it).second[1] / 255.0, (*it).second[2] / 255.0);
212         }
213
214         prop3Dvect.push_back(data);
215
216         data->setId(_idCount);
217         EnableBoundingBox(interactor, data->getId());
218         DisableBoundingBox(data->getId());
219         _idCount++;*/
220
221
222     }else{
223         image = img;
224
225         VolumeRendererManagerData* data = new VolumeRendererManagerData(img, "");
226         prop3Dvect.push_back(data);
227
228
229         data->setId(_idCount);
230         _idCount++;
231
232         EnableBoundingBox(interactor, data->getId());
233         DisableBoundingBox(data->getId());
234
235
236
237         return data->getId();
238
239     }
240 }
241
242 /**
243   *  @pre the image is not null and has more than one scalar component
244   *  @post Each component in the image is put in a single image
245   *  @param vtkImageData* img, multiple component image i.e. an image of vectors like an rgb
246   *  @return vtkImageData* double type image
247   */
248 void VolumeRendererManager::GetImageDouble(vtkImageData* img, vtkImageData* imgushort){
249
250
251     int *extent = img->GetExtent();
252
253     for(unsigned i = extent[0]; i < extent[1]; i++){
254         for(unsigned j = extent[2]; j < extent[3]; j++){
255             for(unsigned k = extent[4]; k < extent[5]; k++){
256                 if(img->GetScalarType() == VTK_UNSIGNED_CHAR){
257                     unsigned char *imgpoint = ((unsigned char*)img->GetScalarPointer(i, j, k));
258
259                     unsigned short *vectimgpoint = (unsigned short*)imgushort->GetScalarPointer(i, j, k);
260                     double temp = (double)(0.299*imgpoint[0] + 0.587*imgpoint[1] + 0.114*imgpoint[2]);
261                     *vectimgpoint = temp*255.0;
262
263                 }
264             }
265         }
266     }
267 }
268
269 /**
270   *  @pre the image is not null and has more than one scalar component
271   *  @post Each component in the image is separated to form a different image
272   *  @param vtkImageData* img, multiple component image i.e. an image of vectors like an rgb
273   *  @return vector<vtkImageData* > a vector of images, one for each component
274   */
275 void VolumeRendererManager::GetImages(vtkImageData* img, vector<vtkImageData* >& vectimg){
276
277     for(unsigned i = 0; i < img->GetNumberOfScalarComponents(); i++){
278         vectimg.push_back(vtkImageData::New());
279         vectimg[i]->SetNumberOfScalarComponents(1);
280         vectimg[i]->SetExtent(img->GetExtent());
281         vectimg[i]->SetSpacing(img->GetSpacing());
282         vectimg[i]->SetOrigin(img->GetOrigin());
283         vectimg[i]->SetScalarType(img->GetScalarType());
284         vectimg[i]->AllocateScalars();
285     }
286
287     int *extent = img->GetExtent();
288
289     for(unsigned i = extent[0]; i < extent[1]; i++){
290         for(unsigned j = extent[2]; j < extent[3]; j++){
291             for(unsigned k = extent[4]; k < extent[5]; k++){
292                 if(img->GetScalarType() == VTK_UNSIGNED_CHAR){
293                     unsigned char *imgpoint = ((unsigned char*)img->GetScalarPointer(i, j, k));
294
295                     for(unsigned l = 0; l < vectimg.size(); l++){
296                         unsigned char *vectimgpoint = (unsigned char*)vectimg[l]->GetScalarPointer(i, j, k);
297                         *vectimgpoint = imgpoint[l];
298                     }
299                 }else if(img->GetScalarType() == VTK_CHAR){
300                     char *imgpoint = ((char*)img->GetScalarPointer(i, j, k));
301
302                    for(unsigned l = 0; l < vectimg.size(); l++){
303                         char *vectimgpoint = ( char*)vectimg[l]->GetScalarPointer(i, j, k);
304                        *vectimgpoint = imgpoint[l];
305                    }
306                }else if(img->GetScalarType() == VTK_UNSIGNED_SHORT){
307                     unsigned short *imgpoint = ((unsigned short*)img->GetScalarPointer(i, j, k));
308
309                     for(unsigned l = 0; l < vectimg.size(); l++){
310                         unsigned short *vectimgpoint = (unsigned short*)vectimg[l]->GetScalarPointer(i, j, k);
311                         *vectimgpoint = imgpoint[l];
312                     }
313                 }else if(img->GetScalarType() == VTK_SHORT){
314                      short *imgpoint = ((short*)img->GetScalarPointer(i, j, k));
315
316                     for(unsigned l = 0; l < vectimg.size(); l++){
317                          short *vectimgpoint = ( short*)vectimg[l]->GetScalarPointer(i, j, k);
318                         *vectimgpoint = imgpoint[l];
319                     }
320                 }
321             }
322         }
323     }
324 }
325
326 /**
327 **      Adds a prop3D to the manager and returns the identifier
328 **/
329 int VolumeRendererManager::addVolume(int idTP, vtkImageData* vol, std::string dataname) throw(char*){
330         checkInvariant();
331         image = vol;
332         if(vol != NULL){
333                 VolumeRendererManagerData* data = new VolumeRendererManagerData(vol, dataname);
334                 prop3Dvect.push_back(data);
335                 _renderer->AddActor(data->getProp3D());
336                 if(idTP == -1)
337                 {
338                         data->setId(_idCount);
339                         _idCount++;
340                 }
341                 else
342                 {
343                         data->setId(idTP);
344                 }
345                 printf("VolumeRendererManager::addVolume->idVolumeRenderer: %i\n", data->getId());
346                 return data->getId();
347         }else{
348                 throw "Check mhd imagefile file or input";
349         }
350         return -1;
351 }
352 /**
353 **      adds or removes an actor depending of the bool value
354 **/
355
356 void VolumeRendererManager::addRemoveActor(int propid, bool addremove)  throw(char*){
357         checkInvariant();
358
359         VolumeRendererManagerData* data = this->getViewData(propid);
360         if(data->getProp3D()!=NULL){
361                 if(addremove){
362                         _renderer->AddViewProp(data->getProp3D());
363                 }else{
364                         _renderer->RemoveViewProp(data->getProp3D());
365                 }
366                 _renderer->Render();
367         }
368
369 }
370 /**
371 **      Changes the opacity in a prop3D
372 **/
373 void VolumeRendererManager::setVolumeOpacity(int propid, std::vector<double> greylevel,std::vector<double> value)  throw(char*){
374         checkInvariant();
375
376         this->getViewData(propid)->setVolumeOpacity(greylevel, value);
377
378         _renderer->Render();
379
380 }
381
382 /**
383 **      Set Volume Color
384 **/
385 void VolumeRendererManager::setVolumeColor(int volid, std::vector<double> greylevel,
386                                                                 std::vector<double> red,
387                                                                 std::vector<double> green,
388                                                                 std::vector<double> blue)throw(char*){
389         checkInvariant();
390
391         this->getViewData(volid)->setVolumeColor(greylevel, red, green, blue);
392
393         _renderer->Render();
394 }
395
396 vtkImageData* VolumeRendererManager::getImageData(std::string filename){
397         if(filename.compare("")!= 0){
398
399                 vtkMetaImageReader* reader =  vtkMetaImageReader::New();
400                 reader->SetFileName(filename.c_str());
401                 reader->Update();
402                 vtkImageData* img = reader->GetOutput();
403
404                 vtkImageCast* cast = vtkImageCast::New();
405                 cast->SetInput(img);
406                 cast->SetOutputScalarTypeToUnsignedShort();
407                 cast->Update();
408                 //reader->Delete();
409                 //img->Delete();
410                 return cast->GetOutput();
411                 //return img;
412         }
413         return NULL;
414 }
415
416 vtkImageData* VolumeRendererManager::getImageData(){
417         return image;
418 }
419
420 void VolumeRendererManager::checkInvariant()  throw(char*){
421         if(this->_renderer==NULL){
422                 throw "Renderer not set";
423         }
424 }
425
426 VolumeRendererManagerData* VolumeRendererManager::getViewData(int id) throw(char*){
427     int i;
428         for(i = 0; i < (int)(prop3Dvect.size());i++){
429                 if(prop3Dvect[i]->getId() == id){
430                         return prop3Dvect[i];
431                 }
432         }
433         throw "id not found in the data";
434
435         return NULL;
436 }
437
438 void VolumeRendererManager::deleteActor(int propid) throw (char *){
439         checkInvariant();
440
441         this->addRemoveActor(propid, false);
442
443         int i,n;
444         bool exit = false;
445         for(i = 0; i < (int)(prop3Dvect.size())&&!exit;i++){
446                 if(prop3Dvect[i]->getId() == propid){
447                         n=i;
448                         exit = true;
449                 }
450         }
451         if(exit){
452                 VolumeRendererManagerData* data = prop3Dvect[n];
453                 int j;
454                 for(j = i; j < (int)(prop3Dvect.size())-1;j++){
455                         prop3Dvect[j] = prop3Dvect[j+1];
456                 }
457                 delete data;
458                 prop3Dvect.pop_back();
459         }else{
460                 throw "id not found in the data";
461         }
462
463 }
464
465 vtkPiecewiseFunction* VolumeRendererManager::GetTransferFunction(int volumeid){
466         return getViewData(volumeid)->GetTransferFunction();
467 }
468 vtkColorTransferFunction* VolumeRendererManager::GetColorFunction(int volumeid){
469
470         return getViewData(volumeid)->GetColorFunction();
471 }
472
473 void VolumeRendererManager::changeCompositeMIPFunction(int id, int function) throw (char *){
474     if(id == -1){
475         for(unsigned i = 0; i < prop3Dvect.size(); i++)
476             prop3Dvect[i]->changeCompositeMIPFunction(function);
477     }else{
478         getViewData(id)->changeCompositeMIPFunction(function);
479     }
480 }
481
482 /**
483   Changes the interpolation of the volume rendering.
484   type == 0 for linear interpolation
485   type == 1 for nearest interpolation
486   */
487 void VolumeRendererManager::changeInterpolationType(int type, int propid){
488     if(propid == -1){
489         for(unsigned i = 0; i < prop3Dvect.size(); i++)
490             prop3Dvect[i]->changeInterpolationType(type);
491     }else{
492         getViewData(propid)->changeInterpolationType(type);
493     }
494 }
495
496 /**
497   * Set the lookuptable to the volumes in memory
498   * if the id is set then it only changes the lookup table for a specific volume
499  */
500 void VolumeRendererManager::SetLookupTable(vtkLookupTable* lookup, int id){
501     if(id == -1){
502         for(unsigned i = 0; i < prop3Dvect.size(); i++)
503             prop3Dvect[i]->SetLookupTable(lookup);
504     }else{
505         getViewData(id)->SetLookupTable(lookup);
506     }
507
508 }
509
510 /**
511   * @returns all the props3D in this manager
512 */
513 vector< vtkProp3D* > VolumeRendererManager::getProps3D(){
514
515     vector< vtkProp3D* >  propvects;
516     for(unsigned i = 0; i < prop3Dvect.size(); i++){
517         propvects.push_back(prop3Dvect[i]->getProp3D());
518     }
519     return propvects;
520 }
521
522 /**
523   *  @param std::vector<double> greylevel, the corresponding greylevel in the image
524   *  @param std::vector<double> value, the corresponding value for the opacity
525   *  @param int propid, the correspoding id, by default it applies the changes to the first volume in the array
526   */
527 void VolumeRendererManager::setVolumeOpacity(std::vector<double> greylevel, std::vector<double> value, int propid){
528     if(propid == -1){
529         for(unsigned i = 0; i < prop3Dvect.size(); i++)
530             prop3Dvect[i]->setVolumeOpacity(greylevel, value);
531     }else{
532         getViewData(propid)->setVolumeOpacity(greylevel, value);
533     }
534 }
535
536 void VolumeRendererManager::EnableBoundingBox(vtkRenderWindowInteractor* interactor, int propid){
537     if(propid == -1){
538         for(unsigned i = 0; i < prop3Dvect.size(); i++)
539             prop3Dvect[i]->EnableBoundingBox(interactor);
540     }else{
541         getViewData(propid)->EnableBoundingBox(interactor);
542     }
543 }
544
545 void VolumeRendererManager::DisableBoundingBox(int propid){
546
547     if(propid == -1){
548         for(unsigned i = 0; i < prop3Dvect.size(); i++)
549             prop3Dvect[i]->DisableBoundingBox();
550     }else{
551         getViewData(propid)->DisableBoundingBox();
552     }
553 }