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