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