]> Creatis software - clitk.git/blob - vv/vvToolRigidReg.cxx
Debug try with ImageReslice update and autoCrop
[clitk.git] / vv / vvToolRigidReg.cxx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to:
5   - University of LYON              http://www.universite-lyon.fr/
6   - Léon Bérard cancer center       http://www.centreleonberard.fr
7   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
9   This software is distributed WITHOUT ANY WARRANTY; without even
10   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11   PURPOSE.  See the copyright notices for more information.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================**/
18
19 // vv
20 #include "vvToolRigidReg.h"
21 #include "vvSlicer.h"
22 #include <vvBlendImageActor.h>
23
24 // vtk
25 #include <vtkImageData.h>
26 #include <vtkSmartPointer.h>
27 #include <vtkInformation.h>
28 #include <vtkTransform.h>
29 #include <vtkImageActor.h>
30 #include <vtkImageMapper3D.h>
31 #include <vtkOpenGLImageSliceMapper.h>
32
33 // itk
34 #include <itkEuler3DTransform.h>
35
36 // clitk
37 #include "clitkTransformUtilities.h"
38 #include "clitkMatrix.h"
39
40 // qt
41 #include <QMessageBox>
42 #include <QFileDialog>
43 #include <QTextStream>
44
45
46 //------------------------------------------------------------------------------
47 // Create the tool and automagically (I like this word) insert it in
48 // the main window menu.
49 ADD_TOOL(vvToolRigidReg);
50 //------------------------------------------------------------------------------
51
52 //------------------------------------------------------------------------------
53 vvToolRigidReg::vvToolRigidReg(vvMainWindowBase * parent, Qt::WindowFlags f):
54     vvToolWidgetBase(parent, f),
55     vvToolBase<vvToolRigidReg>(parent),
56     Ui::vvToolRigidReg()
57 {
58   // GUI Initialization
59   Ui_vvToolRigidReg::setupUi(mToolWidget);
60   
61   // Set how many inputs are needed for this tool
62   AddInputSelector("Select moving image");
63
64   QFont font = transformationLabel->font();
65   font.setStyleHint(QFont::TypeWriter);
66   transformationLabel->setFont(font);
67
68   mInitialMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
69
70   // Set slider ranges, assume degrees, will not be changed for radians
71   std::vector<QSlider *> transSliders, rotSliders;
72   std::vector<QDoubleSpinBox *> transSBs, rotSBs;
73   GetSlidersAndSpinBoxes(transSliders, rotSliders, transSBs, rotSBs);
74   for(int i=0; i<3; i++) {
75     transSliders[i]->setRange(-2000,2000);
76     rotSliders[i]->setRange(-360,360);
77     transSBs[i]->setRange(-2000,2000);
78     transSBs[i]->setDecimals(3);
79     rotSBs[i]->setRange(-360,360);
80     rotSBs[i]->setDecimals(3);
81   }
82 }
83 //------------------------------------------------------------------------------
84
85 //------------------------------------------------------------------------------
86 vvToolRigidReg::~vvToolRigidReg()
87 {
88 }
89 //------------------------------------------------------------------------------
90
91 //------------------------------------------------------------------------------
92 void vvToolRigidReg::Initialize()
93 {
94   SetToolName("Register");
95   SetToolMenuName("Register manually");
96   SetToolIconFilename(":/common/icons/register.png");
97   SetToolTip("Register manually.");
98   SetToolExperimental(false);
99 }
100 //------------------------------------------------------------------------------
101
102 //------------------------------------------------------------------------------
103 void vvToolRigidReg::InputIsSelected(vvSlicerManager *input)
104 {
105   mInput = input;
106   HideInputSelector();
107   QTabWidget * tab = dynamic_cast<vvMainWindow*>(mMainWindow)->GetTab();
108   move(tab->mapToGlobal(tab->pos()));
109   resize(tab->width(), 0);
110
111   //default image rotation center is the center of the image
112   QString xcord,ycord,zcord;
113   std::vector<double> imageorigin;
114   imageorigin=mInput->GetImage()->GetOrigin();
115   std::vector<int> imageSize = mInput->GetImage()->GetSize();
116   std::vector<double> imageSpacing = mInput->GetImage()->GetSpacing();
117   xcord=xcord.setNum(imageorigin[0]+(imageSize[0]-1)*imageSpacing[0]*0.5, 'g', 3);
118   ycord=ycord.setNum(imageorigin[1]+(imageSize[1]-1)*imageSpacing[1]*0.5, 'g', 3);
119   zcord=zcord.setNum(imageorigin[2]+(imageSize[2]-1)*imageSpacing[2]*0.5, 'g', 3);
120   Xval->setText(xcord);
121   Yval->setText(ycord);
122   Zval->setText(zcord);
123
124   //backup original matrix
125   for(int j=0; j<4; j++)
126     for(int i=0; i<4; i++)
127       // TODO SR and BP: check on the list of transforms and not the first only
128       mInitialMatrix->SetElement(i,j, mCurrentSlicerManager->GetImage()->GetTransform()[0]->GetMatrix()->GetElement(i,j));
129   QString origTransformString(clitk::Get4x4MatrixDoubleAsString(mInitialMatrix).c_str());
130   transformationLabel->setText(origTransformString);
131   SetTransform(mInitialMatrix);
132
133   //connect all sigs to slots
134   connect(resetbutton, SIGNAL(pressed()), this, SLOT(ResetTransform()));
135   connect(loadbutton, SIGNAL(pressed()), this, SLOT(LoadFile()));
136   connect(savebutton, SIGNAL(pressed()), this, SLOT(SaveFile()));
137
138   connect(xtrans_slider, SIGNAL(valueChanged(int)), this, SLOT(SliderChange(int)));
139   connect(ytrans_slider, SIGNAL(valueChanged(int)), this, SLOT(SliderChange(int)));
140   connect(ztrans_slider, SIGNAL(valueChanged(int)), this, SLOT(SliderChange(int)));
141   connect(xrot_slider, SIGNAL(valueChanged(int)), this, SLOT(SliderChange(int)));
142   connect(yrot_slider, SIGNAL(valueChanged(int)), this, SLOT(SliderChange(int)));
143   connect(zrot_slider, SIGNAL(valueChanged(int)), this, SLOT(SliderChange(int)));
144   connect(xtrans_sb, SIGNAL(valueChanged(double)), this, SLOT(SpinBoxChange(double)));
145   connect(ytrans_sb, SIGNAL(valueChanged(double)), this, SLOT(SpinBoxChange(double)));
146   connect(ztrans_sb, SIGNAL(valueChanged(double)), this, SLOT(SpinBoxChange(double)));
147   connect(xrot_sb,   SIGNAL(valueChanged(double)), this, SLOT(SpinBoxChange(double)));
148   connect(yrot_sb,   SIGNAL(valueChanged(double)), this, SLOT(SpinBoxChange(double)));
149   connect(zrot_sb,   SIGNAL(valueChanged(double)), this, SLOT(SpinBoxChange(double)));
150
151   connect(stepTransSpinBox, SIGNAL(valueChanged(double)), this, SLOT(SetTranslationStep(double)));
152   connect(stepRotSpinBox, SIGNAL(valueChanged(double)), this, SLOT(SetRotationStep(double)));
153
154   connect(checkBoxDegrees, SIGNAL(stateChanged(int)), this, SLOT(ToggleSpinBoxAnglesUnit()));
155
156   connect(Xval, SIGNAL(editingFinished()), this, SLOT(ChangeOfRotationCenter()));
157   connect(Yval, SIGNAL(editingFinished()), this, SLOT(ChangeOfRotationCenter()));
158   connect(Zval, SIGNAL(editingFinished()), this, SLOT(ChangeOfRotationCenter()));
159
160   // Init step modifiers
161   stepTransSpinBox->setValue(1.);
162   stepRotSpinBox->setValue(1.);
163 }
164 //------------------------------------------------------------------------------
165
166 //------------------------------------------------------------------------------
167 void vvToolRigidReg::apply()
168 {
169   vvToolWidgetBase::close();
170 }
171 //------------------------------------------------------------------------------
172
173 //------------------------------------------------------------------------------
174 bool vvToolRigidReg::close()
175 {
176   QString warning = "Are you sure you want to reset the original transform?";
177   QMessageBox msgBox(QMessageBox::Warning, tr("Reset transform"),warning, 0, this);
178   msgBox.addButton(tr("Yes"), QMessageBox::AcceptRole);
179   msgBox.addButton(tr("No"), QMessageBox::RejectRole);
180   if (msgBox.exec() == QMessageBox::AcceptRole) {
181     SetTransform(mInitialMatrix);
182     return vvToolWidgetBase::close();
183   }
184   return false;
185 }
186 //------------------------------------------------------------------------------
187
188 //------------------------------------------------------------------------------
189 void vvToolRigidReg::reject()
190 {
191   return vvToolWidgetBase::reject();
192 }
193 //------------------------------------------------------------------------------
194
195 //------------------------------------------------------------------------------
196 void vvToolRigidReg::SetTranslationStep(double v)
197 {
198   xtrans_sb->setSingleStep(v);
199   ytrans_sb->setSingleStep(v);
200   ztrans_sb->setSingleStep(v);
201 }
202 //------------------------------------------------------------------------------
203
204 //------------------------------------------------------------------------------
205 void vvToolRigidReg::SetRotationStep(double v)
206 {
207   xrot_sb->setSingleStep(v);
208   yrot_sb->setSingleStep(v);
209   zrot_sb->setSingleStep(v);
210 }
211 //------------------------------------------------------------------------------
212
213 //------------------------------------------------------------------------------
214 void vvToolRigidReg::SliderChange(int newVal)
215 {
216   std::vector<QSlider *> transSliders, rotSliders;
217   std::vector<QDoubleSpinBox *> transSBs, rotSBs;
218   GetSlidersAndSpinBoxes(transSliders, rotSliders, transSBs, rotSBs);
219   for(int i=0; i<3; i++) {
220     if(transSliders[i] == QObject::sender()) {
221       transSBs[i]->setValue(newVal);
222     }
223     if(rotSliders[i] == QObject::sender()) {
224       double rad = (checkBoxDegrees->checkState()==Qt::Unchecked)?itk::Math::pi/180.:1.;
225       rotSBs[i]->setValue(newVal*rad);
226     }
227   }
228 }
229 //------------------------------------------------------------------------------
230
231 //------------------------------------------------------------------------------
232 void vvToolRigidReg::SpinBoxChange(double newVal)
233 {
234   std::vector<QSlider *> transSliders, rotSliders;
235   std::vector<QDoubleSpinBox *> transSBs, rotSBs;
236   GetSlidersAndSpinBoxes(transSliders, rotSliders, transSBs, rotSBs);
237   for(int i=0; i<3; i++) {
238     if(transSBs[i] == QObject::sender()) {
239       transSliders[i]->blockSignals(true);
240       transSliders[i]->setValue(itk::Math::Round<double,double>(newVal));
241       transSliders[i]->blockSignals(false);
242     }
243     if(rotSBs[i] == QObject::sender()) {
244       double rad = (checkBoxDegrees->checkState()==Qt::Unchecked)?180./itk::Math::pi:1.;
245       rotSliders[i]->blockSignals(true);
246       rotSliders[i]->setValue(itk::Math::Round<double,double>(newVal*rad));
247       rotSliders[i]->blockSignals(false);
248     }
249   }
250
251   // Compute transform and set
252   // TODO SR and BP: check on the list of transforms and not the first only
253   vtkSmartPointer<vtkTransform> transform_final=mInput->GetImage()->GetTransform()[0];
254   transform_final->Identity();
255   transform_final->PostMultiply();
256
257   // Rotations
258   double x=0, y=0 ,z=0;
259   x= Xval->text().toDouble();
260   y= Yval->text().toDouble();
261   z= Zval->text().toDouble();
262   double rad = (checkBoxDegrees->checkState()==Qt::Unchecked)?180./itk::Math::pi:1.;
263   transform_final->Translate(-x,-y,-z);
264   transform_final->RotateY(yrot_sb->value()*rad);
265   transform_final->RotateX(xrot_sb->value()*rad);
266   transform_final->RotateZ(zrot_sb->value()*rad);
267   transform_final->Translate(x,y,z);
268
269   // Translation
270   transform_final->Translate(xtrans_sb->value(),
271                              ytrans_sb->value(),
272                              ztrans_sb->value());
273   transform_final->Update();
274   SetTransform(transform_final->GetMatrix());
275 }
276 //------------------------------------------------------------------------------
277
278 //------------------------------------------------------------------------------
279 void vvToolRigidReg::ToggleSpinBoxAnglesUnit()
280 {
281   double rad = (checkBoxDegrees->checkState()==Qt::Unchecked)?itk::Math::pi/180.:180./itk::Math::pi;
282   std::vector<QSlider *> transSliders, rotSliders;
283   std::vector<QDoubleSpinBox *> transSBs, rotSBs;
284   GetSlidersAndSpinBoxes(transSliders, rotSliders, transSBs, rotSBs);
285   for(int i=0; i<3; i++) {
286     rotSBs[i]->blockSignals(true);
287     rotSBs[i]->setValue(rotSBs[i]->value()*rad);
288     rotSBs[i]->blockSignals(false);
289   }
290 }
291 //------------------------------------------------------------------------------
292
293 //------------------------------------------------------------------------------
294 void vvToolRigidReg::SaveFile()
295 {
296   //Write the Transformation Matrix
297   std::string absPath = mCurrentSlicerManager->GetFileName();
298   absPath = itksys::SystemTools::GetFilenameWithoutExtension(absPath) + std::string(".mat");
299   QString filename = QFileDialog::getSaveFileName(this, tr("Save Transformation Matrix File"),
300                                             absPath.c_str(),
301                                             tr("Text (*.mat *.txt *.doc *.rtf)"));
302
303   QFile file(filename);
304   if (file.open(QFile::WriteOnly | QFile::Truncate)) {
305     // TODO SR and BP: check on the list of transforms and not the first only
306     vtkMatrix4x4* matrix = mCurrentSlicerManager->GetImage()->GetTransform()[0]->GetMatrix();
307     QString matrixStr = clitk::Get4x4MatrixDoubleAsString(matrix,16).c_str();
308     QTextStream out(&file);
309     out << matrixStr;
310   }
311   else
312   {
313     QMessageBox::information(this,"Error","Unable to open file for writing");
314   }
315 }
316 //------------------------------------------------------------------------------
317
318 //------------------------------------------------------------------------------
319 void vvToolRigidReg::LoadFile()
320 {
321   //Open File to read the transformation parameters
322   QString file = QFileDialog::getOpenFileName(
323                    this,
324                    "Choose the filename for the transformation matrix",
325                    vtksys::SystemTools::GetFilenamePath(mCurrentSlicerManager->GetFileName()).c_str(),
326                    "Text (*.mat *.txt *.rtf *.doc)");
327    if (file.isEmpty())
328      return;
329
330
331   itk::Matrix<double, 4, 4> itkMat = clitk::ReadMatrix3D(file.toStdString());
332   vtkSmartPointer<vtkMatrix4x4> matrix = vtkSmartPointer<vtkMatrix4x4>::New();
333   matrix->Identity();
334   for(int j=0; j<4; j++)
335     for(int i=0; i<4; i++)
336       matrix->SetElement(j,i,itkMat[j][i]);
337   SetTransform(matrix);
338 }
339 //------------------------------------------------------------------------------
340   
341 //------------------------------------------------------------------------------
342 void vvToolRigidReg::ChangeOfRotationCenter()
343 {
344   // TODO SR and BP: check on the list of transforms and not the first only
345   SetTransform(mCurrentSlicerManager->GetImage()->GetTransform()[0]->GetMatrix());
346 }
347 //------------------------------------------------------------------------------
348
349 //------------------------------------------------------------------------------
350 void vvToolRigidReg::ResetTransform()
351 {
352   SetTransform(mInitialMatrix);
353 }
354 //------------------------------------------------------------------------------
355
356 //------------------------------------------------------------------------------
357 void vvToolRigidReg::SetTransform(vtkMatrix4x4 *matrix)
358 {
359   vtkSmartPointer<vtkTransform> transform=vtkSmartPointer<vtkTransform>::New();
360   // TODO SR and BP: check on the list of transforms and not the first only
361   mCurrentSlicerManager->GetImage()->GetTransform()[0]->SetMatrix(matrix);
362   //mCurrentSlicerManager->GetSlicer(2)->GetSlicingTransform()->SetMatrix(matrix);
363   transform->Update();
364   Render();
365   dynamic_cast<vvMainWindow*>(mMainWindow)->ImageInfoChanged();
366
367   // Compute parameters from transfer using itk Euler transform
368   itk::Euler3DTransform<double>::CenterType center;
369   center[0] = Xval->text().toDouble();
370   center[1] = Yval->text().toDouble();
371   center[2] = Zval->text().toDouble();
372   itk::Euler3DTransform<double>::MatrixType rotMat;
373   itk::Euler3DTransform<double>::OutputVectorType transVec;
374   for(int i=0; i<3; i++) {
375     transVec[i] = matrix->GetElement(i,3);
376     for(int j=0; j<3; j++)
377       rotMat[i][j] = matrix->GetElement(i,j);
378   }
379   itk::Euler3DTransform<double>::Pointer euler;
380   euler = itk::Euler3DTransform<double>::New();
381   euler->SetCenter(center);
382   euler->SetMatrix(rotMat);
383   euler->SetOffset(transVec);
384
385   // Modify GUI according to the new parameters
386   std::vector<QSlider *> transSliders, rotSliders;
387   std::vector<QDoubleSpinBox *> transSBs, rotSBs;
388   GetSlidersAndSpinBoxes(transSliders, rotSliders, transSBs, rotSBs);
389   for(int i=0; i<3; i++) {
390     // Translations
391     transSBs[i]->blockSignals(true);
392     transSBs[i]->setValue( euler->GetParameters()[i+3] );
393     transSBs[i]->blockSignals(false);
394     transSliders[i]->blockSignals(true);
395     transSliders[i]->setValue( itk::Math::Round<double,double>(euler->GetParameters()[i+3]) );
396     transSliders[i]->blockSignals(false);
397
398     // Rotations
399     double rad = (checkBoxDegrees->checkState()==Qt::Checked)?180./itk::Math::pi:1.;
400     double angleDiff = euler->GetParameters()[i]-rotSBs[i]->value()/rad+2*itk::Math::pi;
401     angleDiff = angleDiff - 2*itk::Math::pi*itk::Math::Round<double,double>(angleDiff/(2*itk::Math::pi));
402     if(angleDiff>1.e-4) {
403       rotSBs[i]->blockSignals(true);
404       rotSBs[i]->setValue( euler->GetParameters()[i]*rad );
405       rotSBs[i]->blockSignals(false);
406     }
407     int iAngle = itk::Math::Round<int,double>(euler->GetParameters()[i]*180./itk::Math::pi);
408     if((iAngle-rotSliders[i]->value()+360)%360!=0) {
409       rotSliders[i]->blockSignals(true);
410       rotSliders[i]->setValue(iAngle);
411       rotSliders[i]->blockSignals(false);
412     }
413   }cout << euler->GetParameters()[0+3] << " " << euler->GetParameters()[1+3] << " " << euler->GetParameters()[2+3] << endl;
414 }
415 //------------------------------------------------------------------------------
416
417 //------------------------------------------------------------------------------
418 // Just an helper function to shorten the code with loops on sliders and spinboxes
419 void vvToolRigidReg::GetSlidersAndSpinBoxes(std::vector<QSlider *>&transSliders, std::vector<QSlider *>&rotSliders,
420                                             std::vector<QDoubleSpinBox *>&transSBs, std::vector<QDoubleSpinBox *>&rotSBs)
421 {
422   transSliders.push_back(xtrans_slider);
423   transSliders.push_back(ytrans_slider);
424   transSliders.push_back(ztrans_slider);
425
426   rotSliders.push_back(xrot_slider);
427   rotSliders.push_back(yrot_slider);
428   rotSliders.push_back(zrot_slider);
429
430   transSBs.push_back(xtrans_sb);
431   transSBs.push_back(ytrans_sb);
432   transSBs.push_back(ztrans_sb);
433
434   rotSBs.push_back(xrot_sb);
435   rotSBs.push_back(yrot_sb);
436   rotSBs.push_back(zrot_sb);
437 }
438 //------------------------------------------------------------------------------
439
440 //------------------------------------------------------------------------------
441 void vvToolRigidReg::ExtentMax(const double pointExtent[8][4], double maxExtent[2][3])
442 {
443     double max, min;
444     for (int i=0; i<3; ++i) {
445         max = pointExtent[0][i];
446         min = pointExtent[0][i];
447         for (int j=1; j<8; ++j) {
448             if (pointExtent[j][i] > max) {
449                 max = pointExtent[j][i];
450             }
451             if (pointExtent[j][i] < min) {
452                 min = pointExtent[j][i];
453             }
454         }
455         maxExtent[0][i] = min;
456         maxExtent[1][i] = max;
457     }
458 }
459 //------------------------------------------------------------------------------
460
461 //------------------------------------------------------------------------------
462 void vvToolRigidReg::Render()
463 { //out << __func__ << endl;
464 #if VTK_MAJOR_VERSION > 7
465 double translationValues[4], translationValuesUpdate[4];
466 mCurrentSlicerManager->GetImage()->GetTransform()[0]->Print(cout);
467 vtkMatrix4x4* matrix = mCurrentSlicerManager->GetImage()->GetTransform()[0]->GetMatrix();
468 vtkMatrix4x4* matrixTranspose = matrix->NewInstance();
469 for (int i=0; i<3; ++i) {
470     for (int j=0; j<3; ++j)
471     {
472         matrixTranspose->SetElement(i,j,matrix->GetElement(j,i));
473     }
474 }
475 for (int j=0; j<3; ++j)
476 {
477     translationValues[j] = matrix->GetElement(j,3);
478 }
479 translationValues[3] = 0.0;
480 matrix->MultiplyPoint(translationValues, translationValuesUpdate);
481 for (int i=0; i<3; ++i) {
482    matrixTranspose->SetElement(i,3,translationValuesUpdate[i]);
483 }
484 for (int i=0; i<4; ++i) {
485    matrixTranspose->SetElement(3,i,matrix->GetElement(3,i));
486 }
487
488 #endif
489 for (int i=0; i<mCurrentSlicerManager->GetNumberOfSlicers(); i++) {
490 #if VTK_MAJOR_VERSION > 7
491     double pointExtent[8][4], pointExtentUpdate[8][4], pointOverlayExtent[8][4], pointOverlayExtentUpdate[8][4], centre[3], translation[3];
492     std::vector<int> w_ext;
493     w_ext=mCurrentSlicerManager->GetImage()->GetSize();
494     pointExtent[0][0] = 0.0;
495         pointExtent[0][1] = 0.0;
496         pointExtent[0][2] = 0.0;
497         pointExtent[0][3] = 1.0;
498     pointExtent[1][0] = w_ext[0]-1;
499         pointExtent[1][1] = w_ext[1]-1;
500         pointExtent[1][2] = w_ext[2]-1;
501         pointExtent[1][3] = 1.0;
502         pointExtent[2][0] = 0.0;
503         pointExtent[2][1] = w_ext[1]-1;
504         pointExtent[2][2] = w_ext[2]-1;
505         pointExtent[2][3] = 1.0;
506         pointExtent[3][0] = w_ext[0]-1;
507         pointExtent[3][1] = 0.0;
508         pointExtent[3][2] = w_ext[2]-1;
509         pointExtent[3][3] = 1.0;
510         pointExtent[4][0] = w_ext[0]-1;
511         pointExtent[4][1] = w_ext[1]-1;
512         pointExtent[4][2] = 0.0;
513         pointExtent[4][3] = 1.0;
514         pointExtent[5][0] = 0.0;
515         pointExtent[5][1] = 0.0;
516         pointExtent[5][2] = w_ext[2]-1;
517         pointExtent[5][3] = 1.0;
518         pointExtent[6][0] = 0.0;
519         pointExtent[6][1] = w_ext[1]-1;
520         pointExtent[6][2] = 0.0;
521         pointExtent[6][3] = 1.0;
522         pointExtent[7][0] = w_ext[0]-1;
523         pointExtent[7][1] = 0.0;
524         pointExtent[7][2] = 0.0;
525         pointExtent[7][3] = 1.0;
526         
527         centre[0] = Xval->text().toDouble();
528         centre[1] = Yval->text().toDouble();
529         centre[2] = Zval->text().toDouble();
530         
531         for (int k=0; k<8; ++k) {
532             for (int j=0; j<3; ++j)
533             {
534                 pointOverlayExtent[k][j] = mCurrentSlicerManager->GetImage()->GetSpacing()[j]*pointExtent[k][j] - centre[j];
535             }
536             pointOverlayExtent[k][3] = 0.0;
537             matrixTranspose->MultiplyPoint(pointOverlayExtent[k], pointOverlayExtentUpdate[k]);
538             for (int j=0; j<3; ++j)
539             {
540                 pointOverlayExtentUpdate[k][j] = (pointOverlayExtentUpdate[k][j] + centre[j])/mCurrentSlicerManager->GetImage()->GetSpacing()[j];
541                 cout << pointOverlayExtentUpdate[k][j] << " ";
542             }
543             cout << endl;
544     }
545         cout << endl;
546         for (int k=0; k<8; ++k) {
547             for (int j=0; j<3; ++j)
548             {
549                 pointExtent[k][j] = mCurrentSlicerManager->GetImage()->GetSpacing()[j] * pointExtent[k][j];
550             }
551             matrixTranspose->MultiplyPoint(pointExtent[k], pointExtentUpdate[k]);
552                 for (int j=0; j<3; ++j)
553             {
554                 pointExtentUpdate[k][j] = (pointExtentUpdate[k][j])/mCurrentSlicerManager->GetImage()->GetSpacing()[j];
555                 cout << pointExtentUpdate[k][j] << " ";
556             }
557             cout << endl;
558     }
559     double extUpdateTemp[2][3], extOverlayUpdateTemp[2][3];
560     int extUpdate[6];
561     ExtentMax(pointExtentUpdate, extUpdateTemp);
562     ExtentMax(pointOverlayExtentUpdate, extOverlayUpdateTemp);
563     for (int j=0; j<3; ++j) {
564         extUpdate[2*j] = 0;
565         extUpdate[2*j+1] = itk::Math::Round<double>(extUpdateTemp[1][j] - extUpdateTemp[0][j]);
566     }
567     mCurrentSlicerManager->GetSlicer(i)->SetRegisterExtent(extUpdate);
568     extUpdate[2*mCurrentSlicerManager->GetSlicer(i)->GetOrientation()] = mCurrentSlicerManager->GetSlicer(i)->GetSlice();
569     extUpdate[2*mCurrentSlicerManager->GetSlicer(i)->GetOrientation()+1] = mCurrentSlicerManager->GetSlicer(i)->GetSlice();
570     
571     vtkSmartPointer<vtkOpenGLImageSliceMapper> mapperOpenGL= vtkSmartPointer<vtkOpenGLImageSliceMapper>::New();
572     try {
573         mapperOpenGL = dynamic_cast<vtkOpenGLImageSliceMapper*>(mCurrentSlicerManager->GetSlicer(i)->GetImageActor()->GetMapper());
574     } catch (const std::bad_cast& e) {
575                 std::cerr << e.what() << std::endl;
576                 std::cerr << "Conversion error" << std::endl;
577                 return;
578         }
579         cout << extUpdate[0] << " " << extUpdate[1] << " " << extUpdate[2] << " " << extUpdate[3] << " " << extUpdate[4] << " " << extUpdate[5] << endl;
580         mapperOpenGL->SetCroppingRegion(extUpdate);
581         
582         if (mCurrentSlicerManager->GetSlicer(i)->GetOverlay() && mCurrentSlicerManager->GetSlicer(i)->GetOverlayActor()->GetVisibility()) {
583             int extOverlayUpdate[6];
584             for (int j=0; j<3; ++j) { //Rotation
585                 if (extOverlayUpdateTemp[1][j] - extOverlayUpdateTemp[0][j] > w_ext[j]-1) {
586                     extOverlayUpdate[2*j] = 0;
587                     extOverlayUpdate[2*j+1] = w_ext[j]-1;
588                 } else {
589                     extOverlayUpdate[2*j] = itk::Math::Round<double>(extOverlayUpdateTemp[0][j]);
590                     extOverlayUpdate[2*j+1] = itk::Math::Round<double>(extOverlayUpdateTemp[1][j]);
591                 }
592             }
593             
594             //Compute translation
595             double pointOrigin[4], pointOriginUpdate[4];
596             for (int j=0; j<3; ++j)
597             {
598                 pointOrigin[j] = 0 - centre[j];
599             }
600             pointOrigin[3] = 0.0;
601             matrix->MultiplyPoint(pointOrigin, pointOriginUpdate);
602             for (int j=0; j<3; ++j)
603             {
604                 pointOriginUpdate[j] = (pointOriginUpdate[j] + centre[j])/mCurrentSlicerManager->GetImage()->GetSpacing()[j];
605                 translation[j] = matrix->GetElement(j,3) - pointOriginUpdate[j]*mCurrentSlicerManager->GetImage()->GetSpacing()[j];
606                 pointOrigin[j] = translation[j];
607             }
608             pointOrigin[3] = 0.0;
609             matrixTranspose->MultiplyPoint(pointOrigin, pointOriginUpdate);
610             for (int j=0; j<3; ++j)
611             {
612                 translation[j] = pointOriginUpdate[j]/mCurrentSlicerManager->GetImage()->GetSpacing()[j];
613             }
614             
615             for (int j=0; j<3; ++j) { //Translation
616                 if (0 < extOverlayUpdateTemp[0][j] - translation[j]) {
617                     extOverlayUpdate[2*j] = itk::Math::Round<double>(extOverlayUpdateTemp[0][j] - translation[j]);
618                 } else {
619                     extOverlayUpdate[2*j] = 0;
620                 }
621                 if (extOverlayUpdateTemp[1][j] - translation[j] < w_ext[j]-1) {
622                     extOverlayUpdate[2*j+1] = itk::Math::Round<double>(extOverlayUpdateTemp[1][j] - translation[j]);
623                 } else {
624                     extOverlayUpdate[2*j+1] = w_ext[j]-1;
625                 }
626             }
627             extOverlayUpdate[2*mCurrentSlicerManager->GetSlicer(i)->GetOrientation()] += mCurrentSlicerManager->GetSlicer(i)->GetSlice();
628         extOverlayUpdate[2*mCurrentSlicerManager->GetSlicer(i)->GetOrientation()+1] = extOverlayUpdate[2*mCurrentSlicerManager->GetSlicer(i)->GetOrientation()];
629             vtkSmartPointer<vtkOpenGLImageSliceMapper> mapperOpenGL= vtkSmartPointer<vtkOpenGLImageSliceMapper>::New();
630             try {
631             mapperOpenGL = dynamic_cast<vtkOpenGLImageSliceMapper*>(mCurrentSlicerManager->GetSlicer(i)->GetOverlayActor()->GetMapper());
632         } catch (const std::bad_cast& e) {
633                     std::cerr << e.what() << std::endl;
634                     std::cerr << "Conversion error" << std::endl;
635                     return;
636             }
637             
638             //Slice number
639             double spacing[4],spacingUpdate[4];
640             int sliceNumber;
641             spacing[0] = 240*mCurrentSlicerManager->GetImage()->GetSpacing()[0]-centre[0];
642             spacing[1] = 179*mCurrentSlicerManager->GetImage()->GetSpacing()[1]-centre[1];
643             spacing[2] = 22*mCurrentSlicerManager->GetImage()->GetSpacing()[2]-centre[2];
644             spacing[3] = 0;
645             matrixTranspose->MultiplyPoint(spacing, spacingUpdate);
646             spacingUpdate[0] = (spacingUpdate[0]+centre[0])/mCurrentSlicerManager->GetImage()->GetSpacing()[0];
647             spacingUpdate[1] = (spacingUpdate[1]+centre[1])/mCurrentSlicerManager->GetImage()->GetSpacing()[1];
648             spacingUpdate[2] = (spacingUpdate[2]+centre[2])/mCurrentSlicerManager->GetImage()->GetSpacing()[2];
649             cout << spacingUpdate[0] << " " << spacingUpdate[1] << " " << spacingUpdate[2] << endl;
650             sliceNumber = mCurrentSlicerManager->GetSlicer(i)->GetSlice()*spacingUpdate[mCurrentSlicerManager->GetSlicer(i)->GetOrientation()]/mCurrentSlicerManager->GetImage()->GetSpacing()[mCurrentSlicerManager->GetSlicer(i)->GetOrientation()];
651             extOverlayUpdate[2*mCurrentSlicerManager->GetSlicer(i)->GetOrientation()] = 12;//sliceNumber;
652             extOverlayUpdate[2*mCurrentSlicerManager->GetSlicer(i)->GetOrientation()+1] = 12;//sliceNumber;
653             
654             mapperOpenGL->SetCroppingRegion(extOverlayUpdate);
655         }
656 #endif
657     mCurrentSlicerManager->GetSlicer(i)->ForceUpdateDisplayExtent();
658     mCurrentSlicerManager->GetSlicer(i)->Render();
659 }
660 }
661 //------------------------------------------------------------------------------
662