]> Creatis software - bbtk.git/blob - packages/vtk/src/bbvtkImagePlanes.cxx
Future 1454
[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/04 08:38:21 $
6   Version:   $Revision: 1.36 $
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
69
70 namespace bbstd
71 {
72
73   //====================================================================
74   BBTK_BLACK_BOX_TEMPLATE2_IMPLEMENTATION(Cast,
75                                           bbtk::AtomicBlackBox);
76   //====================================================================
77   //====================================================================
78 //  BBTK_BLACK_BOX_TEMPLATE_IMPLEMENTATION(Relay,
79 //                                       bbtk::AtomicBlackBox);
80   //====================================================================
81
82 }
83 using namespace bbstd;
84 /*
85 namespace bbtk
86 {
87         typedef vtkImageData::Pointer vtkImageDataPointer;
88   BBTK_DEFINE_HUMAN_READABLE_TYPE_NAME(vtkImageDataPointer,
89                                        "vtkImageDataPointer");
90 }
91 */
92 namespace bbvtk
93 {
94
95   //====================================================================
96   // Add the specialized adaptors to the package
97   typedef vtkImagePlaneWidget* I;
98   typedef vtkInteractorObserver* O;
99
100   BBTK_ADD_TEMPLATE2_BLACK_BOX_TO_PACKAGE(vtk,Cast,I,O);
101
102   BBTK_DEFINE_RELAY_BLACK_BOX(vtkImageDataPointer,vtk,vtkImageDataPointerRelay);
103   BBTK_BLACK_BOX_IMPLEMENTATION(vtkImageDataPointerRelay,bbtk::AtomicBlackBox);
104
105   BBTK_ADD_BLACK_BOX_TO_PACKAGE(vtk,vtkImageDataPointerRelay);
106  // BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(vtk,Relay,vtkImageDataPointer);
107   //Pointer);
108
109 }
110
111 namespace bbvtk
112 {
113
114   //================================================================
115  class ImagePlanes::VtkCallbackType : public vtkCommand
116  {
117  public:
118    static VtkCallbackType *New()
119    {
120      return new VtkCallbackType;
121    }
122    //vtkTypeRevisionMacro(VtkCallbackType,vtkCommand);
123
124    virtual void Execute(vtkObject *caller, unsigned long, void*)
125    {
126        mBlackBox->Process();
127        mBlackBox->bbSignalOutputModification();
128    } 
129    void SetBlackBox(ImagePlanes *BB) { mBlackBox = BB;};    
130    //   void SetVtkPlaneWidget( vtkImagePlaneWidget *planeWidget );
131    VtkCallbackType() {};
132
133  private:
134    //   vtkPlaneWidget *planeWidget;
135    ImagePlanes *mBlackBox;
136  };
137   //================================================================
138
139   //vtkCxxRevisionMacro(ImagePlanes::VtkCallbackType, "$Revision: 1.36 $");
140
141   //================================================================
142
143    BBTK_ADD_BLACK_BOX_TO_PACKAGE(vtk,ImagePlanes)
144    BBTK_BLACK_BOX_IMPLEMENTATION(ImagePlanes,bbtk::AtomicBlackBox);
145
146    void ImagePlanes::bbUserSetDefaultValues() 
147    { 
148      bbSetOutputPlaneX(0);
149      bbSetOutputPlaneY(0);
150      bbSetOutputPlaneZ(0);
151      bbSetOutputImageX(0);
152      bbSetOutputImageY(0);
153      bbSetOutputImageZ(0);
154      bbSetInputIn(0);
155      std::vector<double> vect;
156      vect.push_back(0);
157      vect.push_back(0);
158      bbSetInputWindowLevel (vect);  
159      mVtkCallback = 0;
160
161      std::vector<int> vectpoints;
162
163      bbSetOutputPlane3Pts(0);
164      bbSetOutputImage3Pts(0);
165      bbSetInputPointsX(vectpoints);
166      bbSetInputPointsY(vectpoints);
167      bbSetInputPointsZ(vectpoints);
168
169      _imageReslicer = NULL;
170      image          = NULL;
171      _transform     = NULL;
172      _matrix        = NULL;
173            
174            bbSetInputInterpolation(1);     
175    }
176
177         
178    void ImagePlanes::bbUserInitializeProcessing() 
179    {  
180      /// CREATION DES WIDGETS
181      if (bbGetOutputPlaneX() != 0) return;
182        
183      // The shared picker enables us to use 3 planes at one time
184      // and gets the picking order right
185      vtkCellPicker* picker = vtkCellPicker::New();
186      picker->SetTolerance(0.005);
187   
188      // The 3 image plane widgets 
189      vtkImagePlaneWidget* planeWidgetX = GetPlaneWidget('x', 1, 0, 0, picker);
190      vtkImagePlaneWidget* planeWidgetY = GetPlaneWidget('y', 1, 1, 0, picker);
191      planeWidgetY->SetLookupTable(planeWidgetX->GetLookupTable());
192
193      vtkImagePlaneWidget* planeWidgetZ = GetPlaneWidget('z', 0, 0, 1, picker);     
194      planeWidgetZ->SetLookupTable(planeWidgetX->GetLookupTable());
195
196      vtkImagePlaneWidget* planeWidget3Pts = GetPlaneWidget('3', 0, 1, 1, picker);        
197      planeWidget3Pts->SetLookupTable(planeWidgetX->GetLookupTable());
198
199      bbSetOutputPlaneX(planeWidgetX);
200      bbSetOutputPlaneY(planeWidgetY);
201      bbSetOutputPlaneZ(planeWidgetZ);
202      bbSetOutputPlane3Pts(planeWidget3Pts);      
203      bbSetOutputImageX(planeWidgetX->GetResliceOutput());
204      bbSetOutputImageY(planeWidgetY->GetResliceOutput());
205      bbSetOutputImageZ(planeWidgetZ->GetResliceOutput());
206      bbSetInputInteractor(0);
207      //bbSetOutputImage3Pts(planeWidget3Pts->GetResliceOutput());
208
209          if(picker != 0)
210                 picker->UnRegister(NULL);
211      
212      mVtkCallback = VtkCallbackType::New();
213      mVtkCallback->SetBlackBox(this);
214      planeWidgetX->AddObserver(vtkCommand::InteractionEvent,mVtkCallback);
215      planeWidgetY->AddObserver(vtkCommand::InteractionEvent,mVtkCallback);
216      planeWidgetZ->AddObserver(vtkCommand::InteractionEvent,mVtkCallback);       
217
218    }
219
220 //---------------------------------------------------------------------
221   void ImagePlanes::bbUserFinalizeProcessing()
222   {
223
224     if (bbGetOutputPlaneX()) 
225       {
226
227         /*
228           bbGetOutputPlaneX()->RemoveObserver(mVtkCallback);
229           bbGetOutputPlaneY()->RemoveObserver(mVtkCallback);
230           bbGetOutputPlaneZ()->RemoveObserver(mVtkCallback);
231
232         bbGetOutputPlaneX()->Delete();
233         bbGetOutputPlaneY()->Delete();
234         bbGetOutputPlaneZ()->Delete();
235         mVtkCallback->Delete();
236         */
237         //bbGetOutputPlaneX()->SetInput(NULL);
238         //bbGetOutputPlaneY()->SetInput(NULL);
239         //bbGetOutputPlaneZ()->SetInput(NULL);
240
241       }
242   }
243   
244 //---------------------------------------------------------------------  
245   void ImagePlanes::Process()
246   {
247         if (bbGetInputIn()!=0)
248         {
249                 int xMin, xMax, yMin, yMax, zMin, zMax;
250                 bbGetInputIn()->GetExtent(xMin, xMax, yMin, yMax, zMin, zMax);
251
252                 if ( image != bbGetInputIn()){//bbGetInputStatus("In") != bbtk::UPTODATE ){
253                         // Input image has changed : reinitialize planes
254                         image = bbGetInputIn();                 
255
256                         // Initial values : center of the volume (in real world, not in pixels!)
257                         double xSpacing, ySpacing, zSpacing;
258                         bbGetInputIn()->GetSpacing(xSpacing, ySpacing, zSpacing);
259
260                         bbGetOutputPlaneX()->SetInput(bbGetInputIn());
261                         bbGetOutputPlaneX()->SetPlaneOrientationToXAxes();       
262                         bbGetOutputPlaneX()->SetSlicePosition((xMax+xMin)/2.*xSpacing);
263
264                         //                 bbGetOutputPlaneX()->SetOrigin( 58*xSpacing , 80*ySpacing , 82*zSpacing );
265                         //                 bbGetOutputPlaneX()->SetPoint1( 0*xSpacing, 146*ySpacing, 186*zSpacing);
266                         //                 bbGetOutputPlaneX()->SetPoint2( 126*xSpacing, 146*ySpacing, 0*zSpacing);
267
268                         bbGetOutputPlaneY()->SetInput(bbGetInputIn());
269                         bbGetOutputPlaneY()->SetPlaneOrientationToYAxes();
270                         bbGetOutputPlaneY()->SetSlicePosition((yMax+yMin)/2.*ySpacing);
271
272                         bbGetOutputPlaneZ()->SetInput(bbGetInputIn());
273                         bbGetOutputPlaneZ()->SetPlaneOrientationToZAxes();
274                         bbGetOutputPlaneZ()->SetSlicePosition((zMax+zMin)/2.*zSpacing);
275
276                         if (bbGetInputWindowLevel()[0]!=0)
277                         {
278                                 bbGetOutputPlaneZ()->SetWindowLevel(bbGetInputWindowLevel()[0],
279                                                                 bbGetInputWindowLevel()[1]);
280                         }
281                         else 
282                         {
283                                 double *range = image->GetScalarRange();
284                                 bbGetOutputPlaneZ()->SetWindowLevel(range[1]-range[0],
285                                                                0.5*(range[1]+range[0]));
286                         }
287                         updateInteractor();
288            }
289                         // UPDATE DES SORTIES 
290                 bbGetOutputPlaneX()->SetResliceInterpolate( bbGetInputInterpolation() );
291                 bbGetOutputPlaneY()->SetResliceInterpolate( bbGetInputInterpolation() );
292                 bbGetOutputPlaneZ()->SetResliceInterpolate( bbGetInputInterpolation() );
293                 
294                 bbGetOutputPlaneX()->GetResliceOutput()->Update();
295                 bbGetOutputPlaneY()->GetResliceOutput()->Update(); 
296                 bbGetOutputPlaneZ()->GetResliceOutput()->Update();               
297
298                 std::vector<int> pointsx = bbGetInputPointsX();
299                 std::vector<int> pointsy = bbGetInputPointsY();
300                 std::vector<int> pointsz = bbGetInputPointsZ();
301
302                 //std::cout<<pointsx.size()<<pointsy.size()<<pointsz.size()<<std::endl;
303
304                 if (pointsx.size()==pointsy.size() && pointsx.size()==pointsz.size()&&pointsx.size()>=3)
305                 {
306
307                         //Get the corresponding three points out of the vectors
308                         double origin[3];
309                         origin[0] = pointsx[0];
310                         origin[1] = pointsy[0];
311                         origin[2] = pointsz[0];
312
313                         double point1[3];
314                         point1[0] = pointsx[1];
315                         point1[1] = pointsy[1];
316                         point1[2] = pointsz[1];
317                         double point2[3];
318                         point2[0]= pointsx[2];
319                         point2[1]= pointsy[2];
320                         point2[2]= pointsz[2];  
321
322                         //With the three points we create the corresponding X, Y and Z vectors all orthogonal to each other
323                         double* vect1= getNormal(makeVector(origin, point1));
324                         double* vect2= getNormal(makeVector(origin, point2));                           
325                         double* crossp = getCrossProduct(vect1, vect2);
326
327                         double *newx = getCrossProduct(vect2, crossp);
328
329                         int ext[6],factor=0;
330                         bbGetInputIn()->GetExtent(ext);
331
332                         factor = ext[0]<ext[3]? ext[3] : ext[0];
333                         factor = factor<ext[5]? ext[5] : factor;
334
335         //for the plane widgets
336                         vtkImagePlaneWidget* plane3pts = (vtkImagePlaneWidget*)bbGetOutputPlane3Pts();
337                         plane3pts->SetInput(bbGetInputIn());                    
338                         double xSpacing, ySpacing, zSpacing;
339                         bbGetInputIn()->GetSpacing(xSpacing, ySpacing, zSpacing);
340                         plane3pts->SetOrigin(pointsx[0]*xSpacing,pointsy[0]*ySpacing,pointsz[0]*zSpacing);      
341                         plane3pts->SetPoint1((origin[0]+newx[0]*factor)*xSpacing,
342                                                                         (origin[1]+newx[1]*factor)*ySpacing,
343                                                                         (origin[2]+newx[2]*factor)*zSpacing);
344                         plane3pts->SetPoint2((origin[0]+vect2[0]*factor)*xSpacing,
345                                                                         (origin[1]+vect2[1]*factor)*ySpacing,
346                                                                         (origin[2]+vect2[2]*factor)*zSpacing);
347                         plane3pts->GetResliceOutput()->Update();
348 //To get the slice of image out of the selected volume
349                         if (_imageReslicer==NULL){
350                                 _imageReslicer = vtkImageReslice::New();                                        
351                                 _imageReslicer->SetOutputDimensionality(2);
352                                 _transform = vtkTransform::New();
353                                 _matrix = vtkMatrix4x4::New();  
354                         }
355                         _imageReslicer->SetInterpolationMode( bbGetInputInterpolation() );
356                         _imageReslicer->SetInput( bbGetInputIn() );
357                         _imageReslicer->SetInformationInput(bbGetInputIn());    
358                         //fill out the information with the created vectors and using the spacing of the image
359                         _imageReslicer->SetResliceAxesDirectionCosines(newx[0]*xSpacing,newx[1]*xSpacing,newx[2]*xSpacing,
360                                                                         vect2[0]*ySpacing,vect2[1]*ySpacing,vect2[2]*ySpacing,
361                                                                         crossp[0]*zSpacing,crossp[1]*zSpacing,crossp[2]*zSpacing);                      
362                         _imageReslicer->SetResliceAxesOrigin(origin[0]*xSpacing,origin[1]*ySpacing,origin[2]*zSpacing);
363                         _imageReslicer->GetOutput()->Update();
364                         _imageReslicer->GetOutput()->UpdateInformation();
365
366                         bbSetOutputImage3Pts(_imageReslicer->GetOutput());
367
368                         _matrix->Identity();    
369
370                         _matrix->SetElement(0,0,newx[0]*xSpacing);
371                         _matrix->SetElement(1,0,newx[1]*xSpacing);
372                         _matrix->SetElement(2,0,newx[2]*xSpacing);
373                         _matrix->SetElement(0,1,vect2[0]*ySpacing);
374                         _matrix->SetElement(1,1,vect2[1]*ySpacing);
375                         _matrix->SetElement(2,1,vect2[2]*ySpacing);
376                         _matrix->SetElement(0,2,crossp[0]*zSpacing);
377                         _matrix->SetElement(1,2,crossp[1]*zSpacing);
378                         _matrix->SetElement(2,2,crossp[2]*zSpacing);
379                         _matrix->SetElement(0,3,origin[0]*xSpacing);
380                         _matrix->SetElement(1,3,origin[1]*ySpacing);
381                         _matrix->SetElement(2,3,origin[2]*zSpacing);
382
383                         _transform->SetMatrix(_matrix);
384
385                         //set the transformation out to be used by other bbBoxes
386                         bbSetOutputTransform3Pts((vtkLinearTransform*)_transform);                      
387                 }       // pointsx pointsy  pointsz
388         } // bbGetInputIn
389   }
390         
391   void ImagePlanes::updateInteractor(){
392
393         vtkRenderWindowInteractor* interactor = bbGetInputInteractor();
394
395         if(interactor){
396                 bbGetOutputPlaneX()->SetInteractor(interactor);
397                 bbGetOutputPlaneX()->EnabledOn();
398                 bbGetOutputPlaneY()->SetInteractor(interactor);
399                 bbGetOutputPlaneY()->EnabledOn();
400                 bbGetOutputPlaneZ()->SetInteractor(interactor);
401                 bbGetOutputPlaneZ()->EnabledOn();
402                 bbGetOutputPlane3Pts()->SetInteractor(interactor);
403                 bbGetOutputPlane3Pts()->EnabledOn();
404         }
405   }
406         //-----------------------------------------------------------------     
407   void vtkImageDataPointerRelay::bbUserSetDefaultValues()
408         {
409                 
410         }
411         
412         //-----------------------------------------------------------------     
413   void vtkImageDataPointerRelay::bbUserInitializeProcessing()
414         {
415         }
416         
417         //-----------------------------------------------------------------     
418   void vtkImageDataPointerRelay::bbUserFinalizeProcessing()
419         {
420         }
421         
422   vtkImagePlaneWidget* ImagePlanes::GetPlaneWidget(unsigned char activationkey, double r, double g, double b, vtkCellPicker* picker)
423   {
424                 vtkProperty* prop1 = 0;         
425                 vtkImagePlaneWidget* planeWidget = 0;
426
427                 planeWidget = vtkImagePlaneWidget::New();
428                 planeWidget->DisplayTextOn();
429                 planeWidget->SetPicker(picker);
430                 planeWidget->SetKeyPressActivationValue(activationkey);
431                 prop1 = planeWidget->GetPlaneProperty();
432                 prop1->SetColor(r, g, b);
433
434                 return planeWidget;
435   }
436
437   double* ImagePlanes::getCrossProduct(double* vect0,double* vect1){
438         double* vectCross;
439         vectCross = new double[3];
440         vectCross[0] = vect0[1]*vect1[2]-(vect0[2]*vect1[1]);
441         vectCross[1] = -(vect0[0]*vect1[2]-(vect0[2]*vect1[0]));
442         vectCross[2] = vect0[0]*vect1[1]-(vect0[1]*vect1[0]);
443
444         return vectCross;
445   }
446 /**
447 **      Returns the magnitud of the given vector
448 **/
449   double ImagePlanes::getMagnitud(double* vect){
450
451         double mag;
452         mag = sqrt(pow(vect[0],2) + pow(vect[1],2) + pow(vect[2],2));
453         //std::cout<<"mag "<<mag <<std::endl;
454         return mag;
455   }
456 /**
457 **      returns the unitary vector of the given vector
458 **      u = 1/|vect| . vect
459 **/
460   double* ImagePlanes::getNormal(double* vect){
461
462         double* vectnorm;
463         double mag = getMagnitud(vect);
464
465         vectnorm = new double[3];
466
467         if(mag!=0){
468                 vectnorm[0] = vect[0]/mag;
469                 vectnorm[1] = vect[1]/mag;
470                 vectnorm[2] = vect[2]/mag;
471         }else{
472                 vectnorm[0] = 0;
473                 vectnorm[1] = 0;
474                 vectnorm[2] = 0;
475         }
476
477         return vectnorm;
478   }
479
480   double* ImagePlanes::makeVector(double podouble0[3], double podouble1[3]){
481         double *vect;
482         vect = new double[3];
483
484         vect[0]= podouble1[0]-podouble0[0];
485         vect[1]= podouble1[1]-podouble0[1];
486         vect[2]= podouble1[2]-podouble0[2];
487
488         return vect;
489   }
490         
491 }//namespace bbtk
492
493 #endif // _USE_VTK_