]> Creatis software - bbtk.git/blob - packages/vtk/src/bbvtkImagePlanes.cxx
change subdirs to add_subdirectory
[bbtk.git] / packages / vtk / src / bbvtkImagePlanes.cxx
1 /*=========================================================================                                                                               
2   Program:   bbtk
3   Module:    $RCSfile: bbvtkImagePlanes.cxx,v $
4   Language:  C++
5   Date:      $Date: 2010/08/18 12:36:45 $
6   Version:   $Revision: 1.35 $
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.35 $");
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
175         
176    void ImagePlanes::bbUserInitializeProcessing() 
177    {  
178      /// CREATION DES WIDGETS
179      if (bbGetOutputPlaneX() != 0) return;
180        
181      // The shared picker enables us to use 3 planes at one time
182      // and gets the picking order right
183      vtkCellPicker* picker = vtkCellPicker::New();
184      picker->SetTolerance(0.005);
185   
186      // The 3 image plane widgets 
187      vtkImagePlaneWidget* planeWidgetX = GetPlaneWidget('x', 1, 0, 0, picker);
188      vtkImagePlaneWidget* planeWidgetY = GetPlaneWidget('y', 1, 1, 0, picker);
189      planeWidgetY->SetLookupTable(planeWidgetX->GetLookupTable());
190
191      vtkImagePlaneWidget* planeWidgetZ = GetPlaneWidget('z', 0, 0, 1, picker);     
192      planeWidgetZ->SetLookupTable(planeWidgetX->GetLookupTable());
193
194      vtkImagePlaneWidget* planeWidget3Pts = GetPlaneWidget('3', 0, 1, 1, picker);        
195      planeWidget3Pts->SetLookupTable(planeWidgetX->GetLookupTable());
196
197      bbSetOutputPlaneX(planeWidgetX);
198      bbSetOutputPlaneY(planeWidgetY);
199      bbSetOutputPlaneZ(planeWidgetZ);
200      bbSetOutputPlane3Pts(planeWidget3Pts);      
201      bbSetOutputImageX(planeWidgetX->GetResliceOutput());
202      bbSetOutputImageY(planeWidgetY->GetResliceOutput());
203      bbSetOutputImageZ(planeWidgetZ->GetResliceOutput());
204      bbSetInputInteractor(0);
205      //bbSetOutputImage3Pts(planeWidget3Pts->GetResliceOutput());
206
207          if(picker != 0)
208                 picker->UnRegister(NULL);
209      
210      mVtkCallback = VtkCallbackType::New();
211      mVtkCallback->SetBlackBox(this);
212      planeWidgetX->AddObserver(vtkCommand::InteractionEvent,mVtkCallback);
213      planeWidgetY->AddObserver(vtkCommand::InteractionEvent,mVtkCallback);
214      planeWidgetZ->AddObserver(vtkCommand::InteractionEvent,mVtkCallback);       
215
216    }
217
218 //---------------------------------------------------------------------
219   void ImagePlanes::bbUserFinalizeProcessing()
220   {
221
222     if (bbGetOutputPlaneX()) 
223       {
224
225         /*
226           bbGetOutputPlaneX()->RemoveObserver(mVtkCallback);
227           bbGetOutputPlaneY()->RemoveObserver(mVtkCallback);
228           bbGetOutputPlaneZ()->RemoveObserver(mVtkCallback);
229
230         bbGetOutputPlaneX()->Delete();
231         bbGetOutputPlaneY()->Delete();
232         bbGetOutputPlaneZ()->Delete();
233         mVtkCallback->Delete();
234         */
235         //bbGetOutputPlaneX()->SetInput(NULL);
236         //bbGetOutputPlaneY()->SetInput(NULL);
237         //bbGetOutputPlaneZ()->SetInput(NULL);
238
239       }
240   }
241   
242 //---------------------------------------------------------------------  
243   void ImagePlanes::Process()
244   {
245         if (bbGetInputIn()!=0)
246         {
247                 int xMin, xMax, yMin, yMax, zMin, zMax;
248                 bbGetInputIn()->GetExtent(xMin, xMax, yMin, yMax, zMin, zMax);
249
250                 if ( image != bbGetInputIn()){//bbGetInputStatus("In") != bbtk::UPTODATE ){
251                         // Input image has changed : reinitialize planes
252                         image = bbGetInputIn();                 
253
254                         // Initial values : center of the volume (in real world, not in pixels!)
255                         double xSpacing, ySpacing, zSpacing;
256                         bbGetInputIn()->GetSpacing(xSpacing, ySpacing, zSpacing);
257
258                         bbGetOutputPlaneX()->SetInput(bbGetInputIn());
259                         bbGetOutputPlaneX()->SetPlaneOrientationToXAxes();       
260                         bbGetOutputPlaneX()->SetSlicePosition((xMax+xMin)/2.*xSpacing);
261
262                         //                 bbGetOutputPlaneX()->SetOrigin( 58*xSpacing , 80*ySpacing , 82*zSpacing );
263                         //                 bbGetOutputPlaneX()->SetPoint1( 0*xSpacing, 146*ySpacing, 186*zSpacing);
264                         //                 bbGetOutputPlaneX()->SetPoint2( 126*xSpacing, 146*ySpacing, 0*zSpacing);
265
266                         bbGetOutputPlaneY()->SetInput(bbGetInputIn());
267                         bbGetOutputPlaneY()->SetPlaneOrientationToYAxes();
268                         bbGetOutputPlaneY()->SetSlicePosition((yMax+yMin)/2.*ySpacing);
269
270                         bbGetOutputPlaneZ()->SetInput(bbGetInputIn());
271                         bbGetOutputPlaneZ()->SetPlaneOrientationToZAxes();
272                         bbGetOutputPlaneZ()->SetSlicePosition((zMax+zMin)/2.*zSpacing);
273
274                         if (bbGetInputWindowLevel()[0]!=0)
275                         {
276                                 bbGetOutputPlaneZ()->SetWindowLevel(bbGetInputWindowLevel()[0],
277                                                                 bbGetInputWindowLevel()[1]);
278                         }
279                         else 
280                         {
281                                 double *range = image->GetScalarRange();
282                                 bbGetOutputPlaneZ()->SetWindowLevel(range[1]-range[0],
283                                                                0.5*(range[1]+range[0]));
284                         }
285                         updateInteractor();
286            }
287                         // UPDATE DES SORTIES 
288                 bbGetOutputPlaneX()->GetResliceOutput()->Update();
289                 bbGetOutputPlaneY()->GetResliceOutput()->Update(); 
290                 bbGetOutputPlaneZ()->GetResliceOutput()->Update();               
291
292                 std::vector<int> pointsx = bbGetInputPointsX();
293                 std::vector<int> pointsy = bbGetInputPointsY();
294                 std::vector<int> pointsz = bbGetInputPointsZ();
295
296                 //std::cout<<pointsx.size()<<pointsy.size()<<pointsz.size()<<std::endl;
297
298                 if (pointsx.size()==pointsy.size() && pointsx.size()==pointsz.size()&&pointsx.size()>=3)
299                 {
300
301                         //Get the corresponding three points out of the vectors
302                         double origin[3];
303                         origin[0] = pointsx[0];
304                         origin[1] = pointsy[0];
305                         origin[2] = pointsz[0];
306
307                         double point1[3];
308                         point1[0] = pointsx[1];
309                         point1[1] = pointsy[1];
310                         point1[2] = pointsz[1];
311                         double point2[3];
312                         point2[0]= pointsx[2];
313                         point2[1]= pointsy[2];
314                         point2[2]= pointsz[2];  
315
316                         //With the three points we create the corresponding X, Y and Z vectors all orthogonal to each other
317                         double* vect1= getNormal(makeVector(origin, point1));
318                         double* vect2= getNormal(makeVector(origin, point2));                           
319                         double* crossp = getCrossProduct(vect1, vect2);
320
321                         double *newx = getCrossProduct(vect2, crossp);
322
323                         int ext[6],factor=0;
324                         bbGetInputIn()->GetExtent(ext);
325
326                         factor = ext[0]<ext[3]? ext[3] : ext[0];
327                         factor = factor<ext[5]? ext[5] : factor;
328
329         //for the plane widgets
330                         vtkImagePlaneWidget* plane3pts = (vtkImagePlaneWidget*)bbGetOutputPlane3Pts();
331                         plane3pts->SetInput(bbGetInputIn());                    
332                         double xSpacing, ySpacing, zSpacing;
333                         bbGetInputIn()->GetSpacing(xSpacing, ySpacing, zSpacing);
334                         plane3pts->SetOrigin(pointsx[0]*xSpacing,pointsy[0]*ySpacing,pointsz[0]*zSpacing);      
335                         plane3pts->SetPoint1((origin[0]+newx[0]*factor)*xSpacing,
336                                                                         (origin[1]+newx[1]*factor)*ySpacing,
337                                                                         (origin[2]+newx[2]*factor)*zSpacing);
338                         plane3pts->SetPoint2((origin[0]+vect2[0]*factor)*xSpacing,
339                                                                         (origin[1]+vect2[1]*factor)*ySpacing,
340                                                                         (origin[2]+vect2[2]*factor)*zSpacing);
341                         plane3pts->GetResliceOutput()->Update();
342 //To get the slice of image out of the selected volume
343                         if (_imageReslicer==NULL){
344                                 _imageReslicer = vtkImageReslice::New();                                        
345                                 _imageReslicer->SetOutputDimensionality(2);
346                                 _imageReslicer->SetInterpolationModeToLinear();
347                                 _transform = vtkTransform::New();
348                                 _matrix = vtkMatrix4x4::New();  
349                         }
350                         _imageReslicer->SetInput( bbGetInputIn() );
351                         _imageReslicer->SetInformationInput(bbGetInputIn());    
352                         //fill out the information with the created vectors and using the spacing of the image
353                         _imageReslicer->SetResliceAxesDirectionCosines(newx[0]*xSpacing,newx[1]*xSpacing,newx[2]*xSpacing,
354                                                                         vect2[0]*ySpacing,vect2[1]*ySpacing,vect2[2]*ySpacing,
355                                                                         crossp[0]*zSpacing,crossp[1]*zSpacing,crossp[2]*zSpacing);                      
356                         _imageReslicer->SetResliceAxesOrigin(origin[0]*xSpacing,origin[1]*ySpacing,origin[2]*zSpacing);
357                         _imageReslicer->GetOutput()->Update();
358                         _imageReslicer->GetOutput()->UpdateInformation();
359
360                         bbSetOutputImage3Pts(_imageReslicer->GetOutput());
361
362                         _matrix->Identity();    
363
364                         _matrix->SetElement(0,0,newx[0]*xSpacing);
365                         _matrix->SetElement(1,0,newx[1]*xSpacing);
366                         _matrix->SetElement(2,0,newx[2]*xSpacing);
367                         _matrix->SetElement(0,1,vect2[0]*ySpacing);
368                         _matrix->SetElement(1,1,vect2[1]*ySpacing);
369                         _matrix->SetElement(2,1,vect2[2]*ySpacing);
370                         _matrix->SetElement(0,2,crossp[0]*zSpacing);
371                         _matrix->SetElement(1,2,crossp[1]*zSpacing);
372                         _matrix->SetElement(2,2,crossp[2]*zSpacing);
373                         _matrix->SetElement(0,3,origin[0]*xSpacing);
374                         _matrix->SetElement(1,3,origin[1]*ySpacing);
375                         _matrix->SetElement(2,3,origin[2]*zSpacing);
376
377                         _transform->SetMatrix(_matrix);
378
379                         //set the transformation out to be used by other bbBoxes
380                         bbSetOutputTransform3Pts((vtkLinearTransform*)_transform);                      
381                 }       
382         }
383   }
384         
385   void ImagePlanes::updateInteractor(){
386
387         vtkRenderWindowInteractor* interactor = bbGetInputInteractor();
388
389         if(interactor){
390                 bbGetOutputPlaneX()->SetInteractor(interactor);
391                 bbGetOutputPlaneX()->EnabledOn();
392                 bbGetOutputPlaneY()->SetInteractor(interactor);
393                 bbGetOutputPlaneY()->EnabledOn();
394                 bbGetOutputPlaneZ()->SetInteractor(interactor);
395                 bbGetOutputPlaneZ()->EnabledOn();
396                 bbGetOutputPlane3Pts()->SetInteractor(interactor);
397                 bbGetOutputPlane3Pts()->EnabledOn();
398         }
399   }
400         //-----------------------------------------------------------------     
401   void vtkImageDataPointerRelay::bbUserSetDefaultValues()
402         {
403                 
404         }
405         
406         //-----------------------------------------------------------------     
407   void vtkImageDataPointerRelay::bbUserInitializeProcessing()
408         {
409         }
410         
411         //-----------------------------------------------------------------     
412   void vtkImageDataPointerRelay::bbUserFinalizeProcessing()
413         {
414         }
415         
416   vtkImagePlaneWidget* ImagePlanes::GetPlaneWidget(unsigned char activationkey, double r, double g, double b, vtkCellPicker* picker)
417   {
418                 vtkProperty* prop1 = 0;         
419                 vtkImagePlaneWidget* planeWidget = 0;
420
421                 planeWidget = vtkImagePlaneWidget::New();
422                 planeWidget->DisplayTextOn();
423                 planeWidget->SetPicker(picker);
424                 planeWidget->SetKeyPressActivationValue(activationkey);
425                 prop1 = planeWidget->GetPlaneProperty();
426                 prop1->SetColor(r, g, b);
427
428                 return planeWidget;
429   }
430
431   double* ImagePlanes::getCrossProduct(double* vect0,double* vect1){
432         double* vectCross;
433         vectCross = new double[3];
434         vectCross[0] = vect0[1]*vect1[2]-(vect0[2]*vect1[1]);
435         vectCross[1] = -(vect0[0]*vect1[2]-(vect0[2]*vect1[0]));
436         vectCross[2] = vect0[0]*vect1[1]-(vect0[1]*vect1[0]);
437
438         return vectCross;
439   }
440 /**
441 **      Returns the magnitud of the given vector
442 **/
443   double ImagePlanes::getMagnitud(double* vect){
444
445         double mag;
446         mag = sqrt(pow(vect[0],2) + pow(vect[1],2) + pow(vect[2],2));
447         //std::cout<<"mag "<<mag <<std::endl;
448         return mag;
449   }
450 /**
451 **      returns the unitary vector of the given vector
452 **      u = 1/|vect| . vect
453 **/
454   double* ImagePlanes::getNormal(double* vect){
455
456         double* vectnorm;
457         double mag = getMagnitud(vect);
458
459         vectnorm = new double[3];
460
461         if(mag!=0){
462                 vectnorm[0] = vect[0]/mag;
463                 vectnorm[1] = vect[1]/mag;
464                 vectnorm[2] = vect[2]/mag;
465         }else{
466                 vectnorm[0] = 0;
467                 vectnorm[1] = 0;
468                 vectnorm[2] = 0;
469         }
470
471         return vectnorm;
472   }
473
474   double* ImagePlanes::makeVector(double podouble0[3], double podouble1[3]){
475         double *vect;
476         vect = new double[3];
477
478         vect[0]= podouble1[0]-podouble0[0];
479         vect[1]= podouble1[1]-podouble0[1];
480         vect[2]= podouble1[2]-podouble0[2];
481
482         return vect;
483   }
484         
485 }//namespace bbtk
486
487 #endif // _USE_VTK_