1 /*=========================================================================
3 Module: $RCSfile: bbvtkImagePlanes.cxx,v $
5 Date: $Date: 2009/09/01 13:59:48 $
6 Version: $Revision: 1.30 $
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"
41 #include "vtkPolyData.h"
44 #include "vtkMetaImageWriter.h"
45 #include "vtkPNGWriter.h"
47 #include "bbstdCast.h"
48 #include <vtkCommand.h>
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"
58 //#include "vtkRenderer.h"
59 //#include "vtkCamera.h"
61 #include "vtkPlaneWidget.h"
63 #include <vtkImplicitPlaneWidget.h>
65 #include "bbstdRelay.h"
67 #include "vtkObjectFactory.h"
73 //====================================================================
74 BBTK_BLACK_BOX_TEMPLATE2_IMPLEMENTATION(Cast,
75 bbtk::AtomicBlackBox);
76 //====================================================================
77 //====================================================================
78 // BBTK_BLACK_BOX_TEMPLATE_IMPLEMENTATION(Relay,
79 // bbtk::AtomicBlackBox);
80 //====================================================================
83 using namespace bbstd;
87 typedef vtkImageData::Pointer vtkImageDataPointer;
88 BBTK_DEFINE_HUMAN_READABLE_TYPE_NAME(vtkImageDataPointer,
89 "vtkImageDataPointer");
96 //====================================================================
97 // Add the specialized adaptors to the package
98 typedef vtkImagePlaneWidget* I;
99 typedef vtkInteractorObserver* O;
101 BBTK_ADD_TEMPLATE2_BLACK_BOX_TO_PACKAGE(vtk,Cast,I,O);
103 BBTK_DEFINE_RELAY_BLACK_BOX(vtkImageDataPointer,vtk,vtkImageDataPointerRelay);
104 BBTK_BLACK_BOX_IMPLEMENTATION(vtkImageDataPointerRelay,bbtk::AtomicBlackBox);
106 BBTK_ADD_BLACK_BOX_TO_PACKAGE(vtk,vtkImageDataPointerRelay);
107 // BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(vtk,Relay,vtkImageDataPointer);
115 //================================================================
116 class ImagePlanes::VtkCallbackType : public vtkCommand
119 static VtkCallbackType *New()
121 return new VtkCallbackType;
123 //vtkTypeRevisionMacro(VtkCallbackType,vtkCommand);
125 virtual void Execute(vtkObject *caller, unsigned long, void*)
127 mBlackBox->Process();
128 mBlackBox->bbSignalOutputModification();
130 void SetBlackBox(ImagePlanes *BB) { mBlackBox = BB;};
131 // void SetVtkPlaneWidget( vtkImagePlaneWidget *planeWidget );
132 VtkCallbackType() {};
135 // vtkPlaneWidget *planeWidget;
136 ImagePlanes *mBlackBox;
138 //================================================================
140 //vtkCxxRevisionMacro(ImagePlanes::VtkCallbackType, "$Revision: 1.30 $");
142 //================================================================
144 BBTK_ADD_BLACK_BOX_TO_PACKAGE(vtk,ImagePlanes)
145 BBTK_BLACK_BOX_IMPLEMENTATION(ImagePlanes,bbtk::AtomicBlackBox);
149 void ImagePlanes::bbUserSetDefaultValues()
151 bbSetOutputPlaneX(0);
152 bbSetOutputPlaneY(0);
153 bbSetOutputPlaneZ(0);
154 bbSetOutputImageX(0);
155 bbSetOutputImageY(0);
156 bbSetOutputImageZ(0);
158 std::vector<double> vect;
161 bbSetInputWindowLevel (vect);
165 std::vector<int> vectpoints;
167 bbSetOutputPlane3Pts(0);
168 bbSetOutputImage3Pts(0);
169 bbSetInputPointsX(vectpoints);
170 bbSetInputPointsY(vectpoints);
171 bbSetInputPointsZ(vectpoints);
173 _imageReslicer = NULL;
181 void ImagePlanes::bbUserInitializeProcessing()
184 /// CREATION DES WIDGETS
185 if (bbGetOutputPlaneX() != 0) return;
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);
192 // The 3 image plane widgets
193 vtkImagePlaneWidget* planeWidgetX = vtkImagePlaneWidget::New();
194 planeWidgetX->DisplayTextOn();
195 planeWidgetX->SetPicker(picker);
196 planeWidgetX->SetKeyPressActivationValue('x');
197 vtkProperty* prop1 = planeWidgetX->GetPlaneProperty();
198 prop1->SetColor(1, 0, 0);
200 vtkImagePlaneWidget* planeWidgetY = vtkImagePlaneWidget::New();
201 planeWidgetY->DisplayTextOn();
202 planeWidgetY->SetPicker(picker);
203 planeWidgetY->SetKeyPressActivationValue('y');
204 vtkProperty* prop2 = planeWidgetY->GetPlaneProperty();
205 prop2->SetColor(1, 1, 0);
206 planeWidgetY->SetLookupTable(planeWidgetX->GetLookupTable());
208 vtkImagePlaneWidget* planeWidgetZ = vtkImagePlaneWidget::New();
209 planeWidgetZ->DisplayTextOn();
210 planeWidgetZ->SetPicker(picker);
211 planeWidgetZ->SetKeyPressActivationValue('z');
212 vtkProperty* prop3 = planeWidgetZ->GetPlaneProperty();
213 prop3->SetColor(0, 0, 1);
214 planeWidgetZ->SetLookupTable(planeWidgetX->GetLookupTable());
216 vtkImagePlaneWidget* planeWidget3Pts = vtkImagePlaneWidget::New();
217 //vtkPlaneWidget* planeWidget3Pts = vtkPlaneWidget::New();
218 planeWidget3Pts->DisplayTextOn();
219 planeWidget3Pts->SetPicker(picker);
220 planeWidget3Pts->SetKeyPressActivationValue('3');
221 vtkProperty* prop3Pts = planeWidget3Pts->GetPlaneProperty();
222 prop3Pts->SetColor(0, 1, 1);
223 planeWidget3Pts->SetLookupTable(planeWidgetX->GetLookupTable());
225 bbSetOutputPlaneX(planeWidgetX);
226 bbSetOutputPlaneY(planeWidgetY);
227 bbSetOutputPlaneZ(planeWidgetZ);
228 bbSetOutputPlane3Pts(planeWidget3Pts);
229 bbSetOutputImageX(planeWidgetX->GetResliceOutput());
230 bbSetOutputImageY(planeWidgetY->GetResliceOutput());
231 bbSetOutputImageZ(planeWidgetZ->GetResliceOutput());
232 //bbSetOutputImage3Pts(planeWidget3Pts->GetResliceOutput());
234 picker->UnRegister(NULL);
236 mVtkCallback = VtkCallbackType::New();
237 mVtkCallback->SetBlackBox(this);
238 planeWidgetX->AddObserver(vtkCommand::InteractionEvent,mVtkCallback);
239 planeWidgetY->AddObserver(vtkCommand::InteractionEvent,mVtkCallback);
240 planeWidgetZ->AddObserver(vtkCommand::InteractionEvent,mVtkCallback);
243 //---------------------------------------------------------------------
244 void ImagePlanes::bbUserFinalizeProcessing()
247 if (bbGetOutputPlaneX())
252 bbGetOutputPlaneX()->RemoveObserver(mVtkCallback);
253 bbGetOutputPlaneY()->RemoveObserver(mVtkCallback);
254 bbGetOutputPlaneZ()->RemoveObserver(mVtkCallback);
257 bbGetOutputPlaneX()->Delete();
258 bbGetOutputPlaneY()->Delete();
259 bbGetOutputPlaneZ()->Delete();
260 mVtkCallback->Delete();
262 //bbGetOutputPlaneX()->SetInput(NULL);
263 //bbGetOutputPlaneY()->SetInput(NULL);
264 //bbGetOutputPlaneZ()->SetInput(NULL);
270 //---------------------------------------------------------------------
271 void ImagePlanes::Process()
273 if (bbGetInputIn()!=0)
276 int xMin, xMax, yMin, yMax, zMin, zMax;
277 bbGetInputIn()->GetExtent(xMin, xMax, yMin, yMax, zMin, zMax);
279 if ( image != bbGetInputIn()){//bbGetInputStatus("In") != bbtk::UPTODATE ){
280 // Input image has changed : reinitialize planes
281 image = bbGetInputIn();
284 // Initial values : center of the volume (in real world, not in pixels!)
285 double xSpacing, ySpacing, zSpacing;
286 bbGetInputIn()->GetSpacing(xSpacing, ySpacing, zSpacing);
288 bbGetOutputPlaneX()->SetInput(bbGetInputIn());
289 bbGetOutputPlaneX()->SetPlaneOrientationToXAxes();
290 bbGetOutputPlaneX()->SetSlicePosition((xMax+xMin)/2.*xSpacing);
293 // bbGetOutputPlaneX()->SetOrigin( 58*xSpacing , 80*ySpacing , 82*zSpacing );
294 // bbGetOutputPlaneX()->SetPoint1( 0*xSpacing, 146*ySpacing, 186*zSpacing);
295 // bbGetOutputPlaneX()->SetPoint2( 126*xSpacing, 146*ySpacing, 0*zSpacing);
298 bbGetOutputPlaneY()->SetInput(bbGetInputIn());
299 bbGetOutputPlaneY()->SetPlaneOrientationToYAxes();
300 bbGetOutputPlaneY()->SetSlicePosition((yMax+yMin)/2.*ySpacing);
302 bbGetOutputPlaneZ()->SetInput(bbGetInputIn());
303 bbGetOutputPlaneZ()->SetPlaneOrientationToZAxes();
304 bbGetOutputPlaneZ()->SetSlicePosition((zMax+zMin)/2.*zSpacing);
306 if (bbGetInputWindowLevel()[0]!=0)
308 bbGetOutputPlaneZ()->SetWindowLevel(bbGetInputWindowLevel()[0],
309 bbGetInputWindowLevel()[1]);
313 double *range = image->GetScalarRange();
314 bbGetOutputPlaneZ()->SetWindowLevel(range[1] - range[0],
315 0.5*(range[1]+range[0]));
319 // UPDATE DES SORTIES
320 bbGetOutputPlaneX()->GetResliceOutput()->Update();
321 bbGetOutputPlaneY()->GetResliceOutput()->Update();
322 bbGetOutputPlaneZ()->GetResliceOutput()->Update();
324 std::vector<int> pointsx = bbGetInputPointsX();
325 std::vector<int> pointsy = bbGetInputPointsY();
326 std::vector<int> pointsz = bbGetInputPointsZ();
328 std::cout<<pointsx.size()<<pointsy.size()<<pointsz.size()<<std::endl;
330 if(pointsx.size()==pointsy.size() && pointsx.size()==pointsz.size()&&pointsx.size()>=3){
333 //Get the corresponding three points out of the vectors
335 origin[0] = pointsx[0];
336 origin[1] = pointsy[0];
337 origin[2] = pointsz[0];
340 point1[0] = pointsx[1];
341 point1[1] = pointsy[1];
342 point1[2] = pointsz[1];
344 point2[0]= pointsx[2];
345 point2[1]= pointsy[2];
346 point2[2]= pointsz[2];
348 //With the three points we create the corresponding X, Y and Z vectors all orthogonal to each other
349 double* vect1= getNormal(makeVector(origin, point1));
350 double* vect2= getNormal(makeVector(origin, point2));
351 double* crossp = getCrossProduct(vect1, vect2);
353 double *newx = getCrossProduct(vect2, crossp);
356 bbGetInputIn()->GetExtent(ext);
358 factor = ext[0]<ext[3]? ext[3] : ext[0];
359 factor = factor<ext[5]? ext[5] : factor;
361 //for the plane widgets
362 vtkImagePlaneWidget* plane3pts = (vtkImagePlaneWidget*)bbGetOutputPlane3Pts();
363 plane3pts->SetInput(bbGetInputIn());
364 double xSpacing, ySpacing, zSpacing;
365 bbGetInputIn()->GetSpacing(xSpacing, ySpacing, zSpacing);
366 plane3pts->SetOrigin(pointsx[0]*xSpacing,pointsy[0]*ySpacing,pointsz[0]*zSpacing);
367 plane3pts->SetPoint1((origin[0]+newx[0]*factor)*xSpacing,
368 (origin[1]+newx[1]*factor)*ySpacing,
369 (origin[2]+newx[2]*factor)*zSpacing);
370 plane3pts->SetPoint2((origin[0]+vect2[0]*factor)*xSpacing,
371 (origin[1]+vect2[1]*factor)*ySpacing,
372 (origin[2]+vect2[2]*factor)*zSpacing);
373 plane3pts->GetResliceOutput()->Update();
374 //To get the slice of image out of the selected volume
375 if (_imageReslicer==NULL){
376 _imageReslicer = vtkImageReslice::New();
377 _imageReslicer->SetOutputDimensionality(2);
378 _imageReslicer->SetInterpolationModeToLinear();
379 _transform = vtkTransform::New();
380 _matrix = vtkMatrix4x4::New();
382 _imageReslicer->SetInput( bbGetInputIn() );
383 _imageReslicer->SetInformationInput(bbGetInputIn());
384 //fill out the information with the created vectors and using the spacing of the image
385 _imageReslicer->SetResliceAxesDirectionCosines(newx[0]*xSpacing,newx[1]*xSpacing,newx[2]*xSpacing,
386 vect2[0]*ySpacing,vect2[1]*ySpacing,vect2[2]*ySpacing,
387 crossp[0]*zSpacing,crossp[1]*zSpacing,crossp[2]*zSpacing);
388 _imageReslicer->SetResliceAxesOrigin(origin[0]*xSpacing,origin[1]*ySpacing,origin[2]*zSpacing);
389 _imageReslicer->GetOutput()->Update();
390 _imageReslicer->GetOutput()->UpdateInformation();
393 bbSetOutputImage3Pts(_imageReslicer->GetOutput());
399 _matrix->SetElement(0,0,newx[0]*xSpacing);
400 _matrix->SetElement(1,0,newx[1]*xSpacing);
401 _matrix->SetElement(2,0,newx[2]*xSpacing);
402 _matrix->SetElement(0,1,vect2[0]*ySpacing);
403 _matrix->SetElement(1,1,vect2[1]*ySpacing);
404 _matrix->SetElement(2,1,vect2[2]*ySpacing);
405 _matrix->SetElement(0,2,crossp[0]*zSpacing);
406 _matrix->SetElement(1,2,crossp[1]*zSpacing);
407 _matrix->SetElement(2,2,crossp[2]*zSpacing);
408 _matrix->SetElement(0,3,origin[0]*xSpacing);
409 _matrix->SetElement(1,3,origin[1]*ySpacing);
410 _matrix->SetElement(2,3,origin[2]*zSpacing);
413 _transform->SetMatrix(_matrix);
415 //set the transformation out to be used by other bbBoxes
416 bbSetOutputTransform3Pts((vtkLinearTransform*)_transform);
425 //-----------------------------------------------------------------
426 void vtkImageDataPointerRelay::bbUserSetDefaultValues()
430 //-----------------------------------------------------------------
431 void vtkImageDataPointerRelay::bbUserInitializeProcessing()
435 //-----------------------------------------------------------------
436 void vtkImageDataPointerRelay::bbUserFinalizeProcessing()
442 double* ImagePlanes::getCrossProduct(double* vect0,double* vect1){
444 vectCross = new double[3];
445 vectCross[0] = vect0[1]*vect1[2]-(vect0[2]*vect1[1]);
446 vectCross[1] = -(vect0[0]*vect1[2]-(vect0[2]*vect1[0]));
447 vectCross[2] = vect0[0]*vect1[1]-(vect0[1]*vect1[0]);
452 ** Returns the magnitud of the given vector
454 double ImagePlanes::getMagnitud(double* vect){
458 mag = sqrt(pow(vect[0],2) + pow(vect[1],2) + pow(vect[2],2));
460 std::cout<<"mag "<<mag <<std::endl;
466 ** returns the unitary vector of the given vector
467 ** u = 1/|vect| . vect
469 double* ImagePlanes::getNormal(double* vect){
472 double mag = getMagnitud(vect);
474 vectnorm = new double[3];
478 vectnorm[0] = vect[0]/mag;
479 vectnorm[1] = vect[1]/mag;
480 vectnorm[2] = vect[2]/mag;
492 double* ImagePlanes::makeVector(double podouble0[3], double podouble1[3]){
494 vect = new double[3];
496 vect[0]= podouble1[0]-podouble0[0];
497 vect[1]= podouble1[1]-podouble0[1];
498 vect[2]= podouble1[2]-podouble0[2];