2 # ---------------------------------------------------------------------
4 # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
6 # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
7 # Previous Authors : Laurent Guigues, Jean-Pierre Roux
8 # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
10 # This software is governed by the CeCILL-B license under French law and
11 # abiding by the rules of distribution of free software. You can use,
12 # modify and/ or redistribute the software under the terms of the CeCILL-B
13 # license as circulated by CEA, CNRS and INRIA at the following URL
14 # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
15 # or in the file LICENSE.txt.
17 # As a counterpart to the access to the source code and rights to copy,
18 # modify and redistribute granted by the license, users are provided only
19 # with a limited warranty and the software's author, the holder of the
20 # economic rights, and the successive licensors have only limited
23 # The fact that you are presently reading this means that you have had
24 # knowledge of the CeCILL-B license and that you accept its terms.
25 # ------------------------------------------------------------------------ */
28 /*=========================================================================
30 Module: $RCSfile: bbvtkImagePlanes.cxx,v $
32 Date: $Date: 2012/11/16 08:51:58 $
33 Version: $Revision: 1.38 $
34 =========================================================================*/
42 #include "bbvtkImagePlanes.h"
43 #include "bbvtkPackage.h"
44 #include "vtkCellPicker.h"
45 #include "vtkProperty.h"
46 #include "vtkPolyData.h"
49 #include "vtkMetaImageWriter.h"
50 #include "vtkPNGWriter.h"
52 #include "bbstdCast.h"
53 #include <vtkCommand.h>
55 #include "vtkImageData.h"
56 //#include "vtkOutlineFilter.h"
57 //#include "vtkPolyDataMapper.h"
58 //#include "vtkActor.h"
59 #include "vtkImagePlaneWidget.h"
60 #include "vtkCellPicker.h"
61 //#include "vtkProperty.h"
63 //#include "vtkRenderer.h"
64 //#include "vtkCamera.h"
66 #include "vtkPlaneWidget.h"
68 #include <vtkImplicitPlaneWidget.h>
70 #include "bbstdRelay.h"
72 #include "vtkObjectFactory.h"
73 #include "vtkImageFlip.h"
75 #include "vtkImageReslice.h"
76 #include "vtkImageChangeInformation.h"
81 //====================================================================
82 BBTK_BLACK_BOX_TEMPLATE2_IMPLEMENTATION(Cast,
83 bbtk::AtomicBlackBox);
84 //====================================================================
85 //====================================================================
86 // BBTK_BLACK_BOX_TEMPLATE_IMPLEMENTATION(Relay,
87 // bbtk::AtomicBlackBox);
88 //====================================================================
91 using namespace bbstd;
95 typedef vtkImageData::Pointer vtkImageDataPointer;
96 BBTK_DEFINE_HUMAN_READABLE_TYPE_NAME(vtkImageDataPointer,
97 "vtkImageDataPointer");
103 //====================================================================
104 // Add the specialized adaptors to the package
105 typedef vtkImagePlaneWidget* I;
106 typedef vtkInteractorObserver* O;
108 BBTK_ADD_TEMPLATE2_BLACK_BOX_TO_PACKAGE(vtk,Cast,I,O);
110 BBTK_DEFINE_RELAY_BLACK_BOX(vtkImageDataPointer,vtk,vtkImageDataPointerRelay);
111 BBTK_BLACK_BOX_IMPLEMENTATION(vtkImageDataPointerRelay,bbtk::AtomicBlackBox);
113 BBTK_ADD_BLACK_BOX_TO_PACKAGE(vtk,vtkImageDataPointerRelay);
114 // BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(vtk,Relay,vtkImageDataPointer);
122 //================================================================
123 class ImagePlanes::VtkCallbackType : public vtkCommand
126 static VtkCallbackType *New()
128 return new VtkCallbackType;
130 //vtkTypeRevisionMacro(VtkCallbackType,vtkCommand);
132 virtual void Execute(vtkObject *caller, unsigned long, void*)
134 mBlackBox->Process();
135 mBlackBox->bbSignalOutputModification();
137 void SetBlackBox(ImagePlanes *BB) { mBlackBox = BB;};
138 // void SetVtkPlaneWidget( vtkImagePlaneWidget *planeWidget );
139 VtkCallbackType() {};
142 // vtkPlaneWidget *planeWidget;
143 ImagePlanes *mBlackBox;
145 //================================================================
147 //vtkCxxRevisionMacro(ImagePlanes::VtkCallbackType, "$Revision: 1.38 $");
149 //================================================================
151 BBTK_ADD_BLACK_BOX_TO_PACKAGE(vtk,ImagePlanes)
152 BBTK_BLACK_BOX_IMPLEMENTATION(ImagePlanes,bbtk::AtomicBlackBox);
154 void ImagePlanes::bbUserSetDefaultValues()
156 bbSetOutputPlaneX(NULL);
157 bbSetOutputPlaneY(NULL);
158 bbSetOutputPlaneZ(NULL);
159 bbSetOutputImageX(NULL);
160 bbSetOutputImageY(NULL);
161 bbSetOutputImageZ(NULL);
163 std::vector<double> vect;
166 bbSetInputWindowLevel (vect);
169 std::vector<int> vectpoints;
171 bbSetOutputPlane3Pts(0);
172 bbSetOutputImage3Pts(0);
173 bbSetInputPointsX(vectpoints);
174 bbSetInputPointsY(vectpoints);
175 bbSetInputPointsZ(vectpoints);
177 _imageReslicer = NULL;
182 bbSetInputInterpolation(1);
186 void ImagePlanes::bbUserInitializeProcessing()
188 /// CREATION DES WIDGETS
189 if (bbGetOutputPlaneX() != 0) return;
191 // The shared picker enables us to use 3 planes at one time
192 // and gets the picking order right
193 vtkCellPicker* picker = vtkCellPicker::New();
194 picker->SetTolerance(0.005);
196 // The 3 image plane widgets
197 vtkImagePlaneWidget* planeWidgetX = GetPlaneWidget('x', 1, 0, 0, picker);
198 vtkImagePlaneWidget* planeWidgetY = GetPlaneWidget('y', 1, 1, 0, picker);
199 planeWidgetY->SetLookupTable(planeWidgetX->GetLookupTable());
201 vtkImagePlaneWidget* planeWidgetZ = GetPlaneWidget('z', 0, 0, 1, picker);
202 planeWidgetZ->SetLookupTable(planeWidgetX->GetLookupTable());
204 vtkImagePlaneWidget* planeWidget3Pts = GetPlaneWidget('3', 0, 1, 1, picker);
205 planeWidget3Pts->SetLookupTable(planeWidgetX->GetLookupTable());
207 // EED MPR view orientation correction..
208 vtkImageFlip *flipYFilter = vtkImageFlip::New();
209 flipYFilter->SetFilteredAxis(1); // flip y axis
211 //EED 2017-01-01 Migration VTK7
212 #if (VTK_MAJOR_VERSION <= 5)
213 flipYFilter->SetInput( planeWidgetX->GetResliceOutput() );
215 #if (VTK_MAJOR_VERSION >= 6)
216 flipYFilter->SetInputData( planeWidgetX->GetResliceOutput() );
219 flipYFilter->Update();
221 vtkImageChangeInformation *image = vtkImageChangeInformation::New();
223 //EED 2017-01-01 Migration VTK7
224 #if (VTK_MAJOR_VERSION <= 5)
225 image->SetInput( planeWidgetY->GetResliceOutput() );
227 #if (VTK_MAJOR_VERSION >= 6)
228 image->SetInputData( planeWidgetY->GetResliceOutput() );
231 image->SetOutputSpacing( 1,1,1 );
232 image->CenterImageOn();
234 _imageTransform = vtkTransform::New();
235 vtkImageReslice *slicer =vtkImageReslice::New();
237 //EED 2017-01-01 Migration VTK7
238 #if (VTK_MAJOR_VERSION <= 5)
239 slicer->SetInput( image->GetOutput() );
241 #if (VTK_MAJOR_VERSION >= 6)
242 slicer->SetInputData( image->GetOutput() );
245 slicer->SetInformationInput( image->GetOutput() );
246 slicer->SetResliceTransform( _imageTransform );
247 slicer->SetOutputOrigin(0 , 0 , 0 );
248 slicer->SetInterpolationModeToNearestNeighbor();
250 vtkImageChangeInformation *imageResult = vtkImageChangeInformation::New();
252 //EED 2017-01-01 Migration VTK7
253 #if (VTK_MAJOR_VERSION <= 5)
254 imageResult->SetInput( slicer->GetOutput() );
256 #if (VTK_MAJOR_VERSION >= 6)
257 imageResult->SetInputData( slicer->GetOutput() );
261 planeWidgetY->GetResliceOutput()->GetSpacing(spc);
262 imageResult->SetOutputSpacing( spc[1], spc[0], spc[2] );
263 imageResult->SetOutputOrigin( 0,0,0 );
266 bbSetOutputPlaneX(planeWidgetX);
267 bbSetOutputPlaneY(planeWidgetY);
268 bbSetOutputPlaneZ(planeWidgetZ);
269 bbSetOutputPlane3Pts(planeWidget3Pts);
270 bbSetOutputImageX( flipYFilter->GetOutput() ); // EED MPR view orientation correction..
271 bbSetOutputImageY( imageResult->GetOutput() ); // EED MPR view orientation correction..
272 bbSetOutputImageZ(planeWidgetZ->GetResliceOutput());
273 bbSetInputInteractor(0);
274 //bbSetOutputImage3Pts(planeWidget3Pts->GetResliceOutput());
278 picker->UnRegister(NULL);
281 mVtkCallback = VtkCallbackType::New();
282 mVtkCallback->SetBlackBox(this);
283 planeWidgetX->AddObserver(vtkCommand::InteractionEvent,mVtkCallback);
284 planeWidgetY->AddObserver(vtkCommand::InteractionEvent,mVtkCallback);
285 planeWidgetZ->AddObserver(vtkCommand::InteractionEvent,mVtkCallback);
289 //---------------------------------------------------------------------
290 void ImagePlanes::bbUserFinalizeProcessing()
293 if (bbGetOutputPlaneX())
297 bbGetOutputPlaneX()->RemoveObserver(mVtkCallback);
298 bbGetOutputPlaneY()->RemoveObserver(mVtkCallback);
299 bbGetOutputPlaneZ()->RemoveObserver(mVtkCallback);
301 bbGetOutputPlaneX()->Delete();
302 bbGetOutputPlaneY()->Delete();
303 bbGetOutputPlaneZ()->Delete();
304 mVtkCallback->Delete();
306 //bbGetOutputPlaneX()->SetInput(NULL);
307 //bbGetOutputPlaneY()->SetInput(NULL);
308 //bbGetOutputPlaneZ()->SetInput(NULL);
313 //---------------------------------------------------------------------
314 void ImagePlanes::Process()
317 if (bbGetInputIn()!=0)
321 //EED 2017-01-01 Migration VTK7
322 #if (VTK_MAJOR_VERSION <= 5)
323 bbGetOutputPlaneX()->GetResliceOutput()->GetWholeExtent(ext);
325 #if (VTK_MAJOR_VERSION >= 6)
326 bbGetOutputPlaneX()->GetResliceOutput()->GetExtent(ext);
329 dim[0] = ext[1]-ext[0]+1;
330 dim[1] = ext[3]-ext[2]+1;
331 dim[2] = ext[5]-ext[4]+1;
332 _imageTransform->Identity();
333 _imageTransform->PostMultiply();
334 _imageTransform->Translate( (int)(-(dim[0]/2)) , (int)(-(dim[1]/2)) ,0);
335 _imageTransform->RotateZ(90);
338 if ( image != bbGetInputIn()){//bbGetInputStatus("In") != bbtk::UPTODATE ){
339 // Input image has changed : reinitialize planes
340 image = bbGetInputIn();
342 // Initial values : center of the volume (in real world, not in pixels!)
343 int xMin, xMax, yMin, yMax, zMin, zMax;
344 bbGetInputIn()->GetExtent(xMin, xMax, yMin, yMax, zMin, zMax);
345 double xSpacing, ySpacing, zSpacing;
346 bbGetInputIn()->GetSpacing(xSpacing, ySpacing, zSpacing);
348 //EED 2017-01-01 Migration VTK7
349 #if (VTK_MAJOR_VERSION <= 5)
350 bbGetOutputPlaneX()->SetInput(bbGetInputIn());
352 #if (VTK_MAJOR_VERSION >= 6)
353 bbGetOutputPlaneX()->SetInputData(bbGetInputIn());
356 bbGetOutputPlaneX()->SetPlaneOrientationToXAxes();
357 bbGetOutputPlaneX()->SetSlicePosition((xMax+xMin)/2.*xSpacing);
359 // bbGetOutputPlaneX()->SetOrigin( 58*xSpacing , 80*ySpacing , 82*zSpacing );
360 // bbGetOutputPlaneX()->SetPoint1( 0*xSpacing, 146*ySpacing, 186*zSpacing);
361 // bbGetOutputPlaneX()->SetPoint2( 126*xSpacing, 146*ySpacing, 0*zSpacing);
363 //EED 2017-01-01 Migration VTK7
364 #if (VTK_MAJOR_VERSION <= 5)
365 bbGetOutputPlaneY()->SetInput(bbGetInputIn());
367 #if (VTK_MAJOR_VERSION >= 6)
368 bbGetOutputPlaneY()->SetInputData(bbGetInputIn());
371 bbGetOutputPlaneY()->SetPlaneOrientationToYAxes();
372 bbGetOutputPlaneY()->SetSlicePosition((yMax+yMin)/2.*ySpacing);
374 //EED 2017-01-01 Migration VTK7
375 #if (VTK_MAJOR_VERSION <= 5)
376 bbGetOutputPlaneZ()->SetInput(bbGetInputIn());
378 #if (VTK_MAJOR_VERSION >= 6)
379 bbGetOutputPlaneZ()->SetInputData(bbGetInputIn());
382 bbGetOutputPlaneZ()->SetPlaneOrientationToZAxes();
383 bbGetOutputPlaneZ()->SetSlicePosition((zMax+zMin)/2.*zSpacing);
385 if (bbGetInputWindowLevel()[0]!=0)
387 bbGetOutputPlaneZ()->SetWindowLevel(bbGetInputWindowLevel()[0],
388 bbGetInputWindowLevel()[1]);
390 double *range = image->GetScalarRange();
391 bbGetOutputPlaneZ()->SetWindowLevel(range[1]-range[0],
392 0.5*(range[1]+range[0]));
396 dim[0] = xMax-xMin+1;
397 dim[1] = yMax-yMin+1;
398 dim[2] = zMax-zMin+1;
399 _imageTransform->Identity();
400 _imageTransform->PostMultiply();
401 _imageTransform->Translate( (int)(-(dim[0]/2)*(1/xSpacing)) , (int)(-(dim[2]/2)*(1/zSpacing)) ,0);
402 _imageTransform->RotateZ(90);
406 // UPDATE DES SORTIES
407 bbGetOutputPlaneX()->SetResliceInterpolate( bbGetInputInterpolation() );
408 bbGetOutputPlaneY()->SetResliceInterpolate( bbGetInputInterpolation() );
409 bbGetOutputPlaneZ()->SetResliceInterpolate( bbGetInputInterpolation() );
412 //EED 2017-01-01 Migration VTK7
413 #if (VTK_MAJOR_VERSION <= 5)
414 bbGetOutputPlaneX()->GetResliceOutput()->Update();
415 bbGetOutputPlaneY()->GetResliceOutput()->Update();
416 bbGetOutputPlaneZ()->GetResliceOutput()->Update();
418 #if (VTK_MAJOR_VERSION >= 6)
422 std::vector<int> pointsx = bbGetInputPointsX();
423 std::vector<int> pointsy = bbGetInputPointsY();
424 std::vector<int> pointsz = bbGetInputPointsZ();
426 //std::cout<<pointsx.size()<<pointsy.size()<<pointsz.size()<<std::endl;
428 if (pointsx.size()==pointsy.size() && pointsx.size()==pointsz.size()&&pointsx.size()>=3)
431 //Get the corresponding three points out of the vectors
433 origin[0] = pointsx[0];
434 origin[1] = pointsy[0];
435 origin[2] = pointsz[0];
438 point1[0] = pointsx[1];
439 point1[1] = pointsy[1];
440 point1[2] = pointsz[1];
442 point2[0] = pointsx[2];
443 point2[1] = pointsy[2];
444 point2[2] = pointsz[2];
446 //With the three points we create the corresponding X, Y and Z vectors all orthogonal to each other
447 double* vect1 = getNormal(makeVector(origin, point1));
448 double* vect2 = getNormal(makeVector(origin, point2));
449 double* crossp = getCrossProduct(vect1, vect2);
451 double *newx = getCrossProduct(vect2, crossp);
453 int ext[6],factor = 0;
454 bbGetInputIn()->GetExtent(ext);
456 factor = ext[0]<ext[3]? ext[3] : ext[0];
457 factor = factor<ext[5]? ext[5] : factor;
459 //for the plane widgets
460 vtkImagePlaneWidget* plane3pts = (vtkImagePlaneWidget*)bbGetOutputPlane3Pts();
462 //EED 2017-01-01 Migration VTK7
463 #if (VTK_MAJOR_VERSION <= 5)
464 plane3pts->SetInput(bbGetInputIn());
466 #if (VTK_MAJOR_VERSION >= 6)
467 plane3pts->SetInputData(bbGetInputIn());
470 double xSpacing, ySpacing, zSpacing;
471 bbGetInputIn()->GetSpacing(xSpacing, ySpacing, zSpacing);
472 plane3pts->SetOrigin(pointsx[0]*xSpacing,pointsy[0]*ySpacing,pointsz[0]*zSpacing);
473 plane3pts->SetPoint1((origin[0]+newx[0]*factor)*xSpacing,
474 (origin[1]+newx[1]*factor)*ySpacing,
475 (origin[2]+newx[2]*factor)*zSpacing);
476 plane3pts->SetPoint2((origin[0]+vect2[0]*factor)*xSpacing,
477 (origin[1]+vect2[1]*factor)*ySpacing,
478 (origin[2]+vect2[2]*factor)*zSpacing);
480 //EED 2017-01-01 Migration VTK7
481 #if (VTK_MAJOR_VERSION <= 5)
482 plane3pts->GetResliceOutput()->Update();
484 #if (VTK_MAJOR_VERSION >= 6)
488 //To get the slice of image out of the selected volume
489 if (_imageReslicer==NULL)
491 _imageReslicer = vtkImageReslice::New();
492 _imageReslicer->SetOutputDimensionality(2);
493 _transform = vtkTransform::New();
494 _matrix = vtkMatrix4x4::New();
496 _imageReslicer->SetInterpolationMode( bbGetInputInterpolation() );
498 //EED 2017-01-01 Migration VTK7
499 #if (VTK_MAJOR_VERSION <= 5)
500 _imageReslicer->SetInput( bbGetInputIn() );
502 #if (VTK_MAJOR_VERSION >= 6)
503 _imageReslicer->SetInputData( bbGetInputIn() );
507 _imageReslicer->SetInformationInput(bbGetInputIn());
508 //fill out the information with the created vectors and using the spacing of the image
509 _imageReslicer->SetResliceAxesDirectionCosines(newx[0]*xSpacing,newx[1]*xSpacing,newx[2]*xSpacing,
510 vect2[0]*ySpacing,vect2[1]*ySpacing,vect2[2]*ySpacing,
511 crossp[0]*zSpacing,crossp[1]*zSpacing,crossp[2]*zSpacing);
512 _imageReslicer->SetResliceAxesOrigin(origin[0]*xSpacing,origin[1]*ySpacing,origin[2]*zSpacing);
515 //EED 2017-01-01 Migration VTK7
516 #if (VTK_MAJOR_VERSION <= 5)
517 _imageReslicer->GetOutput()->Update();
518 _imageReslicer->GetOutput()->UpdateInformation();
520 #if (VTK_MAJOR_VERSION >= 6)
521 _imageReslicer->Update();
526 bbSetOutputImage3Pts(_imageReslicer->GetOutput());
530 _matrix->SetElement(0,0,newx[0]*xSpacing);
531 _matrix->SetElement(1,0,newx[1]*xSpacing);
532 _matrix->SetElement(2,0,newx[2]*xSpacing);
533 _matrix->SetElement(0,1,vect2[0]*ySpacing);
534 _matrix->SetElement(1,1,vect2[1]*ySpacing);
535 _matrix->SetElement(2,1,vect2[2]*ySpacing);
536 _matrix->SetElement(0,2,crossp[0]*zSpacing);
537 _matrix->SetElement(1,2,crossp[1]*zSpacing);
538 _matrix->SetElement(2,2,crossp[2]*zSpacing);
539 _matrix->SetElement(0,3,origin[0]*xSpacing);
540 _matrix->SetElement(1,3,origin[1]*ySpacing);
541 _matrix->SetElement(2,3,origin[2]*zSpacing);
543 _transform->SetMatrix(_matrix);
545 //set the transformation out to be used by other bbBoxes
546 bbSetOutputTransform3Pts((vtkLinearTransform*)_transform);
547 } // pointsx pointsy pointsz
551 void ImagePlanes::updateInteractor()
553 vtkRenderWindowInteractor* interactor = bbGetInputInteractor();
556 bbGetOutputPlaneX()->SetInteractor(interactor);
557 bbGetOutputPlaneX()->EnabledOn();
558 bbGetOutputPlaneY()->SetInteractor(interactor);
559 bbGetOutputPlaneY()->EnabledOn();
560 bbGetOutputPlaneZ()->SetInteractor(interactor);
561 bbGetOutputPlaneZ()->EnabledOn();
562 bbGetOutputPlane3Pts()->SetInteractor(interactor);
563 bbGetOutputPlane3Pts()->EnabledOn();
567 //-----------------------------------------------------------------
568 void vtkImageDataPointerRelay::bbUserSetDefaultValues()
573 //-----------------------------------------------------------------
574 void vtkImageDataPointerRelay::bbUserInitializeProcessing()
578 //-----------------------------------------------------------------
579 void vtkImageDataPointerRelay::bbUserFinalizeProcessing()
583 vtkImagePlaneWidget* ImagePlanes::GetPlaneWidget(unsigned char activationkey, double r, double g, double b, vtkCellPicker* picker)
585 vtkProperty* prop1 = 0;
586 vtkImagePlaneWidget* planeWidget = 0;
588 planeWidget = vtkImagePlaneWidget::New();
589 planeWidget->DisplayTextOn();
590 planeWidget->SetPicker(picker);
591 planeWidget->SetKeyPressActivationValue(activationkey);
592 prop1 = planeWidget->GetPlaneProperty();
593 prop1->SetColor(r, g, b);
598 double* ImagePlanes::getCrossProduct(double* vect0,double* vect1){
600 vectCross = new double[3];
601 vectCross[0] = vect0[1]*vect1[2]-(vect0[2]*vect1[1]);
602 vectCross[1] = -(vect0[0]*vect1[2]-(vect0[2]*vect1[0]));
603 vectCross[2] = vect0[0]*vect1[1]-(vect0[1]*vect1[0]);
608 ** Returns the magnitud of the given vector
610 double ImagePlanes::getMagnitud(double* vect){
613 mag = sqrt(pow(vect[0],2) + pow(vect[1],2) + pow(vect[2],2));
614 //std::cout<<"mag "<<mag <<std::endl;
618 ** returns the unitary vector of the given vector
619 ** u = 1/|vect| . vect
621 double* ImagePlanes::getNormal(double* vect){
624 double mag = getMagnitud(vect);
626 vectnorm = new double[3];
629 vectnorm[0] = vect[0]/mag;
630 vectnorm[1] = vect[1]/mag;
631 vectnorm[2] = vect[2]/mag;
641 double* ImagePlanes::makeVector(double podouble0[3], double podouble1[3]){
643 vect = new double[3];
645 vect[0]= podouble1[0]-podouble0[0];
646 vect[1]= podouble1[1]-podouble0[1];
647 vect[2]= podouble1[2]-podouble0[2];