1 /*=========================================================================
3 Module: $RCSfile: bbvtkImagePlanes.cxx,v $
5 Date: $Date: 2009/06/24 07:56:02 $
6 Version: $Revision: 1.28 $
7 =========================================================================*/
9 /* ---------------------------------------------------------------------
11 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
12 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
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.
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
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 * ------------------------------------------------------------------------ */
37 #include "bbvtkImagePlanes.h"
38 #include "bbvtkPackage.h"
39 #include "vtkCellPicker.h"
40 #include "vtkProperty.h"
43 #include "vtkMetaImageWriter.h"
44 #include "vtkPNGWriter.h"
46 #include "bbstdCast.h"
47 #include <vtkCommand.h>
49 #include "vtkImageData.h"
50 //#include "vtkOutlineFilter.h"
51 //#include "vtkPolyDataMapper.h"
52 //#include "vtkActor.h"
53 #include "vtkImagePlaneWidget.h"
54 #include "vtkCellPicker.h"
55 //#include "vtkProperty.h"
57 //#include "vtkRenderer.h"
58 //#include "vtkCamera.h"
60 #include "vtkPlaneWidget.h"
62 #include <vtkImplicitPlaneWidget.h>
64 #include "bbstdRelay.h"
66 #include "vtkObjectFactory.h"
72 //====================================================================
73 BBTK_BLACK_BOX_TEMPLATE2_IMPLEMENTATION(Cast,
74 bbtk::AtomicBlackBox);
75 //====================================================================
76 //====================================================================
77 // BBTK_BLACK_BOX_TEMPLATE_IMPLEMENTATION(Relay,
78 // bbtk::AtomicBlackBox);
79 //====================================================================
82 using namespace bbstd;
86 typedef vtkImageData::Pointer vtkImageDataPointer;
87 BBTK_DEFINE_HUMAN_READABLE_TYPE_NAME(vtkImageDataPointer,
88 "vtkImageDataPointer");
95 //====================================================================
96 // Add the specialized adaptors to the package
97 typedef vtkImagePlaneWidget* I;
98 typedef vtkInteractorObserver* O;
100 BBTK_ADD_TEMPLATE2_BLACK_BOX_TO_PACKAGE(vtk,Cast,I,O);
102 BBTK_DEFINE_RELAY_BLACK_BOX(vtkImageDataPointer,vtk,vtkImageDataPointerRelay);
103 BBTK_BLACK_BOX_IMPLEMENTATION(vtkImageDataPointerRelay,bbtk::AtomicBlackBox);
105 BBTK_ADD_BLACK_BOX_TO_PACKAGE(vtk,vtkImageDataPointerRelay);
106 // BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(vtk,Relay,vtkImageDataPointer);
114 //================================================================
115 class ImagePlanes::VtkCallbackType : public vtkCommand
118 static VtkCallbackType *New()
120 return new VtkCallbackType;
122 //vtkTypeRevisionMacro(VtkCallbackType,vtkCommand);
124 virtual void Execute(vtkObject *caller, unsigned long, void*)
126 mBlackBox->Process();
127 mBlackBox->bbSignalOutputModification();
129 void SetBlackBox(ImagePlanes *BB) { mBlackBox = BB;};
130 // void SetVtkPlaneWidget( vtkImagePlaneWidget *planeWidget );
131 VtkCallbackType() {};
134 // vtkPlaneWidget *planeWidget;
135 ImagePlanes *mBlackBox;
137 //================================================================
139 //vtkCxxRevisionMacro(ImagePlanes::VtkCallbackType, "$Revision: 1.28 $");
141 //================================================================
143 BBTK_ADD_BLACK_BOX_TO_PACKAGE(vtk,ImagePlanes)
144 BBTK_BLACK_BOX_IMPLEMENTATION(ImagePlanes,bbtk::AtomicBlackBox);
148 void ImagePlanes::bbUserSetDefaultValues()
150 bbSetOutputPlaneX(0);
151 bbSetOutputPlaneY(0);
152 bbSetOutputPlaneZ(0);
153 bbSetOutputImageX(0);
154 bbSetOutputImageY(0);
155 bbSetOutputImageZ(0);
157 std::vector<double> vect;
160 bbSetInputWindowLevel (vect);
164 std::vector<int> vectpoints;
166 bbSetOutputPlane3Pts(0);
167 bbSetOutputImage3Pts(0);
168 bbSetInputPointsX(vectpoints);
169 bbSetInputPointsY(vectpoints);
170 bbSetInputPointsZ(vectpoints);
172 _imageReslicer = NULL;
178 void ImagePlanes::bbUserInitializeProcessing()
181 /// CREATION DES WIDGETS
182 if (bbGetOutputPlaneX() != 0) return;
184 // The shared picker enables us to use 3 planes at one time
185 // and gets the picking order right
186 vtkCellPicker* picker = vtkCellPicker::New();
187 picker->SetTolerance(0.005);
189 // The 3 image plane widgets
190 vtkImagePlaneWidget* planeWidgetX = vtkImagePlaneWidget::New();
191 planeWidgetX->DisplayTextOn();
192 planeWidgetX->SetPicker(picker);
193 planeWidgetX->SetKeyPressActivationValue('x');
194 vtkProperty* prop1 = planeWidgetX->GetPlaneProperty();
195 prop1->SetColor(1, 0, 0);
197 vtkImagePlaneWidget* planeWidgetY = vtkImagePlaneWidget::New();
198 planeWidgetY->DisplayTextOn();
199 planeWidgetY->SetPicker(picker);
200 planeWidgetY->SetKeyPressActivationValue('y');
201 vtkProperty* prop2 = planeWidgetY->GetPlaneProperty();
202 prop2->SetColor(1, 1, 0);
203 planeWidgetY->SetLookupTable(planeWidgetX->GetLookupTable());
205 vtkImagePlaneWidget* planeWidgetZ = vtkImagePlaneWidget::New();
206 planeWidgetZ->DisplayTextOn();
207 planeWidgetZ->SetPicker(picker);
208 planeWidgetZ->SetKeyPressActivationValue('z');
209 vtkProperty* prop3 = planeWidgetZ->GetPlaneProperty();
210 prop3->SetColor(0, 0, 1);
211 planeWidgetZ->SetLookupTable(planeWidgetX->GetLookupTable());
213 vtkImagePlaneWidget* planeWidget3Pts = vtkImagePlaneWidget::New();
214 //vtkPlaneWidget* planeWidget3Pts = vtkPlaneWidget::New();
215 planeWidget3Pts->DisplayTextOn();
216 planeWidget3Pts->SetPicker(picker);
217 planeWidget3Pts->SetKeyPressActivationValue('3');
218 vtkProperty* prop3Pts = planeWidget3Pts->GetPlaneProperty();
219 prop3Pts->SetColor(0, 1, 1);
220 planeWidget3Pts->SetLookupTable(planeWidgetX->GetLookupTable());
222 bbSetOutputPlaneX(planeWidgetX);
223 bbSetOutputPlaneY(planeWidgetY);
224 bbSetOutputPlaneZ(planeWidgetZ);
225 bbSetOutputPlane3Pts(planeWidget3Pts);
226 bbSetOutputImageX(planeWidgetX->GetResliceOutput());
227 bbSetOutputImageY(planeWidgetY->GetResliceOutput());
228 bbSetOutputImageZ(planeWidgetZ->GetResliceOutput());
229 //bbSetOutputImage3Pts(planeWidget3Pts->GetResliceOutput());
231 picker->UnRegister(NULL);
233 mVtkCallback = VtkCallbackType::New();
234 mVtkCallback->SetBlackBox(this);
235 planeWidgetX->AddObserver(vtkCommand::InteractionEvent,mVtkCallback);
236 planeWidgetY->AddObserver(vtkCommand::InteractionEvent,mVtkCallback);
237 planeWidgetZ->AddObserver(vtkCommand::InteractionEvent,mVtkCallback);
240 //---------------------------------------------------------------------
241 void ImagePlanes::bbUserFinalizeProcessing()
244 if (bbGetOutputPlaneX())
249 bbGetOutputPlaneX()->RemoveObserver(mVtkCallback);
250 bbGetOutputPlaneY()->RemoveObserver(mVtkCallback);
251 bbGetOutputPlaneZ()->RemoveObserver(mVtkCallback);
254 bbGetOutputPlaneX()->Delete();
255 bbGetOutputPlaneY()->Delete();
256 bbGetOutputPlaneZ()->Delete();
257 mVtkCallback->Delete();
259 //bbGetOutputPlaneX()->SetInput(NULL);
260 //bbGetOutputPlaneY()->SetInput(NULL);
261 //bbGetOutputPlaneZ()->SetInput(NULL);
267 //---------------------------------------------------------------------
268 void ImagePlanes::Process()
270 if (bbGetInputIn()!=0)
273 if ( image != bbGetInputIn()){//bbGetInputStatus("In") != bbtk::UPTODATE ){
274 // Input image has changed : reinitialize planes
275 image = bbGetInputIn();
277 int xMin, xMax, yMin, yMax, zMin, zMax;
278 bbGetInputIn()->GetExtent(xMin, xMax, yMin, yMax, zMin, zMax);
280 // Initial values : center of the volume (in real world, not in pixels!)
281 double xSpacing, ySpacing, zSpacing;
282 bbGetInputIn()->GetSpacing(xSpacing, ySpacing, zSpacing);
284 bbGetOutputPlaneX()->SetInput(bbGetInputIn());
285 bbGetOutputPlaneX()->SetPlaneOrientationToXAxes();
286 bbGetOutputPlaneX()->SetSlicePosition((xMax+xMin)/2.*xSpacing);
289 // bbGetOutputPlaneX()->SetOrigin( 58*xSpacing , 80*ySpacing , 82*zSpacing );
290 // bbGetOutputPlaneX()->SetPoint1( 0*xSpacing, 146*ySpacing, 186*zSpacing);
291 // bbGetOutputPlaneX()->SetPoint2( 126*xSpacing, 146*ySpacing, 0*zSpacing);
294 bbGetOutputPlaneY()->SetInput(bbGetInputIn());
295 bbGetOutputPlaneY()->SetPlaneOrientationToYAxes();
296 bbGetOutputPlaneY()->SetSlicePosition((yMax+yMin)/2.*ySpacing);
298 bbGetOutputPlaneZ()->SetInput(bbGetInputIn());
299 bbGetOutputPlaneZ()->SetPlaneOrientationToZAxes();
300 bbGetOutputPlaneZ()->SetSlicePosition((zMax+zMin)/2.*zSpacing);
302 if (bbGetInputWindowLevel()[0]!=0)
304 bbGetOutputPlaneZ()->SetWindowLevel(bbGetInputWindowLevel()[0],
305 bbGetInputWindowLevel()[1]);
309 double *range = image->GetScalarRange();
310 bbGetOutputPlaneZ()->SetWindowLevel(range[1] - range[0],
311 0.5*(range[1]+range[0]));
315 // UPDATE DES SORTIES
316 bbGetOutputPlaneX()->GetResliceOutput()->Update();
317 bbGetOutputPlaneY()->GetResliceOutput()->Update();
318 bbGetOutputPlaneZ()->GetResliceOutput()->Update();
320 std::vector<int> pointsx = bbGetInputPointsX();
321 std::vector<int> pointsy = bbGetInputPointsY();
322 std::vector<int> pointsz = bbGetInputPointsZ();
324 std::cout<<pointsx.size()<<pointsy.size()<<pointsz.size()<<std::endl;
326 if(pointsx.size()==pointsy.size() && pointsx.size()==pointsz.size()&&pointsx.size()>=3){
327 vtkImagePlaneWidget* plane3pts = (vtkImagePlaneWidget*)bbGetOutputPlane3Pts();
328 //vtkPlaneWidget* plane3pts = (vtkPlaneWidget*)bbGetOutputPlane3Pts();
330 plane3pts->SetInput(bbGetInputIn());
332 //xSpacing = ySpacing = zSpacing = 1;
333 double xSpacing, ySpacing, zSpacing;
334 bbGetInputIn()->GetSpacing(xSpacing, ySpacing, zSpacing);
336 plane3pts->SetOrigin(pointsx[0]*xSpacing,pointsy[0]*ySpacing,pointsz[0]*zSpacing);
337 plane3pts->SetPoint1(pointsx[1]*xSpacing,pointsy[1]*ySpacing,pointsz[1]*zSpacing);
338 //plane3pts->SetPoint1((pointsx[1]-pointsx[0])*xSpacing,(pointsy[1]-pointsy[0])*ySpacing,(pointsz[1]-pointsz[0])*zSpacing);
339 plane3pts->SetPoint2(pointsx[2]*xSpacing,pointsy[2]*ySpacing,pointsz[2]*zSpacing);
340 //plane3pts->SetPoint2((pointsx[2]-pointsx[0])*xSpacing,(pointsy[2]-pointsy[0])*ySpacing,(pointsz[2]-pointsz[0])*zSpacing);
341 plane3pts->GetResliceOutput()->Update();
345 if (_imageReslicer==NULL){
346 _imageReslicer = vtkImageReslice::New();
347 _imageReslicer->SetOutputDimensionality(2);
348 _imageReslicer->SetInterpolationModeToLinear();
351 _imageReslicer->SetInput( bbGetInputIn() );
352 _imageReslicer->SetInformationInput(bbGetInputIn());
355 origin[0] = pointsx[0];
356 origin[1] = pointsy[0];
357 origin[2] = pointsz[0];
360 point1[0] = pointsx[1];
361 point1[1] = pointsy[1];
362 point1[2] = pointsz[1];
364 point2[0]= pointsx[2];
365 point2[1]= pointsy[2];
366 point2[2]= pointsz[2];
368 double* vect1= getNormal(makeVector(origin, point1));
369 double* vect2= getNormal(makeVector(origin, point2));
370 double* crossp = getCrossProduct(vect1, vect2);
372 /*std::cout<<"origin "<<origin[0]<<" "<<origin[1]<<" "<<origin[2]<<" "<<std::endl;
373 std::cout<<"point1 "<<point1[0]<<" "<<point1[1]<<" "<<point1[2]<<" "<<std::endl;
374 std::cout<<"point2 "<<point2[0]<<" "<<point2[1]<<" "<<point2[2]<<" "<<std::endl;
375 std::cout<<"vect1 "<<vect1[0]<<" "<<vect1[1]<<" "<<vect1[2]<<" "<<std::endl;
376 std::cout<<"vect2 "<<vect2[0]<<" "<<vect2[1]<<" "<<vect2[2]<<" "<<std::endl;
377 std::cout<<"crossp "<<crossp[0]<<" "<<crossp[1]<<" "<<crossp[2]<<" "<<std::endl;*/
380 _imageReslicer->SetResliceAxesDirectionCosines(vect1[0],vect1[1],vect1[2],
381 vect2[0],vect2[1],vect2[2],
382 crossp[0],crossp[1],crossp[2]);
383 //_imageReslicer->SetResliceAxesOrigin(0,0,0);
384 _imageReslicer->SetResliceAxesOrigin(origin[0],origin[1],origin[2]);
386 _imageReslicer->GetOutput()->Update();
387 _imageReslicer->GetOutput()->UpdateInformation();
389 bbSetOutputImage3Pts(_imageReslicer->GetOutput());
396 //-----------------------------------------------------------------
397 void vtkImageDataPointerRelay::bbUserSetDefaultValues()
401 //-----------------------------------------------------------------
402 void vtkImageDataPointerRelay::bbUserInitializeProcessing()
406 //-----------------------------------------------------------------
407 void vtkImageDataPointerRelay::bbUserFinalizeProcessing()
413 double* ImagePlanes::getCrossProduct(double* vect0,double* vect1){
415 vectCross = new double[3];
416 vectCross[0] = vect0[1]*vect1[2]-(vect0[2]*vect1[1]);
417 vectCross[1] = -(vect0[0]*vect1[2]-(vect0[2]*vect1[0]));
418 vectCross[2] = vect0[0]*vect1[1]-(vect0[1]*vect1[0]);
423 ** Returns the magnitud of the given vector
425 double ImagePlanes::getMagnitud(double* vect){
429 mag = sqrt(pow(vect[0],2) + pow(vect[1],2) + pow(vect[2],2));
431 std::cout<<"mag "<<mag <<std::endl;
437 ** returns the unitary vector of the given vector
438 ** u = 1/|vect| . vect
440 double* ImagePlanes::getNormal(double* vect){
443 double mag = getMagnitud(vect);
445 vectnorm = new double[3];
449 vectnorm[0] = vect[0]/mag;
450 vectnorm[1] = vect[1]/mag;
451 vectnorm[2] = vect[2]/mag;
463 double* ImagePlanes::makeVector(double podouble0[3], double podouble1[3]){
465 vect = new double[3];
467 vect[0]= podouble0[0]-podouble1[0];
468 vect[1]= podouble0[1]-podouble1[1];
469 vect[2]= podouble0[2]-podouble1[2];