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