]> Creatis software - bbtk.git/blob - packages/vtk/src/bbvtkImagePlanes.cxx
426189b031cf5d428edce3cc1b4cb5235d4d22d3
[bbtk.git] / packages / vtk / src / bbvtkImagePlanes.cxx
1 /*=========================================================================                                                                               
2   Program:   bbtk
3   Module:    $RCSfile: bbvtkImagePlanes.cxx,v $
4   Language:  C++
5   Date:      $Date: 2012/07/09 13:02:42 $
6   Version:   $Revision: 1.37 $
7 =========================================================================*/
8
9 /* ---------------------------------------------------------------------
10
11 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
12 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
13 *
14 *  This software is governed by the CeCILL-B license under French law and 
15 *  abiding by the rules of distribution of free software. You can  use, 
16 *  modify and/ or redistribute the software under the terms of the CeCILL-B 
17 *  license as circulated by CEA, CNRS and INRIA at the following URL 
18 *  http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html 
19 *  or in the file LICENSE.txt.
20 *
21 *  As a counterpart to the access to the source code and  rights to copy,
22 *  modify and redistribute granted by the license, users are provided only
23 *  with a limited warranty  and the software's author,  the holder of the
24 *  economic rights,  and the successive licensors  have only  limited
25 *  liability. 
26 *
27 *  The fact that you are presently reading this means that you have had
28 *  knowledge of the CeCILL-B license and that you accept its terms.
29 * ------------------------------------------------------------------------ */                                                                         
30
31 /**
32  *  \file 
33  *  \brief 
34  */
35
36 #ifdef _USE_VTK_
37 #include "bbvtkImagePlanes.h"
38 #include "bbvtkPackage.h"
39 #include "vtkCellPicker.h"
40 #include "vtkProperty.h"
41 #include "vtkPolyData.h"
42
43
44 #include "vtkMetaImageWriter.h"
45 #include "vtkPNGWriter.h"
46
47 #include "bbstdCast.h"
48 #include <vtkCommand.h>
49
50 #include "vtkImageData.h"
51 //#include "vtkOutlineFilter.h"
52 //#include "vtkPolyDataMapper.h"
53 //#include "vtkActor.h"
54 #include "vtkImagePlaneWidget.h"
55 #include "vtkCellPicker.h"
56 //#include "vtkProperty.h"
57
58 //#include "vtkRenderer.h"
59 //#include "vtkCamera.h"
60
61 #include "vtkPlaneWidget.h"
62
63 #include <vtkImplicitPlaneWidget.h>
64
65 #include "bbstdRelay.h"
66
67 #include "vtkObjectFactory.h"
68 #include "vtkImageFlip.h"
69
70 #include "vtkImageReslice.h"
71 #include "vtkImageChangeInformation.h"
72
73 namespace bbstd
74 {
75
76   //====================================================================
77   BBTK_BLACK_BOX_TEMPLATE2_IMPLEMENTATION(Cast,
78                                           bbtk::AtomicBlackBox);
79   //====================================================================
80   //====================================================================
81 //  BBTK_BLACK_BOX_TEMPLATE_IMPLEMENTATION(Relay,
82 //                                       bbtk::AtomicBlackBox);
83   //====================================================================
84
85 }
86 using namespace bbstd;
87 /*
88 namespace bbtk
89 {
90         typedef vtkImageData::Pointer vtkImageDataPointer;
91   BBTK_DEFINE_HUMAN_READABLE_TYPE_NAME(vtkImageDataPointer,
92                                        "vtkImageDataPointer");
93 }
94 */
95 namespace bbvtk
96 {
97
98   //====================================================================
99   // Add the specialized adaptors to the package
100   typedef vtkImagePlaneWidget* I;
101   typedef vtkInteractorObserver* O;
102
103   BBTK_ADD_TEMPLATE2_BLACK_BOX_TO_PACKAGE(vtk,Cast,I,O);
104
105   BBTK_DEFINE_RELAY_BLACK_BOX(vtkImageDataPointer,vtk,vtkImageDataPointerRelay);
106   BBTK_BLACK_BOX_IMPLEMENTATION(vtkImageDataPointerRelay,bbtk::AtomicBlackBox);
107
108   BBTK_ADD_BLACK_BOX_TO_PACKAGE(vtk,vtkImageDataPointerRelay);
109  // BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(vtk,Relay,vtkImageDataPointer);
110   //Pointer);
111
112 }
113
114 namespace bbvtk
115 {
116
117   //================================================================
118  class ImagePlanes::VtkCallbackType : public vtkCommand
119  {
120  public:
121    static VtkCallbackType *New()
122    {
123      return new VtkCallbackType;
124    }
125    //vtkTypeRevisionMacro(VtkCallbackType,vtkCommand);
126
127    virtual void Execute(vtkObject *caller, unsigned long, void*)
128    {
129        mBlackBox->Process();
130        mBlackBox->bbSignalOutputModification();
131    } 
132    void SetBlackBox(ImagePlanes *BB) { mBlackBox = BB;};    
133    //   void SetVtkPlaneWidget( vtkImagePlaneWidget *planeWidget );
134    VtkCallbackType() {};
135
136  private:
137    //   vtkPlaneWidget *planeWidget;
138    ImagePlanes *mBlackBox;
139  };
140   //================================================================
141
142   //vtkCxxRevisionMacro(ImagePlanes::VtkCallbackType, "$Revision: 1.37 $");
143
144   //================================================================
145
146    BBTK_ADD_BLACK_BOX_TO_PACKAGE(vtk,ImagePlanes)
147    BBTK_BLACK_BOX_IMPLEMENTATION(ImagePlanes,bbtk::AtomicBlackBox);
148
149    void ImagePlanes::bbUserSetDefaultValues() 
150    { 
151      bbSetOutputPlaneX(0);
152      bbSetOutputPlaneY(0);
153      bbSetOutputPlaneZ(0);
154      bbSetOutputImageX(0);
155      bbSetOutputImageY(0);
156      bbSetOutputImageZ(0);
157      bbSetInputIn(0);
158      std::vector<double> vect;
159      vect.push_back(0);
160      vect.push_back(0);
161      bbSetInputWindowLevel (vect);  
162      mVtkCallback = 0;
163
164      std::vector<int> vectpoints;
165
166      bbSetOutputPlane3Pts(0);
167      bbSetOutputImage3Pts(0);
168      bbSetInputPointsX(vectpoints);
169      bbSetInputPointsY(vectpoints);
170      bbSetInputPointsZ(vectpoints);
171
172      _imageReslicer = NULL;
173      image          = NULL;
174      _transform     = NULL;
175      _matrix        = NULL;
176            
177            bbSetInputInterpolation(1);     
178    }
179
180         
181    void ImagePlanes::bbUserInitializeProcessing() 
182    {  
183      /// CREATION DES WIDGETS
184      if (bbGetOutputPlaneX() != 0) return;
185        
186      // The shared picker enables us to use 3 planes at one time
187      // and gets the picking order right
188      vtkCellPicker* picker = vtkCellPicker::New();
189      picker->SetTolerance(0.005);
190   
191      // The 3 image plane widgets 
192      vtkImagePlaneWidget* planeWidgetX = GetPlaneWidget('x', 1, 0, 0, picker);
193      vtkImagePlaneWidget* planeWidgetY = GetPlaneWidget('y', 1, 1, 0, picker);
194      planeWidgetY->SetLookupTable(planeWidgetX->GetLookupTable());
195
196      vtkImagePlaneWidget* planeWidgetZ = GetPlaneWidget('z', 0, 0, 1, picker);     
197      planeWidgetZ->SetLookupTable(planeWidgetX->GetLookupTable());
198
199      vtkImagePlaneWidget* planeWidget3Pts = GetPlaneWidget('3', 0, 1, 1, picker);        
200      planeWidget3Pts->SetLookupTable(planeWidgetX->GetLookupTable());
201
202            // EED MPR view orientation correction..
203      vtkImageFlip  *flipYFilter = vtkImageFlip::New();
204      flipYFilter->SetFilteredAxis(1); // flip y axis
205      flipYFilter->SetInput( planeWidgetX->GetResliceOutput() );
206      flipYFilter->Update();
207
208            vtkImageChangeInformation *image = vtkImageChangeInformation::New();
209            image->SetInput(  planeWidgetY->GetResliceOutput()  );
210            image->SetOutputSpacing( 1,1,1 );       
211            image->CenterImageOn();
212            image->Update();
213            _imageTransform = vtkTransform::New();
214            vtkImageReslice *slicer =vtkImageReslice::New();
215            slicer->SetInput( image->GetOutput() );
216            slicer->SetInformationInput( image->GetOutput() );
217            slicer->SetResliceTransform( _imageTransform );
218            slicer->SetOutputOrigin(0 , 0 , 0 );
219            slicer->SetInterpolationModeToNearestNeighbor();
220            slicer->Update();       
221            vtkImageChangeInformation *imageResult = vtkImageChangeInformation::New();
222            imageResult->SetInput( slicer->GetOutput() );
223            double spc[3];
224             planeWidgetY->GetResliceOutput()->GetSpacing(spc);
225            imageResult->SetOutputSpacing( spc[1], spc[0], spc[2] ); 
226            imageResult->SetOutputOrigin( 0,0,0 ); 
227                    
228            
229      bbSetOutputPlaneX(planeWidgetX);
230      bbSetOutputPlaneY(planeWidgetY);
231      bbSetOutputPlaneZ(planeWidgetZ);
232      bbSetOutputPlane3Pts(planeWidget3Pts);      
233      bbSetOutputImageX( flipYFilter->GetOutput() );             // EED MPR view orientation correction..
234      bbSetOutputImageY( imageResult->GetOutput() );                     // EED MPR view orientation correction..
235      bbSetOutputImageZ(planeWidgetZ->GetResliceOutput());
236      bbSetInputInteractor(0);
237      //bbSetOutputImage3Pts(planeWidget3Pts->GetResliceOutput());
238
239          if(picker != 0)
240                 picker->UnRegister(NULL);
241      
242      mVtkCallback = VtkCallbackType::New();
243      mVtkCallback->SetBlackBox(this);
244      planeWidgetX->AddObserver(vtkCommand::InteractionEvent,mVtkCallback);
245      planeWidgetY->AddObserver(vtkCommand::InteractionEvent,mVtkCallback);
246      planeWidgetZ->AddObserver(vtkCommand::InteractionEvent,mVtkCallback);       
247
248    }
249
250 //---------------------------------------------------------------------
251   void ImagePlanes::bbUserFinalizeProcessing()
252   {
253
254     if (bbGetOutputPlaneX()) 
255       {
256
257         /*
258           bbGetOutputPlaneX()->RemoveObserver(mVtkCallback);
259           bbGetOutputPlaneY()->RemoveObserver(mVtkCallback);
260           bbGetOutputPlaneZ()->RemoveObserver(mVtkCallback);
261
262         bbGetOutputPlaneX()->Delete();
263         bbGetOutputPlaneY()->Delete();
264         bbGetOutputPlaneZ()->Delete();
265         mVtkCallback->Delete();
266         */
267         //bbGetOutputPlaneX()->SetInput(NULL);
268         //bbGetOutputPlaneY()->SetInput(NULL);
269         //bbGetOutputPlaneZ()->SetInput(NULL);
270
271       }
272   }
273   
274 //---------------------------------------------------------------------  
275   void ImagePlanes::Process()
276   {
277           
278         if (bbGetInputIn()!=0)
279         {
280                 int dim[3];
281                 int ext[6];
282                 bbGetOutputPlaneX()->GetResliceOutput()->GetWholeExtent(ext);
283                 dim[0] = ext[1]-ext[0]+1;
284                 dim[1] = ext[3]-ext[2]+1;
285                 dim[2] = ext[5]-ext[4]+1;
286                 _imageTransform->Identity();
287                 _imageTransform->PostMultiply();
288                 _imageTransform->Translate( (int)(-(dim[0]/2)) , (int)(-(dim[1]/2)) ,0);
289                 _imageTransform->RotateZ(90);
290                 
291                 
292                 if ( image != bbGetInputIn()){//bbGetInputStatus("In") != bbtk::UPTODATE ){
293                         // Input image has changed : reinitialize planes
294                         image = bbGetInputIn();                 
295
296                         // Initial values : center of the volume (in real world, not in pixels!)
297                         int xMin, xMax, yMin, yMax, zMin, zMax;
298                         bbGetInputIn()->GetExtent(xMin, xMax, yMin, yMax, zMin, zMax);
299                         double xSpacing, ySpacing, zSpacing;
300                         bbGetInputIn()->GetSpacing(xSpacing, ySpacing, zSpacing);
301
302                         bbGetOutputPlaneX()->SetInput(bbGetInputIn());
303                         bbGetOutputPlaneX()->SetPlaneOrientationToXAxes();       
304                         bbGetOutputPlaneX()->SetSlicePosition((xMax+xMin)/2.*xSpacing);
305
306                         //                 bbGetOutputPlaneX()->SetOrigin( 58*xSpacing , 80*ySpacing , 82*zSpacing );
307                         //                 bbGetOutputPlaneX()->SetPoint1( 0*xSpacing, 146*ySpacing, 186*zSpacing);
308                         //                 bbGetOutputPlaneX()->SetPoint2( 126*xSpacing, 146*ySpacing, 0*zSpacing);
309
310                         bbGetOutputPlaneY()->SetInput(bbGetInputIn());
311                         bbGetOutputPlaneY()->SetPlaneOrientationToYAxes();
312                         bbGetOutputPlaneY()->SetSlicePosition((yMax+yMin)/2.*ySpacing);
313
314                         bbGetOutputPlaneZ()->SetInput(bbGetInputIn());
315                         bbGetOutputPlaneZ()->SetPlaneOrientationToZAxes();
316                         bbGetOutputPlaneZ()->SetSlicePosition((zMax+zMin)/2.*zSpacing);
317
318                         if (bbGetInputWindowLevel()[0]!=0)
319                         {
320                                 bbGetOutputPlaneZ()->SetWindowLevel(bbGetInputWindowLevel()[0],
321                                                                 bbGetInputWindowLevel()[1]);
322                         } else {
323                                 double *range = image->GetScalarRange();
324                                 bbGetOutputPlaneZ()->SetWindowLevel(range[1]-range[0],
325                                                                0.5*(range[1]+range[0]));
326                         } // windowlevel
327                         updateInteractor();
328                         
329                         dim[0] = xMax-xMin+1;
330                         dim[1] = yMax-yMin+1;
331                         dim[2] = zMax-zMin+1;
332                         _imageTransform->Identity();
333                         _imageTransform->PostMultiply();
334                         _imageTransform->Translate( (int)(-(dim[0]/2)*(1/xSpacing)) , (int)(-(dim[2]/2)*(1/zSpacing)) ,0);
335                         _imageTransform->RotateZ(90);
336                         
337            } // image
338                 
339                         // UPDATE DES SORTIES 
340                 bbGetOutputPlaneX()->SetResliceInterpolate( bbGetInputInterpolation() );
341                 bbGetOutputPlaneY()->SetResliceInterpolate( bbGetInputInterpolation() );
342                 bbGetOutputPlaneZ()->SetResliceInterpolate( bbGetInputInterpolation() );
343
344                 
345                 bbGetOutputPlaneX()->GetResliceOutput()->Update();
346                 bbGetOutputPlaneY()->GetResliceOutput()->Update(); 
347                 bbGetOutputPlaneZ()->GetResliceOutput()->Update();               
348                 
349                 std::vector<int> pointsx = bbGetInputPointsX();
350                 std::vector<int> pointsy = bbGetInputPointsY();
351                 std::vector<int> pointsz = bbGetInputPointsZ();
352
353                 //std::cout<<pointsx.size()<<pointsy.size()<<pointsz.size()<<std::endl;
354
355                 if (pointsx.size()==pointsy.size() && pointsx.size()==pointsz.size()&&pointsx.size()>=3)
356                 {
357
358                         //Get the corresponding three points out of the vectors
359                         double origin[3];
360                         origin[0] = pointsx[0];
361                         origin[1] = pointsy[0];
362                         origin[2] = pointsz[0];
363
364                         double point1[3];
365                         point1[0] = pointsx[1];
366                         point1[1] = pointsy[1];
367                         point1[2] = pointsz[1];
368                         double point2[3];
369                         point2[0]= pointsx[2];
370                         point2[1]= pointsy[2];
371                         point2[2]= pointsz[2];  
372
373                         //With the three points we create the corresponding X, Y and Z vectors all orthogonal to each other
374                         double* vect1= getNormal(makeVector(origin, point1));
375                         double* vect2= getNormal(makeVector(origin, point2));                           
376                         double* crossp = getCrossProduct(vect1, vect2);
377
378                         double *newx = getCrossProduct(vect2, crossp);
379
380                         int ext[6],factor=0;
381                         bbGetInputIn()->GetExtent(ext);
382
383                         factor = ext[0]<ext[3]? ext[3] : ext[0];
384                         factor = factor<ext[5]? ext[5] : factor;
385
386         //for the plane widgets
387                         vtkImagePlaneWidget* plane3pts = (vtkImagePlaneWidget*)bbGetOutputPlane3Pts();
388                         plane3pts->SetInput(bbGetInputIn());                    
389                         double xSpacing, ySpacing, zSpacing;
390                         bbGetInputIn()->GetSpacing(xSpacing, ySpacing, zSpacing);
391                         plane3pts->SetOrigin(pointsx[0]*xSpacing,pointsy[0]*ySpacing,pointsz[0]*zSpacing);      
392                         plane3pts->SetPoint1((origin[0]+newx[0]*factor)*xSpacing,
393                                                                         (origin[1]+newx[1]*factor)*ySpacing,
394                                                                         (origin[2]+newx[2]*factor)*zSpacing);
395                         plane3pts->SetPoint2((origin[0]+vect2[0]*factor)*xSpacing,
396                                                                         (origin[1]+vect2[1]*factor)*ySpacing,
397                                                                         (origin[2]+vect2[2]*factor)*zSpacing);
398                         plane3pts->GetResliceOutput()->Update();
399 //To get the slice of image out of the selected volume
400                         if (_imageReslicer==NULL){
401                                 _imageReslicer = vtkImageReslice::New();                                        
402                                 _imageReslicer->SetOutputDimensionality(2);
403                                 _transform = vtkTransform::New();
404                                 _matrix = vtkMatrix4x4::New();  
405                         }
406                         _imageReslicer->SetInterpolationMode( bbGetInputInterpolation() );
407                         _imageReslicer->SetInput( bbGetInputIn() );
408                         _imageReslicer->SetInformationInput(bbGetInputIn());    
409                         //fill out the information with the created vectors and using the spacing of the image
410                         _imageReslicer->SetResliceAxesDirectionCosines(newx[0]*xSpacing,newx[1]*xSpacing,newx[2]*xSpacing,
411                                                                         vect2[0]*ySpacing,vect2[1]*ySpacing,vect2[2]*ySpacing,
412                                                                         crossp[0]*zSpacing,crossp[1]*zSpacing,crossp[2]*zSpacing);                      
413                         _imageReslicer->SetResliceAxesOrigin(origin[0]*xSpacing,origin[1]*ySpacing,origin[2]*zSpacing);
414                         _imageReslicer->GetOutput()->Update();
415                         _imageReslicer->GetOutput()->UpdateInformation();
416
417                         bbSetOutputImage3Pts(_imageReslicer->GetOutput());
418
419                         _matrix->Identity();    
420
421                         _matrix->SetElement(0,0,newx[0]*xSpacing);
422                         _matrix->SetElement(1,0,newx[1]*xSpacing);
423                         _matrix->SetElement(2,0,newx[2]*xSpacing);
424                         _matrix->SetElement(0,1,vect2[0]*ySpacing);
425                         _matrix->SetElement(1,1,vect2[1]*ySpacing);
426                         _matrix->SetElement(2,1,vect2[2]*ySpacing);
427                         _matrix->SetElement(0,2,crossp[0]*zSpacing);
428                         _matrix->SetElement(1,2,crossp[1]*zSpacing);
429                         _matrix->SetElement(2,2,crossp[2]*zSpacing);
430                         _matrix->SetElement(0,3,origin[0]*xSpacing);
431                         _matrix->SetElement(1,3,origin[1]*ySpacing);
432                         _matrix->SetElement(2,3,origin[2]*zSpacing);
433
434                         _transform->SetMatrix(_matrix);
435
436                         //set the transformation out to be used by other bbBoxes
437                         bbSetOutputTransform3Pts((vtkLinearTransform*)_transform);                      
438                 }       // pointsx pointsy  pointsz
439         } // bbGetInputIn
440   }
441         
442   void ImagePlanes::updateInteractor(){
443
444         vtkRenderWindowInteractor* interactor = bbGetInputInteractor();
445
446         if(interactor){
447                 bbGetOutputPlaneX()->SetInteractor(interactor);
448                 bbGetOutputPlaneX()->EnabledOn();
449                 bbGetOutputPlaneY()->SetInteractor(interactor);
450                 bbGetOutputPlaneY()->EnabledOn();
451                 bbGetOutputPlaneZ()->SetInteractor(interactor);
452                 bbGetOutputPlaneZ()->EnabledOn();
453                 bbGetOutputPlane3Pts()->SetInteractor(interactor);
454                 bbGetOutputPlane3Pts()->EnabledOn();
455         }
456   }
457         //-----------------------------------------------------------------     
458   void vtkImageDataPointerRelay::bbUserSetDefaultValues()
459         {
460                 
461         }
462         
463         //-----------------------------------------------------------------     
464   void vtkImageDataPointerRelay::bbUserInitializeProcessing()
465         {
466         }
467         
468         //-----------------------------------------------------------------     
469   void vtkImageDataPointerRelay::bbUserFinalizeProcessing()
470         {
471         }
472         
473   vtkImagePlaneWidget* ImagePlanes::GetPlaneWidget(unsigned char activationkey, double r, double g, double b, vtkCellPicker* picker)
474   {
475                 vtkProperty* prop1 = 0;         
476                 vtkImagePlaneWidget* planeWidget = 0;
477
478                 planeWidget = vtkImagePlaneWidget::New();
479                 planeWidget->DisplayTextOn();
480                 planeWidget->SetPicker(picker);
481                 planeWidget->SetKeyPressActivationValue(activationkey);
482                 prop1 = planeWidget->GetPlaneProperty();
483                 prop1->SetColor(r, g, b);
484
485                 return planeWidget;
486   }
487
488   double* ImagePlanes::getCrossProduct(double* vect0,double* vect1){
489         double* vectCross;
490         vectCross = new double[3];
491         vectCross[0] = vect0[1]*vect1[2]-(vect0[2]*vect1[1]);
492         vectCross[1] = -(vect0[0]*vect1[2]-(vect0[2]*vect1[0]));
493         vectCross[2] = vect0[0]*vect1[1]-(vect0[1]*vect1[0]);
494
495         return vectCross;
496   }
497 /**
498 **      Returns the magnitud of the given vector
499 **/
500   double ImagePlanes::getMagnitud(double* vect){
501
502         double mag;
503         mag = sqrt(pow(vect[0],2) + pow(vect[1],2) + pow(vect[2],2));
504         //std::cout<<"mag "<<mag <<std::endl;
505         return mag;
506   }
507 /**
508 **      returns the unitary vector of the given vector
509 **      u = 1/|vect| . vect
510 **/
511   double* ImagePlanes::getNormal(double* vect){
512
513         double* vectnorm;
514         double mag = getMagnitud(vect);
515
516         vectnorm = new double[3];
517
518         if(mag!=0){
519                 vectnorm[0] = vect[0]/mag;
520                 vectnorm[1] = vect[1]/mag;
521                 vectnorm[2] = vect[2]/mag;
522         }else{
523                 vectnorm[0] = 0;
524                 vectnorm[1] = 0;
525                 vectnorm[2] = 0;
526         }
527
528         return vectnorm;
529   }
530
531   double* ImagePlanes::makeVector(double podouble0[3], double podouble1[3]){
532         double *vect;
533         vect = new double[3];
534
535         vect[0]= podouble1[0]-podouble0[0];
536         vect[1]= podouble1[1]-podouble0[1];
537         vect[2]= podouble1[2]-podouble0[2];
538
539         return vect;
540   }
541         
542 }//namespace bbtk
543
544 #endif // _USE_VTK_