]> Creatis software - creaMaracasVisu.git/blob - lib/Kernel/VTKObjects/VolumeRenderer/volumerenderermanager.cxx
#3109 creaMaracasVisu Bug New Normal - branch vtk7itk4 compilation with vtk7
[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 //EED 2017-01-01 Migration VTK7
115 #if VTK_MAJOR_VERSION <= 5
116         luminance->SetInput(img);
117 #else
118         luminance->SetInputData(img);
119 #endif
120
121         luminance->Update();
122
123         vtkSmartPointer< vtkImageAppendComponents > append = vtkSmartPointer< vtkImageAppendComponents >::New();
124
125 //EED 2017-01-01 Migration VTK7
126 #if VTK_MAJOR_VERSION <= 5
127         append->SetInput(0, img);
128         append->SetInput(1, luminance->GetOutput());
129 #else
130         append->SetInputData(0, img);
131         append->SetInputData(1, luminance->GetOutput());
132 #endif
133
134         append->Update();
135
136
137
138         VolumeRendererManagerData* data = new VolumeRendererManagerData(append->GetOutput(), true);
139         data->SetIndependentComponents(independentcomponents);
140
141
142         prop3Dvect.push_back(data);
143
144         data->setId(_idCount);
145         _idCount++;
146
147         return _idCount-1;
148
149
150         /*image = img;
151
152         vector< vtkImageData* > vectimg;
153         GetImages(img, vectimg);
154         vtkBoxWidget* boxw = 0;
155         for(unsigned i = 0; i < vectimg.size(); i++){
156             VolumeRendererManagerData* data = new VolumeRendererManagerData(vectimg[i], "");
157
158             vtkColorTransferFunction* colorf = data->GetColorFunction();
159             colorf->RemoveAllPoints();
160             double r = 0, g = 0, b = 0;
161             for(unsigned j = 0; j < 255; j++){
162
163                 if(i == 0){
164                     r = j/255.0;
165                     g = 0;
166                     b = 0;
167                 }else if(i == 1){
168                     r = 0;
169                     g = j/255.0;
170                     b = 0;
171                 }else if(i == 2){
172                     r = 0;
173                     g = 0;
174                     b = j/255.0;
175                 }
176
177                 colorf->AddRGBPoint(j, r, g, b);
178             }
179
180             prop3Dvect.push_back(data);
181
182             data->setId(_idCount);
183             _idCount++;
184
185             if(!boxw){
186                 EnableBoundingBox(interactor, data->getId());
187                 DisableBoundingBox(data->getId());
188                 boxw = data->GetBoxWidget();
189             }else{
190                 data->SetBoxWidget(boxw);
191             }
192         }
193
194         boxw->RemoveAllObservers();
195
196         vtkBoxWidgetCallback *callback = vtkBoxWidgetCallback::New();
197
198         for(unsigned i = 0; i < prop3Dvect.size(); i++){
199             VolumeRendererManagerData* data = prop3Dvect[i];
200             callback->AddMapper(data->GetVolumeMapper());
201         }
202
203         boxw->AddObserver(vtkCommand::InteractionEvent, callback);
204         callback->Delete();
205
206         return _idCount-1;*/
207
208         /*vtkImageData* imgshort = 0;
209         imgshort = vtkImageData::New();
210         imgshort->SetNumberOfScalarComponents(1);
211         imgshort->SetExtent(img->GetExtent());
212         imgshort->SetSpacing(img->GetSpacing());
213         imgshort->SetOrigin(img->GetOrigin());
214         imgshort->SetScalarTypeToUnsignedShort();
215         imgshort->AllocateScalars();
216         GetImageDouble(img, imgshort);
217
218         VolumeRendererManagerData* data = new VolumeRendererManagerData(imgshort, "");
219
220         vtkColorTransferFunction* colorf = data->GetColorFunction();
221         colorf->RemoveAllPoints();
222
223         map< unsigned short, vector< double > > colormap;
224
225         int *extent = img->GetExtent();
226
227         for(unsigned i = extent[0]; i < extent[1]; i++){
228             for(unsigned j = extent[2]; j < extent[3]; j++){
229                 for(unsigned k = extent[4]; k < extent[5]; k++){
230
231                     unsigned char *imgpoint = ((unsigned char*)img->GetScalarPointer(i, j, k));
232                     double temp = (double)(0.299*imgpoint[0] + 0.587*imgpoint[1] + 0.114*imgpoint[2]);
233                     unsigned short val = temp*255.0;
234
235                     vector< double > rgb;
236                     rgb.push_back(0.299*imgpoint[0]);
237                     rgb.push_back(0.587*imgpoint[1]);
238                     rgb.push_back(0.114*imgpoint[2]);
239
240                     colormap[val] = rgb;
241                 }
242             }
243         }
244
245
246
247         map< unsigned short, vector< double > >::iterator it;
248         for(it = colormap.begin(); it != colormap.end(); ++it){
249
250             colorf->AddRGBPoint((*it).first, (*it).second[0] / 255.0, (*it).second[1] / 255.0, (*it).second[2] / 255.0);
251         }
252
253         prop3Dvect.push_back(data);
254
255         data->setId(_idCount);
256         EnableBoundingBox(interactor, data->getId());
257         DisableBoundingBox(data->getId());
258         _idCount++;*/
259
260
261     }else{
262         image = img;
263
264         VolumeRendererManagerData* data = new VolumeRendererManagerData(img, "");
265         prop3Dvect.push_back(data);
266
267
268         data->setId(_idCount);
269         _idCount++;
270
271         EnableBoundingBox(interactor, data->getId());
272         DisableBoundingBox(data->getId());
273
274
275
276         return data->getId();
277
278     }
279 }
280
281 /**
282   *  @pre the image is not null and has more than one scalar component
283   *  @post Each component in the image is put in a single image
284   *  @param vtkImageData* img, multiple component image i.e. an image of vectors like an rgb
285   *  @return vtkImageData* double type image
286   */
287 void VolumeRendererManager::GetImageDouble(vtkImageData* img, vtkImageData* imgushort){
288
289
290     int *extent = img->GetExtent();
291
292     for(unsigned i = extent[0]; i < extent[1]; i++){
293         for(unsigned j = extent[2]; j < extent[3]; j++){
294             for(unsigned k = extent[4]; k < extent[5]; k++){
295                 if(img->GetScalarType() == VTK_UNSIGNED_CHAR){
296                     unsigned char *imgpoint = ((unsigned char*)img->GetScalarPointer(i, j, k));
297
298                     unsigned short *vectimgpoint = (unsigned short*)imgushort->GetScalarPointer(i, j, k);
299                     double temp = (double)(0.299*imgpoint[0] + 0.587*imgpoint[1] + 0.114*imgpoint[2]);
300                     *vectimgpoint = temp*255.0;
301
302                 }
303             }
304         }
305     }
306 }
307
308 /**
309   *  @pre the image is not null and has more than one scalar component
310   *  @post Each component in the image is separated to form a different image
311   *  @param vtkImageData* img, multiple component image i.e. an image of vectors like an rgb
312   *  @return vector<vtkImageData* > a vector of images, one for each component
313   */
314 void VolumeRendererManager::GetImages(vtkImageData* img, vector<vtkImageData* >& vectimg){
315
316     for(unsigned i = 0; i < img->GetNumberOfScalarComponents(); i++){
317         vectimg.push_back(vtkImageData::New());
318         vectimg[i]->SetExtent(img->GetExtent());
319         vectimg[i]->SetSpacing(img->GetSpacing());
320         vectimg[i]->SetOrigin(img->GetOrigin());
321
322 //EED 2017-01-01 Migration VTK7
323 #if VTK_MAJOR_VERSION <= 5
324         vectimg[i]->SetNumberOfScalarComponents(1);
325         vectimg[i]->SetScalarType(img->GetScalarType());
326         vectimg[i]->AllocateScalars();
327 #else
328         vectimg[i]->AllocateScalars(img->GetScalarType(),1);
329 #endif
330
331     }
332
333     int *extent = img->GetExtent();
334
335     for(unsigned i = extent[0]; i < extent[1]; i++){
336         for(unsigned j = extent[2]; j < extent[3]; j++){
337             for(unsigned k = extent[4]; k < extent[5]; k++){
338                 if(img->GetScalarType() == VTK_UNSIGNED_CHAR){
339                     unsigned char *imgpoint = ((unsigned char*)img->GetScalarPointer(i, j, k));
340
341                     for(unsigned l = 0; l < vectimg.size(); l++){
342                         unsigned char *vectimgpoint = (unsigned char*)vectimg[l]->GetScalarPointer(i, j, k);
343                         *vectimgpoint = imgpoint[l];
344                     }
345                 }else if(img->GetScalarType() == VTK_CHAR){
346                     char *imgpoint = ((char*)img->GetScalarPointer(i, j, k));
347
348                    for(unsigned l = 0; l < vectimg.size(); l++){
349                         char *vectimgpoint = ( char*)vectimg[l]->GetScalarPointer(i, j, k);
350                        *vectimgpoint = imgpoint[l];
351                    }
352                }else if(img->GetScalarType() == VTK_UNSIGNED_SHORT){
353                     unsigned short *imgpoint = ((unsigned short*)img->GetScalarPointer(i, j, k));
354
355                     for(unsigned l = 0; l < vectimg.size(); l++){
356                         unsigned short *vectimgpoint = (unsigned short*)vectimg[l]->GetScalarPointer(i, j, k);
357                         *vectimgpoint = imgpoint[l];
358                     }
359                 }else if(img->GetScalarType() == VTK_SHORT){
360                      short *imgpoint = ((short*)img->GetScalarPointer(i, j, k));
361
362                     for(unsigned l = 0; l < vectimg.size(); l++){
363                          short *vectimgpoint = ( short*)vectimg[l]->GetScalarPointer(i, j, k);
364                         *vectimgpoint = imgpoint[l];
365                     }
366                 }
367             }
368         }
369     }
370 }
371
372 /**
373 **      Adds a prop3D to the manager and returns the identifier
374 **/
375 int VolumeRendererManager::addVolume(int idTP, vtkImageData* vol, std::string dataname) throw(char*){
376         checkInvariant();
377         image = vol;
378         if(vol != NULL){
379                 VolumeRendererManagerData* data = new VolumeRendererManagerData(vol, dataname);
380                 prop3Dvect.push_back(data);
381                 _renderer->AddActor(data->getProp3D());
382                 if(idTP == -1)
383                 {
384                         data->setId(_idCount);
385                         _idCount++;
386                 }
387                 else
388                 {
389                         data->setId(idTP);
390                 }
391                 printf("VolumeRendererManager::addVolume->idVolumeRenderer: %i\n", data->getId());
392                 return data->getId();
393         }else{
394                 throw "Check mhd imagefile file or input";
395         }
396         return -1;
397 }
398 /**
399 **      adds or removes an actor depending of the bool value
400 **/
401
402 void VolumeRendererManager::addRemoveActor(int propid, bool addremove)  throw(char*){
403         checkInvariant();
404
405         VolumeRendererManagerData* data = this->getViewData(propid);
406         if(data->getProp3D()!=NULL){
407                 if(addremove){
408                         _renderer->AddViewProp(data->getProp3D());
409                 }else{
410                         _renderer->RemoveViewProp(data->getProp3D());
411                 }
412                 _renderer->Render();
413         }
414
415 }
416 /**
417 **      Changes the opacity in a prop3D
418 **/
419 void VolumeRendererManager::setVolumeOpacity(int propid, std::vector<double> greylevel,std::vector<double> value)  throw(char*){
420         checkInvariant();
421
422         printf("EED VolumeRendererManager::setVolumeOpacity %d\n",propid);
423         
424         VolumeRendererManagerData* volrenman = this->getViewData(propid);
425         if (volrenman!=NULL) 
426         {
427         volrenman->setVolumeOpacity(greylevel, value);
428         } else {
429                 printf("EED  VolumeRendererManager::setVolumeOpacity  Warning volrenman NULL\n");
430         }
431         
432         _renderer->Render();
433
434 }
435
436 /**
437 **      Set Volume Color
438 **/
439
440 void VolumeRendererManager::setVolumeColor(int volid, std::vector<double> greylevel,
441                                                                 std::vector<double> red,
442                                                                 std::vector<double> green,
443                                                                 std::vector<double> blue)throw(char*){
444         printf("EED VolumeRendererManager::setVolumeColor  start \n");
445         checkInvariant();
446
447         printf("EED VolumeRendererManager::setVolumeColor %d\n",volid);
448         
449         VolumeRendererManagerData* volrenman = this->getViewData(volid);
450         if (volrenman!=NULL) 
451         {
452                 this->getViewData(volid)->setVolumeColor(greylevel, red, green, blue);
453         } else {
454                 printf("EED  VolumeRendererManager::setVolumeColor  Warning volrenman NULL\n");
455         }
456
457         _renderer->Render();
458         printf("EED VolumeRendererManager::setVolumeColor  end \n");
459 }
460
461 vtkImageData* VolumeRendererManager::getImageData(std::string filename){
462         if(filename.compare("")!= 0){
463
464                 vtkMetaImageReader* reader =  vtkMetaImageReader::New();
465                 reader->SetFileName(filename.c_str());
466                 reader->Update();
467                 vtkImageData* img = reader->GetOutput();
468
469                 vtkImageCast* cast = vtkImageCast::New();
470 //EED 2017-01-01 Migration VTK7
471 #if VTK_MAJOR_VERSION <= 5
472                 cast->SetInput(img);
473 #else
474                 cast->SetInputData(img);
475 #endif
476
477                 cast->SetOutputScalarTypeToUnsignedShort();
478                 cast->Update();
479                 //reader->Delete();
480                 //img->Delete();
481                 return cast->GetOutput();
482                 //return img;
483         }
484         return NULL;
485 }
486
487 vtkImageData* VolumeRendererManager::getImageData(){
488         return image;
489 }
490
491 void VolumeRendererManager::checkInvariant()  throw(char*){
492         printf("EED VolumeRendererManager::checkInvariant start\n");
493         if(this->_renderer==NULL){
494                 throw "Renderer not set";
495         }
496         printf("EED VolumeRendererManager::checkInvariant end \n");
497 }
498
499 VolumeRendererManagerData* VolumeRendererManager::getViewData(int id) throw(char*){
500     int i;
501         for(i = 0; i < (int)(prop3Dvect.size());i++){
502                 if(prop3Dvect[i]->getId() == id){
503                         return prop3Dvect[i];
504                 }
505         }
506         throw "id not found in the data";
507
508         return NULL;
509 }
510
511 void VolumeRendererManager::deleteActor(int propid) throw (char *){
512         checkInvariant();
513
514         this->addRemoveActor(propid, false);
515
516         int i,n;
517         bool exit = false;
518         for(i = 0; i < (int)(prop3Dvect.size())&&!exit;i++){
519                 if(prop3Dvect[i]->getId() == propid){
520                         n=i;
521                         exit = true;
522                 }
523         }
524         if(exit){
525                 VolumeRendererManagerData* data = prop3Dvect[n];
526                 int j;
527                 for(j = i; j < (int)(prop3Dvect.size())-1;j++){
528                         prop3Dvect[j] = prop3Dvect[j+1];
529                 }
530                 delete data;
531                 prop3Dvect.pop_back();
532         }else{
533                 throw "id not found in the data";
534         }
535
536 }
537
538 vtkPiecewiseFunction* VolumeRendererManager::GetTransferFunction(int volumeid){
539         return getViewData(volumeid)->GetTransferFunction();
540 }
541 vtkColorTransferFunction* VolumeRendererManager::GetColorFunction(int volumeid){
542
543         return getViewData(volumeid)->GetColorFunction();
544 }
545
546 void VolumeRendererManager::changeCompositeMIPFunction(int id, int function) throw (char *){
547     if(id == -1){
548         for(unsigned i = 0; i < prop3Dvect.size(); i++)
549             prop3Dvect[i]->changeCompositeMIPFunction(function);
550     }else{
551         getViewData(id)->changeCompositeMIPFunction(function);
552     }
553 }
554
555 /**
556   Changes the interpolation of the volume rendering.
557   type == 0 for linear interpolation
558   type == 1 for nearest interpolation
559   */
560 void VolumeRendererManager::changeInterpolationType(int type, int propid){
561     if(propid == -1){
562         for(unsigned i = 0; i < prop3Dvect.size(); i++)
563             prop3Dvect[i]->changeInterpolationType(type);
564     }else{
565         getViewData(propid)->changeInterpolationType(type);
566     }
567 }
568
569 /**
570   * Set the lookuptable to the volumes in memory
571   * if the id is set then it only changes the lookup table for a specific volume
572  */
573 void VolumeRendererManager::SetLookupTable(vtkLookupTable* lookup, int id){
574     if(id == -1){
575         for(unsigned i = 0; i < prop3Dvect.size(); i++)
576             prop3Dvect[i]->SetLookupTable(lookup);
577     }else{
578         getViewData(id)->SetLookupTable(lookup);
579     }
580
581 }
582
583 /**
584   * @returns all the props3D in this manager
585 */
586 vector< vtkProp3D* > VolumeRendererManager::getProps3D(){
587
588     vector< vtkProp3D* >  propvects;
589     for(unsigned i = 0; i < prop3Dvect.size(); i++){
590         propvects.push_back(prop3Dvect[i]->getProp3D());
591     }
592     return propvects;
593 }
594
595 /**
596   *  @param std::vector<double> greylevel, the corresponding greylevel in the image
597   *  @param std::vector<double> value, the corresponding value for the opacity
598   *  @param int propid, the correspoding id, by default it applies the changes to the first volume in the array
599   */
600 void VolumeRendererManager::setVolumeOpacity(std::vector<double> greylevel, std::vector<double> value, int propid){
601     if(propid == -1){
602         for(unsigned i = 0; i < prop3Dvect.size(); i++)
603             prop3Dvect[i]->setVolumeOpacity(greylevel, value);
604     }else{
605         getViewData(propid)->setVolumeOpacity(greylevel, value);
606     }
607 }
608
609 void VolumeRendererManager::EnableBoundingBox(vtkRenderWindowInteractor* interactor, int propid){
610     if(propid == -1){
611         for(unsigned i = 0; i < prop3Dvect.size(); i++)
612             prop3Dvect[i]->EnableBoundingBox(interactor);
613     }else{
614         getViewData(propid)->EnableBoundingBox(interactor);
615     }
616 }
617
618 void VolumeRendererManager::DisableBoundingBox(int propid){
619
620     if(propid == -1){
621         for(unsigned i = 0; i < prop3Dvect.size(); i++)
622             prop3Dvect[i]->DisableBoundingBox();
623     }else{
624         getViewData(propid)->DisableBoundingBox();
625     }
626 }