]> Creatis software - openheart.git/blob - Applications/OpenHeartGui.cxx
commit all the files for the first time
[openheart.git] / Applications / OpenHeartGui.cxx
1 /**
2 * Progam made by Olivier Bernard, associate professor
3 * at Institut National des Sciences Appliquees (INSA) Lyon,
4 * CREATIS Laboratory,
5 * 69621 Villeurbanne, France,
6 * 07th of May 2014
7 */
8
9 #include "OpenHeartGui.h"
10
11 #include <vtkObjectFactory.h>
12 #include <vtkRenderWindow.h>
13 #include <vtkRenderer.h>
14 #include <vtkImageData.h>
15 #include <vtkTextProperty.h>
16 #include <vtkProperty.h>
17 #include <vtkRendererCollection.h>
18 #include <vtkRenderer.h>
19 #include <vtkInteractorStyleTrackballCamera.h>
20 #include <vtkCamera.h>
21 #include <vtkImageGaussianSmooth.h>
22 #include <vtkMarchingCubes.h>
23 #include <vtkDataSetMapper.h>
24 #include <vtkPolyDataMapper.h>
25 #include <vtkCutter.h>
26 #include <vtkSphereSource.h>
27 #include <vtkInteractorStyleSwitch.h>
28 #include <vtkTextMapper.h>
29 #include <vtkMath.h>
30 #include <vtkMetaImageWriter.h>
31 #include <vtkDepthSortPolyData.h>
32 #include <vtkTimerLog.h>
33 #include <vtkTransform.h>
34 #include <vtkTransformPolyDataFilter.h>
35 #include <vtkContextView.h>
36 #include <vtkTable.h>
37 #include <vtkFloatArray.h>
38 #include <vtkChartXY.h>
39 #include <vtkPlot.h>
40 #include <vtkContextScene.h>
41 #include <vtkAxis.h>
42 #include <vtkCamera.h>
43 #include <vtkAxesActor.h>
44 #include <vtkOrientationMarkerWidget.h>
45 #include <vtkCaptionActor2D.h>
46 #include <vtkMetaImageReader.h>
47 #include <vtkImageCast.h>
48 #include <vtkUnstructuredGridReader.h>
49 #include <vtkUnstructuredGrid.h>
50 #include <vtkGenericDataObjectReader.h>
51 #include <vtkCellArray.h>
52 #include <vtkXMLPolyDataReader.h>
53 #include <vtkPolyDataReader.h>
54 #include <vtkUnstructuredGridGeometryFilter.h>
55 #include <vtkDepthSortPolyData.h>
56 #include <vtkLineSource.h>
57 #include <vtkSmartPointer.h>
58 #include <vtkIntersectionPolyDataFilter.h>
59 #include <vtkTriangleFilter.h>
60 #include <vtkImageData.h>
61 #include <vtkImageReslice.h>
62 #include <vtkImageMapper.h>
63 #include <vtkSphereSource.h>
64 #include <vtkLine.h>
65 #include <vtkOutlineFilter.h>
66 #include "vtkMyInteractorStyleTrackballCameraOpenHeart.h"
67 #include "vtkMyInteractorStyleTrackballCameraOpenHeartXY.h"
68 #include "vtkMyInteractorStyleTrackballCameraOpenHeartXZ.h"
69 #include "vtkMyInteractorStyleTrackballCameraOpenHeartYZ.h"
70 #include <QResizeEvent>
71 #include <QPalette>
72
73
74 #define CONFIG_FILE "../../Config/ConfigOpenHeart.txt"
75
76
77 // ****************************************************************
78 // ****************************************************************
79 // ****************************************************************
80 class vtkMyChartXY : public vtkChartXY
81 {
82
83     bool MouseButtonPressEvent(const vtkContextMouseEvent &mouse) { return true; }
84     bool MouseWheelEvent(const vtkContextMouseEvent &mouse, int delta) { return true; }
85     bool MouseMoveEvent(const vtkContextMouseEvent &mouse) { return true; }
86     bool MouseButtonReleaseEvent(const vtkContextMouseEvent &mouse) { return true; }
87
88 };
89
90
91 // ****************************************************************
92 // ****************************************************************
93 // ****************************************************************
94 OpenHeartGui::OpenHeartGui()
95 {
96
97     /// Initialize window
98     this->setupUi(this);
99     this->InstantiateQtVtkRenderers();
100
101     /// Set colors of the interface
102     this->SetInterfaceColors();
103
104     /// Allocate attributes
105     for ( int k=0; k<3; k++ )
106         this->Dims[k] = 0;
107     this->PreviousFrame = 0;
108     this->CurrentFrame = 0;
109     this->NumberOfVolumes = 0;
110     this->ImageData = 0;
111     this->TableChart = 0;
112     this->Properties = new RendererProperties;
113     this->ViewButton = 0;
114     this->MeshRepresentation = 0;
115     this->MeshColor = 0;
116     this->ZoomLabel = 1.6;
117     this->ZoomMain = 1.5;
118     this->RotationMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
119     this->RotationMatrix->Identity();
120     this->TransformViewOrientation = vtkSmartPointer<vtkTransform>::New();
121     this->RotationMatrixInv = vtkSmartPointer<vtkMatrix4x4>::New();
122     this->RotationMatrixInv->Identity();
123     this->TransformViewOrientationInv = vtkSmartPointer<vtkTransform>::New();
124     this->OrientationWidget = vtkSmartPointer<vtkOrientationMarkerWidget>::New();
125
126     /// Flag management
127     this->FlagInterpolation = 0;
128     this->FlagDisplayMesh = 0;
129     this->FlagDisplayMeshContours = 0;
130     this->FlagDisplayMeshContourX = 0;
131     this->FlagDisplayMeshContourY = 0;
132     this->FlagDisplayMeshContourZ = 0;
133     this->FlagLoopEndToBegin = 0;
134     this->FlagLoopBeginToEnd = 0;
135     this->FlagPlay = 0;
136     this->FlagDisplayText = 1;
137     this->FlagHidePlan = 0;
138     this->FlagLongAxis = 0;
139     this->FlagDisplayApexPoint = 0;
140     this->FlagDisplayBasalPoint = 0;
141     this->FlagDisplayMeshContours = 1;
142     this->FlagDisplayLongAxis = 0;
143     this->FlagReslice = 0;
144
145     /// Widget management
146     this->InitPickers();
147     this->InitProperties();
148     this->InitWidgets();
149     this->SetCustomInteractorStyle();
150
151     /// Read 3D volume and create corresponding OpenHeart
152     std::ifstream file(CONFIG_FILE, std::ifstream::in);
153     std::string inputFilename;
154     file >> inputFilename;
155     file >> this->NumberOfVolumes;
156
157     /// Load sequence of volumes
158     this->CreateFromSequenceDataPointer(inputFilename);
159
160     /// Manage main window display
161     /// Force to view XZ orientation at initialization
162     this->ForceXZView();
163
164     /// Initialize text displayed in the main window
165     this->InitTexts();
166
167     /// Initialize the orientation axes after rendering the volume
168     this->InitOrientationAxes();
169
170     /// Manage XY window display
171     this->qVTKXY->GetRenderWindow()->Render();
172
173     /// Manage XZ window display
174     this->qVTKXZ->GetRenderWindow()->Render();
175
176     /// Manage YZ window display
177     this->qVTKYZ->GetRenderWindow()->Render();
178
179     /// Manage scrollbar
180     this->scrollBar->setMaximum(this->NumberOfVolumes-1);
181     this->SliderMeshAlpha->setMaximum(100);
182     this->SliderMeshAlpha->setSingleStep(1);
183     this->SliderMeshAlpha->setValue(20);
184
185     /// Initialized the chart part of the interface
186     this->ViewChart = vtkSmartPointer<vtkContextView>::New();
187     this->ViewChart->SetInteractor(this->qVTKChart->GetInteractor());
188     this->qVTKChart->SetRenderWindow(this->ViewChart->GetRenderWindow());
189     this->qVTKChart->GetRenderWindow()->SetSize(478,478);
190     this->ViewChart->GetRenderer()->SetBackground(255./255.,255./255.,255./255.);
191     this->InitChar();
192
193     /// Instantiate timer for the player
194     Timer = new QTimer(this);
195
196     /// Instantiate Qt events
197     connect(this->scrollBar, SIGNAL(valueChanged(int)), this, SLOT(slotRefreshViewer(int)));
198     connect(this->SliderMeshAlpha, SIGNAL(valueChanged(int)), this, SLOT(slotMeshAlpha(int)));
199     connect(this->pushButtonPlay, SIGNAL(clicked()), this, SLOT(slotPlay()));
200     connect(this->pushButtonXY, SIGNAL(clicked()), this, SLOT(slotXYView()));
201     connect(this->pushButtonXZ, SIGNAL(clicked()), this, SLOT(slotXZView()));
202     connect(this->pushButtonYZ, SIGNAL(clicked()), this, SLOT(slotYZView()));
203     connect(this->pushButton3D, SIGNAL(clicked()), this, SLOT(slot3DView()));
204     connect(this->pushButtonMesh, SIGNAL(clicked()), this, SLOT(slotMeshView()));
205     connect(this->pushButtonMeshRepresentation, SIGNAL(clicked()), this, SLOT(slotMeshRepresentation()));
206     connect(this->pushButtonMeshColor, SIGNAL(clicked()), this, SLOT(slotMeshColor()));
207     connect(this->pushButtonCutter, SIGNAL(clicked()), this, SLOT(slotMeshCutter()));
208     connect(this->Timer, SIGNAL(timeout()), this, SLOT(slotTimerEvent()));
209     connect(this->tabWidgetOption, SIGNAL(currentChanged(int)), this, SLOT(slotTabChange(int)));
210     connect(this->pushButtonBasalPoint, SIGNAL(clicked()), this, SLOT(slotBasalPoint()));
211     connect(this->pushButtonApexPoint, SIGNAL(clicked()), this, SLOT(slotApexPoint()));
212     connect(this->pushButtonReslice, SIGNAL(clicked()), this, SLOT(slotReslice()));
213
214     /// Update coords as we move through the window
215     Connections = vtkEventQtSlotConnect::New();
216     Connections->Connect(this->qVTK->GetRenderWindow()->GetInteractor(),
217                         vtkCommand::MouseMoveEvent,
218                         this,
219                         SLOT(slotUpdateCoords(vtkObject*)));
220
221 }
222
223
224 OpenHeartGui::~OpenHeartGui()
225 {
226
227   Connections->Delete();
228
229 }
230
231
232 void OpenHeartGui::InstantiateQtVtkRenderers()
233 {
234
235     /// ****************************************************************
236     /// Create the main window
237     vtkSmartPointer<vtkRenderWindow> renwin = vtkSmartPointer<vtkRenderWindow>::New();
238     renwin->StereoCapableWindowOn();
239
240     /// Activate 3DConnexion device
241     this->qVTK->SetUseTDx(true);
242     this->qVTK->SetRenderWindow(renwin);
243
244     /// Initialize interactor
245     this->Interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
246     this->Interactor = static_cast<vtkRenderWindowInteractor *>(this->qVTK->GetInteractor()->GetRenderWindow()->GetInteractor());
247
248     /// Add a renderer
249     this->Ren = vtkSmartPointer<vtkRenderer>::New();
250     this->qVTK->GetRenderWindow()->AddRenderer(this->Ren);
251     this->Ren->SetBackground(0,0,0);
252     this->Ren->GetActiveCamera()->SetParallelProjection(1);
253
254
255     /// ****************************************************************
256     /// Create XY window
257     vtkSmartPointer<vtkRenderWindow> renwinXY = vtkSmartPointer<vtkRenderWindow>::New();
258     renwinXY->StereoCapableWindowOn();
259
260     /// Activate 3DConnexion device
261     this->qVTKXY->SetUseTDx(true);
262     this->qVTKXY->SetRenderWindow(renwinXY);
263
264     /// Initialize interactor
265     this->InteractorXY = vtkSmartPointer<vtkRenderWindowInteractor>::New();
266     this->InteractorXY = static_cast<vtkRenderWindowInteractor *>(this->qVTKXY->GetInteractor()->GetRenderWindow()->GetInteractor());
267
268     /// Add a renderer
269     this->RenXY = vtkSmartPointer<vtkRenderer>::New();
270     this->qVTKXY->GetRenderWindow()->AddRenderer(this->RenXY);
271     this->RenXY->SetBackground(0,0,0);
272     this->RenXY->GetActiveCamera()->SetParallelProjection(1);
273
274
275     /// ****************************************************************
276     /// Create XZ window
277     vtkSmartPointer<vtkRenderWindow> renwinXZ = vtkSmartPointer<vtkRenderWindow>::New();
278     renwinXZ->StereoCapableWindowOn();
279
280     /// Activate 3DConnexion device
281     this->qVTKXZ->SetUseTDx(true);
282     this->qVTKXZ->SetRenderWindow(renwinXZ);
283
284     /// Initialize interactor
285     this->InteractorXZ = vtkSmartPointer<vtkRenderWindowInteractor>::New();
286     this->InteractorXZ = static_cast<vtkRenderWindowInteractor *>(this->qVTKXZ->GetInteractor()->GetRenderWindow()->GetInteractor());
287
288     /// Add a renderer
289     this->RenXZ = vtkSmartPointer<vtkRenderer>::New();
290     this->qVTKXZ->GetRenderWindow()->AddRenderer(this->RenXZ);
291     this->RenXZ->SetBackground(0,0,0);
292     this->RenXZ->GetActiveCamera()->SetParallelProjection(1);
293
294
295     /// ****************************************************************
296     /// Create YZ window
297     vtkSmartPointer<vtkRenderWindow> renwinYZ = vtkSmartPointer<vtkRenderWindow>::New();
298     renwinYZ->StereoCapableWindowOn();
299
300     /// Activate 3DConnexion device
301     this->qVTKYZ->SetUseTDx(true);
302     this->qVTKYZ->SetRenderWindow(renwinYZ);
303
304     /// Initialize interactor
305     this->InteractorYZ = static_cast<vtkRenderWindowInteractor *>(this->qVTKYZ->GetInteractor()->GetRenderWindow()->GetInteractor());
306
307     /// Add a renderer
308     this->RenYZ = vtkSmartPointer<vtkRenderer>::New();
309     this->qVTKYZ->GetRenderWindow()->AddRenderer(this->RenYZ);
310     this->RenYZ->SetBackground(0,0,0);
311     this->RenYZ->GetActiveCamera()->SetParallelProjection(1);
312
313 }
314
315
316 void OpenHeartGui::slotMeshView()
317 {
318     this->HidePlanModeManagement();
319 }
320
321
322 void OpenHeartGui::slotYZView()
323 {
324
325     this->ViewButton = 1;
326     this->Properties->xIPW->SetTextureVisibility(1);
327     this->Properties->xIPW->GetPlaneProperty()->SetOpacity(1);
328     this->Properties->xIPW->GetPlaneProperty()->SetColor(0,0,0);
329     this->Properties->yIPW->SetTextureVisibility(0);
330     this->Properties->yIPW->GetPlaneProperty()->SetOpacity(0);
331     this->Properties->yIPW->GetPlaneProperty()->SetColor(0,0,0);
332     this->Properties->zIPW->SetTextureVisibility(0);
333     this->Properties->zIPW->GetPlaneProperty()->SetOpacity(0);
334     this->Properties->zIPW->GetPlaneProperty()->SetColor(0,0,0);
335
336     if ( this->FlagHidePlan == 0 )
337     {
338
339         /// Update corresponding viewer
340         int view = 2;
341         this->UpdateViewer(view,this->ZoomMain,this->Ren);
342
343         /// Also update Slice text
344         int slice = (int)( (this->Properties->position[0] - this->ImageData->GetOrigin()[0]) / this->ImageData->GetSpacing()[0] + 0.5f );
345         QString strSlice;
346         strSlice.sprintf("Slice: %d",slice);
347         this->Properties->TextMapperSlice->SetInput(strSlice.toStdString().c_str());
348
349     }
350     else {
351         this->FlagHidePlan = 0;
352     }
353
354     if ( this->FlagDisplayMeshContours == 1 )
355     {
356         this->GetMeshRenderer()->AddActor(this->Properties->xCutActor);
357         this->GetMeshRenderer()->RemoveActor(this->Properties->yCutActor);
358         this->GetMeshRenderer()->RemoveActor(this->Properties->zCutActor);
359         this->GetRenderWindow()->Render();
360     }
361
362 }
363
364
365 void OpenHeartGui::slotXZView()
366 {
367
368     this->ViewButton = 2;
369     this->Properties->xIPW->SetTextureVisibility(0);
370     this->Properties->xIPW->GetPlaneProperty()->SetOpacity(0);
371     this->Properties->xIPW->GetPlaneProperty()->SetColor(0,0,0);
372     this->Properties->yIPW->SetTextureVisibility(1);
373     this->Properties->yIPW->GetPlaneProperty()->SetOpacity(1);
374     this->Properties->yIPW->GetPlaneProperty()->SetColor(0,0,0);
375     this->Properties->zIPW->SetTextureVisibility(0);
376     this->Properties->zIPW->GetPlaneProperty()->SetOpacity(0);
377     this->Properties->zIPW->GetPlaneProperty()->SetColor(0,0,0);
378
379     if ( this->FlagHidePlan == 0 )
380     {
381
382         /// Update corresponding viewer
383         int view = 1;
384         this->UpdateViewer(view,this->ZoomMain,this->Ren);
385
386         /// Also update Slice text
387         int slice = (int)( (this->Properties->position[1] - this->ImageData->GetOrigin()[1]) / this->ImageData->GetSpacing()[1] + 0.5f );
388         QString strSlice;
389         strSlice.sprintf("Slice: %d",slice);
390         this->Properties->TextMapperSlice->SetInput(strSlice.toStdString().c_str());
391
392     }
393     else {
394         this->FlagHidePlan = 0;
395     }
396
397     if ( this->FlagDisplayMeshContours == 1 )
398     {
399         this->GetMeshRenderer()->RemoveActor(this->Properties->xCutActor);
400         this->GetMeshRenderer()->AddActor(this->Properties->yCutActor);
401         this->GetMeshRenderer()->RemoveActor(this->Properties->zCutActor);
402         this->GetRenderWindow()->Render();
403     }
404
405 }
406
407
408 void OpenHeartGui::slotXYView()
409 {
410
411     this->ViewButton = 3;
412     this->Properties->xIPW->SetTextureVisibility(0);
413     this->Properties->xIPW->GetPlaneProperty()->SetOpacity(0);
414     this->Properties->xIPW->GetPlaneProperty()->SetColor(0,0,0);
415     this->Properties->yIPW->SetTextureVisibility(0);
416     this->Properties->yIPW->GetPlaneProperty()->SetOpacity(0);
417     this->Properties->yIPW->GetPlaneProperty()->SetColor(0,0,0);
418     this->Properties->zIPW->SetTextureVisibility(1);
419     this->Properties->zIPW->GetPlaneProperty()->SetOpacity(1);
420     this->Properties->zIPW->GetPlaneProperty()->SetColor(0,0,0);
421
422     if ( this->FlagHidePlan == 0 )
423     {
424
425         /// Update corresponding viewer
426         int view = 0;
427         this->UpdateViewer(view,this->ZoomMain,this->Ren);
428
429         /// Also update Slice text
430         int slice = (int)( (this->Properties->position[2] - this->ImageData->GetOrigin()[2]) / this->ImageData->GetSpacing()[2] + 0.5f );
431         QString strSlice;
432         strSlice.sprintf("Slice: %d",slice);
433         this->Properties->TextMapperSlice->SetInput(strSlice.toStdString().c_str());
434
435     }
436     else {
437         this->FlagHidePlan = 0;
438     }
439
440     if ( this->FlagDisplayMeshContours == 1 )
441     {
442         this->GetMeshRenderer()->RemoveActor(this->Properties->xCutActor);
443         this->GetMeshRenderer()->RemoveActor(this->Properties->yCutActor);
444         this->GetMeshRenderer()->AddActor(this->Properties->zCutActor);
445         this->GetRenderWindow()->Render();
446     }
447
448 }
449
450
451 void OpenHeartGui::slot3DView()
452 {
453
454     this->ViewButton = 0;
455     this->Properties->xIPW->SetTextureVisibility(1);
456     this->Properties->xIPW->GetPlaneProperty()->SetOpacity(1);
457     this->Properties->xIPW->GetPlaneProperty()->SetColor(1,0,0);
458     this->Properties->yIPW->SetTextureVisibility(1);
459     this->Properties->yIPW->GetPlaneProperty()->SetOpacity(1);
460     this->Properties->yIPW->GetPlaneProperty()->SetColor(1,1,0);
461     this->Properties->zIPW->SetTextureVisibility(1);
462     this->Properties->zIPW->GetPlaneProperty()->SetOpacity(1);
463     this->Properties->zIPW->GetTextProperty()->SetColor(1,0,0);
464     this->Properties->zIPW->GetPlaneProperty()->SetColor(0,0,1);
465
466     if ( this->FlagHidePlan == 0 )
467     {
468
469         this->Ren->ResetCamera();
470         this->Ren->GetActiveCamera()->Zoom(1.);
471
472         if ( this->Properties->MeshActor != 0 )
473         {
474             if ( this->FlagDisplayMesh == 0 ) {
475                 this->FlagDisplayMesh = 1;
476                 this->GetMeshRenderer()->AddActor(this->Properties->MeshActor);
477             }
478         }
479
480     }
481     else {
482         this->FlagHidePlan = 0;
483     }
484     this->GetRenderWindow()->Render();
485
486 }
487
488
489 void OpenHeartGui::slotMeshRepresentation()
490 {
491
492     if ( this->Properties->MeshActor )
493     {
494
495         if ( this->FlagDisplayMeshContours == 1 )
496         {
497             this->GetMeshRenderer()->RemoveActor(this->Properties->xCutActor);
498             this->GetMeshRenderer()->RemoveActor(this->Properties->yCutActor);
499             this->GetMeshRenderer()->RemoveActor(this->Properties->zCutActor);
500             this->FlagDisplayMeshContours = 0;
501             this->GetMeshRenderer()->AddActor(this->Properties->MeshActor);
502             this->FlagDisplayMesh = 1;
503         }
504         switch (this->MeshRepresentation) {
505         case 0:
506             this->MeshRepresentation = 1;
507             this->pushButtonMeshRepresentation->setText("Surface");
508             this->Properties->MeshActor->GetProperty()->SetRepresentationToPoints();
509             break;
510         case 1:
511             this->MeshRepresentation = 2;
512             this->pushButtonMeshRepresentation->setText("No mesh");
513             this->Properties->MeshActor->GetProperty()->SetRepresentationToSurface();
514             break;
515         case 2:
516             this->MeshRepresentation = 3;
517             this->pushButtonMeshRepresentation->setText("Wire");
518             this->GetMeshRenderer()->RemoveActor(this->Properties->MeshActor);
519             this->FlagDisplayMesh = 0;
520             break;
521         case 3:
522             this->MeshRepresentation = 0;
523             this->pushButtonMeshRepresentation->setText("Points");
524             this->Properties->MeshActor->GetProperty()->SetRepresentationToWireframe();
525             this->GetMeshRenderer()->AddActor(this->Properties->MeshActor);
526             this->FlagDisplayMesh = 1;
527             break;
528         default:
529             break;
530         }
531         this->GetRenderWindow()->Render();
532
533     }
534
535 }
536
537
538
539 void OpenHeartGui::slotMeshColor()
540 {
541
542     if ( this->Properties->MeshActor ) {
543         if ( this->MeshColor == 0 ) {
544             this->MeshColor = 1;
545             this->pushButtonMeshColor->setText("Color R");
546             this->Properties->MeshActor->GetProperty()->SetColor(1,1,0);
547             //this->Properties->xCutActor->GetProperty()->SetColor(1,1,0);
548             //this->Properties->yCutActor->GetProperty()->SetColor(1,1,0);
549             //this->Properties->zCutActor->GetProperty()->SetColor(1,1,0);
550         }
551         else if ( this->MeshColor == 1 ) {
552             this->MeshColor = 2;
553             this->pushButtonMeshColor->setText("Color G");
554             this->Properties->MeshActor->GetProperty()->SetColor(1,0,0);
555             //this->Properties->xCutActor->GetProperty()->SetColor(1,0,0);
556             //this->Properties->yCutActor->GetProperty()->SetColor(1,0,0);
557             //this->Properties->zCutActor->GetProperty()->SetColor(1,0,0);
558         }
559         else if ( this->MeshColor == 2 ) {
560             this->MeshColor = 3;
561             this->pushButtonMeshColor->setText("Color B");
562             this->Properties->MeshActor->GetProperty()->SetColor(0,1,0);
563             //this->Properties->xCutActor->GetProperty()->SetColor(0,1,0);
564             //this->Properties->yCutActor->GetProperty()->SetColor(0,1,0);
565             //this->Properties->zCutActor->GetProperty()->SetColor(0,1,0);
566         }
567         else if ( this->MeshColor == 3 ) {
568             this->MeshColor = 4;
569             this->pushButtonMeshColor->setText("Color W");
570             this->Properties->MeshActor->GetProperty()->SetColor(0,0,1);
571             //this->Properties->xCutActor->GetProperty()->SetColor(0,0,1);
572             //this->Properties->yCutActor->GetProperty()->SetColor(0,0,1);
573             //this->Properties->zCutActor->GetProperty()->SetColor(0,0,1);
574         }
575         else if ( this->MeshColor == 4 ) {
576             this->MeshColor = 0;
577             this->pushButtonMeshColor->setText("Color Y");
578             this->Properties->MeshActor->GetProperty()->SetColor(1,1,1);
579             //this->Properties->xCutActor->GetProperty()->SetColor(1,1,1);
580             //this->Properties->yCutActor->GetProperty()->SetColor(1,1,1);
581             //this->Properties->zCutActor->GetProperty()->SetColor(1,1,1);
582         }
583         this->GetRenderWindow()->Render();
584     }
585
586 }
587
588
589 void OpenHeartGui::slotMeshCutter()
590 {
591
592     if ( this->Properties->MeshActor )
593     {
594         if ( this->FlagDisplayMeshContours == 1 )
595         {
596             this->FlagDisplayMeshContours = 0;
597             this->pushButtonCutter->setText("Cut on");
598             this->GetMeshRenderer()->RemoveActor(this->Properties->xCutActor);
599             this->GetMeshRenderer()->RemoveActor(this->Properties->yCutActor);
600             this->GetMeshRenderer()->RemoveActor(this->Properties->zCutActor);
601             if ( this->FlagDisplayMesh == 0 ) {
602                 this->FlagDisplayMesh = 1;
603                 this->GetMeshRenderer()->AddActor(this->Properties->MeshActor);
604             }
605         }
606         else
607         {
608             if ( this->FlagDisplayMesh == 1 ) {
609                 this->FlagDisplayMesh = 0;
610                 this->GetMeshRenderer()->RemoveActor(this->Properties->MeshActor);
611             }
612             this->FlagDisplayMeshContours = 1;
613             this->pushButtonCutter->setText("Cut off");
614             switch (this->ViewButton) {
615             case 0:
616                 this->GetMeshRenderer()->AddActor(this->Properties->xCutActor);
617                 this->GetMeshRenderer()->AddActor(this->Properties->yCutActor);
618                 this->GetMeshRenderer()->AddActor(this->Properties->zCutActor);
619                 break;
620             case 1:
621                 this->GetMeshRenderer()->AddActor(this->Properties->xCutActor);
622                 break;
623             case 2:
624                 this->GetMeshRenderer()->AddActor(this->Properties->yCutActor);
625                 break;
626             case 3:
627                 this->GetMeshRenderer()->AddActor(this->Properties->zCutActor);
628                 break;
629             default:
630                 break;
631             }
632             /*
633             if (this->ViewButton == 0) {
634                 this->GetMeshRenderer()->AddActor(this->Properties->xCutActor);
635                 this->GetMeshRenderer()->AddActor(this->Properties->yCutActor);
636                 this->GetMeshRenderer()->AddActor(this->Properties->zCutActor);
637             }
638             else if (this->ViewButton == 1) {
639                 this->GetMeshRenderer()->AddActor(this->Properties->xCutActor);
640             }
641             else if (this->ViewButton == 2) {
642                 this->GetMeshRenderer()->AddActor(this->Properties->yCutActor);
643             }
644             else if (this->ViewButton == 3) {
645                 this->GetMeshRenderer()->AddActor(this->Properties->zCutActor);
646             }
647             */
648         }
649         this->GetRenderWindow()->Render();
650     }
651
652
653 }
654
655
656 void OpenHeartGui::ForceXZView()
657 {
658
659     this->ViewButton = 2;
660     this->Properties->xIPW->SetTextureVisibility(0);
661     this->Properties->xIPW->GetPlaneProperty()->SetOpacity(0);
662     this->Properties->yIPW->SetTextureVisibility(1);
663     this->Properties->yIPW->GetPlaneProperty()->SetOpacity(1);
664     this->Properties->zIPW->SetTextureVisibility(0);
665     this->Properties->zIPW->GetPlaneProperty()->SetOpacity(0);
666
667     this->Ren->GetActiveCamera()->SetFocalPoint( this->ImageData->GetDimensions()[0]/2,
668                                                  this->ImageData->GetDimensions()[0]/2,
669                                                  this->ImageData->GetDimensions()[2]/2 );
670     this->Ren->GetActiveCamera()->SetPosition(   this->ImageData->GetDimensions()[0]/2,
671                                                  this->ImageData->GetDimensions()[1]*10,
672                                                  this->ImageData->GetDimensions()[0]/2 );
673     this->Ren->GetActiveCamera()->SetViewUp(0,0,-1);
674     this->Ren->ResetCamera();
675     this->Ren->GetActiveCamera()->Zoom(this->ZoomMain);
676     this->GetRenderWindow()->Render();
677
678 }
679
680 void OpenHeartGui::slotUpdateCoords(vtkObject* obj)
681 {
682
683     if (this->FlagPlay == 0)
684     {
685
686         if ( (this->FlagDisplayText) && (this->Properties->TextMapperPixel) )
687         {
688
689             /// Get interactor
690             vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::SafeDownCast(obj);
691
692             // Get intensity value at the corresponding position
693             int X = iren->GetEventPosition()[0];
694             int Y = iren->GetEventPosition()[1];
695             this->Picker->Pick(X,Y,0.0,this->GetMeshRenderer());
696             double pos[3];
697             this->Picker->GetPickPosition( pos );
698             int pixel[3];
699             for ( int i=0; i<3; i++) {
700                 pixel[i] = (int)( (pos[i] - this->ImageData->GetOrigin()[i]) / this->ImageData->GetSpacing()[i] + 0.5f );
701             }
702
703             if ( (pixel[0]>=0) && (pixel[0]<this->Dims[0]) &&
704                  (pixel[1]>=0) && (pixel[1]<this->Dims[1]) &&
705                  (pixel[2]>=0) && (pixel[2]<this->Dims[2]) )
706             {
707
708                 /// Display Pixel coordinates
709                 QString strPixel;
710                 strPixel.sprintf("pixel: (%d %d %d)", pixel[0], pixel[1], pixel[2]);
711                 this->Properties->TextMapperPixel->SetInput(strPixel.toStdString().c_str());
712
713                 /// Display Pixel coordinates
714                 QString strMM;
715                 strMM.sprintf("mm:  (%.0f %.0f %.0f)", pos[0]*1000, pos[1]*1000, pos[2]*1000);
716                 this->Properties->TextMapperMM->SetInput(strMM.toStdString().c_str());
717
718                 QString strValue;
719                 switch (this->ImageData->GetScalarType())
720                 {
721                     case VTK_UNSIGNED_CHAR: {
722                         strValue.sprintf("data value: %u", static_cast<unsigned char*>(this->ImageData->GetScalarPointer(pixel))[0]);
723                         break;
724                     }
725                     case VTK_UNSIGNED_SHORT: {
726                         strValue.sprintf("data value: %u", static_cast<unsigned short*>(this->ImageData->GetScalarPointer(pixel))[0]);
727                         break;
728                     }
729                     case VTK_INT: {
730                         strValue.sprintf("data value: %d", static_cast<int*>(this->ImageData->GetScalarPointer(pixel))[0]);
731                         break;
732                     }
733                     case VTK_FLOAT: {
734                         strValue.sprintf("data value: %.1f", static_cast<float*>(this->ImageData->GetScalarPointer(pixel))[0]);
735                         break;
736                     }
737                     case VTK_DOUBLE: {
738                         strValue.sprintf("data value: %.1f", static_cast<double*>(this->ImageData->GetScalarPointer(pixel))[0]);
739                         break;
740                     }
741
742                 }
743                 this->Properties->TextMapperValue->SetInput(strValue.toStdString().c_str());
744
745             }
746
747             else {
748                 this->Properties->TextMapperPixel->SetInput("");
749                 this->Properties->TextMapperMM->SetInput("");
750                 this->Properties->TextMapperValue->SetInput("");
751             }
752
753         }
754
755         else
756         {
757             if ( this->Properties->TextMapperPixel )
758             {
759                 this->Properties->TextMapperPixel->SetInput("");
760                 this->Properties->TextMapperMM->SetInput("");
761                 this->Properties->TextMapperValue->SetInput("");
762             }
763         }
764
765         this->GetRenderWindow()->Render();
766
767     }
768
769 }
770
771
772 void OpenHeartGui::UpdateCoords(double *pos)
773 {
774
775     if (this->FlagPlay == 0)
776     {
777
778         if ( (this->FlagDisplayText) && (this->Properties->TextMapperPixel) )
779         {
780
781             int pixel[3];
782             for ( int i=0; i<3; i++) {
783                 pixel[i] = (int)( (pos[i] - this->ImageData->GetOrigin()[i]) / this->ImageData->GetSpacing()[i] + 0.5f );
784             }
785
786             if ( (pixel[0]>=0) && (pixel[0]<this->Dims[0]) &&
787                  (pixel[1]>=0) && (pixel[1]<this->Dims[1]) &&
788                  (pixel[2]>=0) && (pixel[2]<this->Dims[2]) )
789             {
790
791                 /// Display Pixel coordinates
792                 QString strPixel;
793                 strPixel.sprintf("pixel: (%d %d %d)", pixel[0], pixel[1], pixel[2]);
794                 this->Properties->TextMapperPixel->SetInput(strPixel.toStdString().c_str());
795
796                 /// Display Pixel coordinates
797                 QString strMM;
798                 strMM.sprintf("mm:  (%.0f %.0f %.0f)", pos[0]*1000, pos[1]*1000, pos[2]*1000);
799                 this->Properties->TextMapperMM->SetInput(strMM.toStdString().c_str());
800
801                 QString strValue;
802                 switch (this->ImageData->GetScalarType())
803                 {
804                     case VTK_UNSIGNED_CHAR: {
805                         strValue.sprintf("data value: %u", static_cast<unsigned char*>(this->ImageData->GetScalarPointer(pixel))[0]);
806                         break;
807                     }
808                     case VTK_UNSIGNED_SHORT: {
809                         strValue.sprintf("data value: %u", static_cast<unsigned short*>(this->ImageData->GetScalarPointer(pixel))[0]);
810                         break;
811                     }
812                     case VTK_INT: {
813                         strValue.sprintf("data value: %d", static_cast<int*>(this->ImageData->GetScalarPointer(pixel))[0]);
814                         break;
815                     }
816                     case VTK_FLOAT: {
817                         strValue.sprintf("data value: %.1f", static_cast<float*>(this->ImageData->GetScalarPointer(pixel))[0]);
818                         break;
819                     }
820                     case VTK_DOUBLE: {
821                         strValue.sprintf("data value: %.1f", static_cast<double*>(this->ImageData->GetScalarPointer(pixel))[0]);
822                         break;
823                     }
824                 }
825                 this->Properties->TextMapperValue->SetInput(strValue.toStdString().c_str());
826
827             }
828
829             else {
830                 this->Properties->TextMapperPixel->SetInput("");
831                 this->Properties->TextMapperMM->SetInput("");
832                 this->Properties->TextMapperValue->SetInput("");
833             }
834
835         }
836         else
837         {
838             if ( this->Properties->TextMapperPixel )
839             {
840                 this->Properties->TextMapperPixel->SetInput("");
841                 this->Properties->TextMapperMM->SetInput("");
842                 this->Properties->TextMapperValue->SetInput("");
843             }
844         }
845
846         this->GetRenderWindow()->Render();
847
848     }
849
850 }
851
852
853 void OpenHeartGui::InitChar()
854 {
855
856     this->TableChart = vtkSmartPointer<vtkTable>::New();
857     vtkSmartPointer<vtkFloatArray> arrX = vtkSmartPointer<vtkFloatArray>::New();
858     arrX->SetName("Number of frames");
859     this->TableChart->AddColumn(arrX);
860     vtkSmartPointer<vtkFloatArray> arrY = vtkSmartPointer<vtkFloatArray>::New();
861     arrY->SetName("Volume");
862     this->TableChart->AddColumn(arrY);
863
864     int numPoints = this->NumberOfVolumes;
865     this->TableChart->SetNumberOfRows(numPoints);
866     for (int i=0; i<numPoints; ++i)
867     {
868         this->TableChart->SetValue(i, 0, i);
869         this->TableChart->SetValue(i, 1, 0);
870     }
871     // Add multiple line plots, setting the colors etc
872     vtkSmartPointer<vtkChartXY> chart = vtkSmartPointer<vtkChartXY>::New();
873     ViewChart->GetScene()->AddItem(chart);
874     chart->AddPlot(vtkChart::LINE);
875     vtkPlot *line = chart->AddPlot(vtkChart::LINE);
876     line->SetInput(this->TableChart, 0, 1);
877     line->SetColor(0, 0, 255, 255);
878     line->SetWidth(3.0);
879     chart->GetAxis(vtkAxis::LEFT)->SetTitle("Volume (mL)");
880     chart->GetAxis(vtkAxis::BOTTOM)->SetTitle("Frames");
881     chart->GetAxis(vtkAxis::LEFT)->SetNotation(2);
882     chart->GetAxis(vtkAxis::LEFT)->SetPrecision(1);
883
884 }
885
886
887 void OpenHeartGui::InitPickers()
888 {
889     this->Picker = vtkSmartPointer<vtkCellPicker>::New();
890     this->Picker->SetTolerance(0.005);
891     this->Interactor->SetPicker(this->Picker);
892     this->PickerXY = vtkSmartPointer<vtkCellPicker>::New();
893     this->PickerXY->SetTolerance(0.005);
894     this->InteractorXY->SetPicker(this->PickerXY);
895     this->PickerXZ = vtkSmartPointer<vtkCellPicker>::New();
896     this->PickerXZ->SetTolerance(0.005);
897     this->InteractorXZ->SetPicker(this->PickerXZ);
898     this->PickerYZ = vtkSmartPointer<vtkCellPicker>::New();
899     this->PickerYZ->SetTolerance(0.005);
900     this->InteractorYZ->SetPicker(this->PickerYZ);
901
902 }
903
904
905
906 void OpenHeartGui::InitWidgets()
907 {
908     /// ImagePlane Widget
909     this->InitPlaneWidget();
910 }
911
912
913 void OpenHeartGui::InitOrientationAxes()
914 {
915     vtkSmartPointer<vtkAxesActor> axes = vtkSmartPointer<vtkAxesActor>::New();
916     axes->GetYAxisTipProperty()->SetColor(1,1,0);
917     axes->GetYAxisShaftProperty()->SetColor(1,1,0);
918     this->OrientationWidget->SetOrientationMarker( axes );
919     this->OrientationWidget->SetInteractor( this->qVTK->GetRenderWindow()->GetInteractor() );
920     this->OrientationWidget->SetViewport( 0.8, 0.0, 1.0, 0.2 );
921     this->OrientationWidget->SetEnabled( 1 );
922     this->OrientationWidget->InteractiveOff();
923 }
924
925
926 void OpenHeartGui::InitProperties()
927 {
928     this->Properties->lut = 0;
929     this->Properties->xIPW = 0;
930     this->Properties->yIPW = 0;
931     this->Properties->zIPW = 0;
932     this->Properties->xyIPW = 0;
933     this->Properties->xzIPW = 0;
934     this->Properties->yzIPW = 0;
935     this->Properties->TextActorPixel = 0;
936     this->Properties->TextMapperPixel = 0;
937     this->Properties->TextActorMM = 0;
938     this->Properties->TextMapperMM = 0;
939     this->Properties->TextActorValue = 0;
940     this->Properties->TextMapperValue = 0;
941     this->Properties->TextActorSlice = 0;
942     this->Properties->TextMapperSlice = 0;
943     this->Properties->TextActorNumFrame = 0;
944     this->Properties->TextMapperNumFrame = 0;
945     this->Properties->TextActorResolution = 0;
946     this->Properties->TextMapperResolution = 0;
947     this->Properties->MeshActor = 0;
948     this->Properties->xCutActor = 0;
949     this->Properties->yCutActor = 0;
950     this->Properties->zCutActor = 0;
951     this->Properties->BasalPointActor = 0;
952     this->Properties->ApexPointActor = 0;
953     this->Properties->LongAxisActor = 0;
954     this->Properties->BoundingBoxActor = 0;
955     this->Properties->position = new double[3];
956 }
957
958
959 void OpenHeartGui::InitPlaneWidget()
960 {
961
962     /// Manage main window
963     this->Properties->xIPW = vtkSmartPointer<vtkImagePlaneWidget>::New();
964     this->Properties->yIPW = vtkSmartPointer<vtkImagePlaneWidget>::New();
965     this->Properties->zIPW = vtkSmartPointer<vtkImagePlaneWidget>::New();
966
967     this->Properties->xIPW->SetInteractor(vtkRenderWindowInteractor::New());
968     this->Properties->yIPW->SetInteractor(this->Properties->xIPW->GetInteractor());
969     this->Properties->zIPW->SetInteractor(this->Properties->xIPW->GetInteractor());
970
971     this->Properties->xIPW->DisplayTextOn();
972     this->Properties->xIPW->GetTextProperty()->SetColor(0,0,0);
973     this->Properties->xIPW->SetPicker(this->Picker);
974     this->Properties->xIPW->RestrictPlaneToVolumeOn();
975     this->Properties->xIPW->GetPlaneProperty()->SetColor(0,0,0);
976     this->Properties->xIPW->SetResliceInterpolateToNearestNeighbour();
977     this->Properties->xIPW->TextureInterpolateOff();
978
979     this->Properties->yIPW->DisplayTextOn();
980     this->Properties->yIPW->GetTextProperty()->SetColor(0,0,0);
981     this->Properties->yIPW->SetPicker(this->Picker);
982     this->Properties->yIPW->RestrictPlaneToVolumeOn();
983     this->Properties->yIPW->GetPlaneProperty()->SetColor(0,0,0);
984     this->Properties->yIPW->SetTexturePlaneProperty(this->Properties->xIPW->GetTexturePlaneProperty());
985     this->Properties->yIPW->SetResliceInterpolateToNearestNeighbour();
986     this->Properties->yIPW->TextureInterpolateOff();
987
988     this->Properties->zIPW->DisplayTextOn();
989     this->Properties->zIPW->GetTextProperty()->SetColor(0,0,0);
990     this->Properties->zIPW->SetPicker(this->Picker);
991     this->Properties->zIPW->GetPlaneProperty()->SetColor(0,0,0);
992     this->Properties->zIPW->SetTexturePlaneProperty(this->Properties->xIPW->GetTexturePlaneProperty());
993     this->Properties->zIPW->SetResliceInterpolateToNearestNeighbour();
994     this->Properties->zIPW->TextureInterpolateOff();
995
996
997     /// Manage XY window
998     this->Properties->xyIPW = vtkImagePlaneWidget::New();
999     this->Properties->xyIPW->SetInteractor(vtkRenderWindowInteractor::New());
1000     this->Properties->xyIPW->DisplayTextOn();
1001     this->Properties->xyIPW->GetTextProperty()->SetColor(0,0,0);
1002     this->Properties->xyIPW->SetPicker(this->PickerXY);
1003     this->Properties->xyIPW->RestrictPlaneToVolumeOn();
1004     this->Properties->xyIPW->GetPlaneProperty()->SetColor(0,0,0);
1005     this->Properties->xyIPW->SetResliceInterpolateToNearestNeighbour();
1006     this->Properties->xyIPW->TextureInterpolateOff();
1007
1008     /// Manage XZ window
1009     this->Properties->xzIPW = vtkImagePlaneWidget::New();
1010     this->Properties->xzIPW->SetInteractor(vtkRenderWindowInteractor::New());
1011     this->Properties->xzIPW->DisplayTextOn();
1012     this->Properties->xzIPW->GetTextProperty()->SetColor(0,0,0);
1013     this->Properties->xzIPW->RestrictPlaneToVolumeOn();
1014     this->Properties->xzIPW->GetPlaneProperty()->SetColor(0,0,0);
1015     this->Properties->xzIPW->SetResliceInterpolateToNearestNeighbour();
1016     this->Properties->xzIPW->TextureInterpolateOff();
1017
1018     /// Manage YZ window
1019     this->Properties->yzIPW = vtkImagePlaneWidget::New();
1020     this->Properties->yzIPW->SetInteractor(vtkRenderWindowInteractor::New());
1021     this->Properties->yzIPW->DisplayTextOn();
1022     this->Properties->yzIPW->GetTextProperty()->SetColor(0,0,0);
1023     this->Properties->yzIPW->RestrictPlaneToVolumeOn();
1024     this->Properties->yzIPW->GetPlaneProperty()->SetColor(0,0,0);
1025     this->Properties->yzIPW->SetResliceInterpolateToNearestNeighbour();
1026     this->Properties->yzIPW->TextureInterpolateOff();
1027
1028 }
1029
1030 void OpenHeartGui::InitTexts()
1031 {
1032
1033     /// Display pixel coordinates
1034     this->Properties->TextActorPixel = vtkSmartPointer<vtkActor2D>::New();
1035     this->Properties->TextMapperPixel = vtkSmartPointer<vtkTextMapper>::New();
1036     this->Properties->TextMapperPixel->GetTextProperty()->SetColor(0, 1, 0);
1037     this->Properties->TextMapperPixel->GetTextProperty()->SetFontSize(15);
1038     if ( this->FlagDisplayText ) {
1039         this->Properties->TextMapperPixel->SetInput("");
1040     }
1041     this->Properties->TextMapperPixel->GetTextProperty()->SetJustificationToRight();
1042     this->Properties->TextMapperPixel->GetTextProperty()->ShadowOff();
1043     this->Properties->TextActorPixel->SetPosition(490,520);
1044     this->Properties->TextActorPixel->SetMapper(this->Properties->TextMapperPixel);
1045     this->GetMeshRenderer()->AddActor(this->Properties->TextActorPixel);
1046
1047     /// Display mm coordinates
1048     this->Properties->TextActorMM = vtkSmartPointer<vtkActor2D>::New();
1049     this->Properties->TextMapperMM= vtkSmartPointer<vtkTextMapper>::New();
1050     this->Properties->TextMapperMM->GetTextProperty()->SetColor(0, 1, 0);
1051     this->Properties->TextMapperMM->GetTextProperty()->SetFontSize(15);
1052     if ( this->FlagDisplayText ) {
1053         this->Properties->TextMapperMM->SetInput("");
1054     }
1055     this->Properties->TextMapperMM->GetTextProperty()->SetJustificationToRight();
1056     this->Properties->TextMapperMM->GetTextProperty()->ShadowOff();
1057     this->Properties->TextActorMM->SetPosition(490,495);
1058     this->Properties->TextActorMM->SetMapper(this->Properties->TextMapperMM);
1059     this->GetMeshRenderer()->AddActor(this->Properties->TextActorMM);
1060
1061     /// Display data value
1062     this->Properties->TextActorValue = vtkSmartPointer<vtkActor2D>::New();
1063     this->Properties->TextMapperValue = vtkSmartPointer<vtkTextMapper>::New();
1064     this->Properties->TextMapperValue->GetTextProperty()->SetColor(0, 1, 0);
1065     this->Properties->TextMapperValue->GetTextProperty()->SetFontSize(15);
1066     if ( this->FlagDisplayText ) {
1067         this->Properties->TextMapperValue->SetInput("");
1068     }
1069     this->Properties->TextMapperValue->GetTextProperty()->SetJustificationToRight();
1070     this->Properties->TextMapperValue->GetTextProperty()->ShadowOff();
1071     this->Properties->TextActorValue->SetPosition(490,470);
1072     this->Properties->TextActorValue->SetMapper(this->Properties->TextMapperValue);
1073     this->GetMeshRenderer()->AddActor(this->Properties->TextActorValue);
1074
1075     /// Display Slice
1076     this->Properties->TextActorSlice = vtkSmartPointer<vtkActor2D>::New();
1077     this->Properties->TextMapperSlice = vtkSmartPointer<vtkTextMapper>::New();
1078     this->Properties->TextMapperSlice->GetTextProperty()->SetColor(0, 1, 0);
1079     this->Properties->TextMapperSlice->GetTextProperty()->SetFontSize(15);
1080     if ( this->FlagDisplayText ) {
1081         int slice = (int)( (this->Properties->position[1] - this->ImageData->GetOrigin()[1]) / this->ImageData->GetSpacing()[1] + 0.5f );
1082         //cout << this->Properties->position[1] << endl;
1083         QString strSlice;
1084         strSlice.sprintf("Slice: %d",slice);
1085         this->Properties->TextMapperSlice->SetInput(strSlice.toStdString().c_str());
1086     }
1087     this->Properties->TextMapperSlice->GetTextProperty()->SetJustificationToLeft();
1088     this->Properties->TextMapperSlice->GetTextProperty()->ShadowOff();
1089     this->Properties->TextActorSlice->SetPosition(10,520);
1090     this->Properties->TextActorSlice->SetMapper(this->Properties->TextMapperSlice);
1091     this->GetMeshRenderer()->AddActor(this->Properties->TextActorSlice);
1092
1093     /// Display frame number
1094     this->Properties->TextActorNumFrame = vtkSmartPointer<vtkActor2D>::New();
1095     this->Properties->TextMapperNumFrame = vtkSmartPointer<vtkTextMapper>::New();
1096     this->Properties->TextMapperNumFrame->GetTextProperty()->SetColor(0, 1, 0);
1097     this->Properties->TextMapperNumFrame->GetTextProperty()->SetFontSize(15);
1098     if ( this->FlagDisplayText ) {
1099         QString str;
1100         str.sprintf("Frame: %d",this->CurrentFrame);
1101         this->Properties->TextMapperNumFrame->SetInput(str.toStdString().c_str());
1102     }
1103     this->Properties->TextMapperNumFrame->GetTextProperty()->SetJustificationToLeft();
1104     this->Properties->TextMapperNumFrame->GetTextProperty()->ShadowOff();
1105     this->Properties->TextActorNumFrame->SetPosition(10, 45);
1106     this->Properties->TextActorNumFrame->SetMapper(this->Properties->TextMapperNumFrame);
1107     this->GetMeshRenderer()->AddActor(this->Properties->TextActorNumFrame);
1108
1109     /// Display resolution value
1110     this->Properties->TextActorResolution = vtkSmartPointer<vtkActor2D>::New();
1111     this->Properties->TextMapperResolution = vtkSmartPointer<vtkTextMapper>::New();
1112     this->Properties->TextMapperResolution->GetTextProperty()->SetColor(0, 1, 0);
1113     this->Properties->TextMapperResolution->GetTextProperty()->SetFontSize(15);
1114     if ( this->FlagDisplayText ) {
1115         QString str;
1116         str.sprintf("Resolution: %.2f x %.2f x %.2f mm",this->ImageData->GetSpacing()[0]*1000,this->ImageData->GetSpacing()[1]*1000,this->ImageData->GetSpacing()[2]*1000);
1117         this->Properties->TextMapperResolution->SetInput(str.toStdString().c_str());
1118     }
1119     this->Properties->TextMapperResolution->GetTextProperty()->SetJustificationToLeft();
1120     this->Properties->TextMapperResolution->GetTextProperty()->ShadowOff();
1121     this->Properties->TextActorResolution->SetPosition(10, 20);
1122     this->Properties->TextActorResolution->SetMapper(this->Properties->TextMapperResolution);
1123     this->GetMeshRenderer()->AddActor(this->Properties->TextActorResolution);
1124
1125 }
1126
1127
1128 void OpenHeartGui::SetCustomInteractorStyle()
1129 {
1130
1131     /// customize main interactor
1132     vtkSmartPointer<vtkMyInteractorStyleTrackballCameraOpenHeart> CustomInteractorStyle =
1133             vtkSmartPointer<vtkMyInteractorStyleTrackballCameraOpenHeart>::New();
1134     CustomInteractorStyle->SetOpenHeartGui( this );
1135     this->Interactor->SetInteractorStyle(CustomInteractorStyle);
1136
1137     /// customize XY interactor
1138     vtkSmartPointer<vtkMyInteractorStyleTrackballCameraOpenHeartXY> CustomInteractorStyleXY =
1139             vtkSmartPointer<vtkMyInteractorStyleTrackballCameraOpenHeartXY>::New();
1140     CustomInteractorStyleXY->SetOpenHeartGui( this );
1141     this->InteractorXY->SetInteractorStyle(CustomInteractorStyleXY);
1142
1143     /// customize XZ interactor
1144     vtkSmartPointer<vtkMyInteractorStyleTrackballCameraOpenHeartXZ> CustomInteractorStyleXZ =
1145             vtkSmartPointer<vtkMyInteractorStyleTrackballCameraOpenHeartXZ>::New();
1146     CustomInteractorStyleXZ->SetOpenHeartGui( this );
1147     this->InteractorXZ->SetInteractorStyle(CustomInteractorStyleXZ);
1148
1149     /// customize YZ interactor
1150     vtkSmartPointer<vtkMyInteractorStyleTrackballCameraOpenHeartYZ> CustomInteractorStyleYZ =
1151             vtkSmartPointer<vtkMyInteractorStyleTrackballCameraOpenHeartYZ>::New();
1152     CustomInteractorStyleYZ->SetOpenHeartGui( this );
1153     this->InteractorYZ->SetInteractorStyle(CustomInteractorStyleYZ);
1154
1155 }
1156
1157
1158 void OpenHeartGui::CreateFromSequenceDataPointer(std::string inputFilename)
1159 {
1160
1161     /// Read 3D volume
1162     QString str;
1163     for (int i=1; i<=this->NumberOfVolumes; i++)
1164     {
1165         if (i<10)
1166             str.sprintf("%s0%d.mhd",inputFilename.c_str(),i);
1167         else
1168             str.sprintf("%s%d.mhd",inputFilename.c_str(),i);
1169         vtkMetaImageReader *reader = vtkMetaImageReader::New();
1170         reader->SetFileName(str.toStdString().c_str());
1171         reader->Update();
1172         this->StackVolume.push_back(reader->GetOutput());
1173     }
1174
1175     /// Initialize attibute related to stack of volumes
1176     this->itStackVolume = this->StackVolume.begin();
1177     this->CurrentFrame = 0;
1178     this->ImageData = (*this->itStackVolume);
1179     double center[3];
1180     for ( unsigned int k=0; k<3; k++ ) {
1181         this->Dims[k] = this->ImageData->GetDimensions()[k];
1182         center[k] = ((this->ImageData->GetDimensions()[k])*(this->ImageData->GetSpacing()[k]))/2;
1183     }
1184
1185     /// Allocate lookuptable
1186     double range[2];
1187     this->ImageData->GetScalarRange(range);
1188     int NumberOfColors = vtkMath::Round(range[1]-range[0]);
1189     NumberOfColors++;
1190     this->Properties->lut = vtkSmartPointer<vtkLookupTable>::New();
1191     this->Properties->lut->SetNumberOfColors(NumberOfColors);
1192     this->Properties->lut->SetValueRange(range[0]/NumberOfColors,range[1]/NumberOfColors);
1193     this->Properties->lut->SetRampToLinear();
1194     this->Properties->lut->SetSaturationRange(0.,0.);
1195     this->Properties->lut->SetHueRange(0.,0.);
1196
1197     /// Manage main window
1198     this->Properties->xIPW->SetCurrentRenderer(this->GetMainRenderer());
1199     this->Properties->yIPW->SetCurrentRenderer(this->GetMainRenderer());
1200     this->Properties->zIPW->SetCurrentRenderer(this->GetMainRenderer());
1201
1202     /// The 3 image plane widgets are used.
1203     this->Properties->xIPW->SetInput(this->ImageData);
1204     this->Properties->yIPW->SetInput(this->ImageData);
1205     this->Properties->zIPW->SetInput(this->ImageData);
1206
1207     this->Properties->xIPW->SetPlaneOrientationToXAxes();
1208     this->Properties->yIPW->SetPlaneOrientationToYAxes();
1209     this->Properties->zIPW->SetPlaneOrientationToZAxes();
1210
1211     this->Properties->xIPW->SetSlicePosition(center[0]);
1212     this->Properties->yIPW->SetSlicePosition(center[1]);
1213     this->Properties->zIPW->SetSlicePosition(center[2]);
1214
1215     this->Properties->xIPW->SetLookupTable(this->Properties->lut);
1216     this->Properties->yIPW->SetLookupTable(this->Properties->lut);
1217     this->Properties->zIPW->SetLookupTable(this->Properties->lut);
1218
1219     this->Properties->position[0] = center[0];
1220     this->Properties->position[1] = center[1];
1221     this->Properties->position[2] = center[2];
1222
1223     this->Properties->xIPW->On();
1224     this->Properties->yIPW->On();
1225     this->Properties->zIPW->On();
1226
1227     /// Manage XY window
1228     this->Properties->xyIPW->SetCurrentRenderer(this->GetXYRenderer());
1229     this->Properties->xyIPW->SetInput(this->ImageData);
1230     this->Properties->xyIPW->SetPlaneOrientationToZAxes();
1231     this->Properties->xyIPW->SetSlicePosition(center[2]);
1232     this->Properties->xyIPW->SetLookupTable(this->Properties->lut);
1233     this->Properties->xyIPW->On();
1234     this->RenXY->GetActiveCamera()->SetFocalPoint( this->ImageData->GetDimensions()[0]/2,
1235                                                    this->ImageData->GetDimensions()[1]/2,
1236                                                    this->ImageData->GetDimensions()[2]/2 );
1237     this->RenXY->GetActiveCamera()->SetPosition( this->ImageData->GetDimensions()[0]/2,
1238                                                  this->ImageData->GetDimensions()[1]/2,
1239                                                  this->ImageData->GetDimensions()[2]*10 );
1240     this->RenXY->GetActiveCamera()->SetViewUp(0,0,-1);
1241     this->RenXY->ResetCamera();
1242     this->RenXY->GetActiveCamera()->Zoom(this->ZoomLabel);
1243     this->GetRenderWindowXY()->Render();
1244
1245     /// Manage XZ window
1246     this->Properties->xzIPW->SetCurrentRenderer(this->GetXZRenderer());
1247     this->Properties->xzIPW->SetInput(this->ImageData);
1248     this->Properties->xzIPW->SetPlaneOrientationToYAxes();
1249     this->Properties->xzIPW->SetSlicePosition(center[1]);
1250     this->Properties->xzIPW->SetLookupTable(this->Properties->lut);
1251     this->Properties->xzIPW->On();
1252     this->RenXZ->GetActiveCamera()->SetFocalPoint( this->ImageData->GetDimensions()[0]/2,
1253                                                    this->ImageData->GetDimensions()[1]/2,
1254                                                    this->ImageData->GetDimensions()[2]/2 );
1255     this->RenXZ->GetActiveCamera()->SetPosition( this->ImageData->GetDimensions()[0]/2,
1256                                                  this->ImageData->GetDimensions()[1]*10,
1257                                                  this->ImageData->GetDimensions()[2]/2 );
1258     this->RenXZ->GetActiveCamera()->SetViewUp(0,0,-1);
1259
1260     this->RenXZ->ResetCamera();
1261     this->RenXZ->GetActiveCamera()->Zoom(this->ZoomLabel);
1262
1263
1264     /// Manage YZ window
1265     this->Properties->yzIPW->SetCurrentRenderer(this->GetYZRenderer());
1266     this->Properties->yzIPW->SetInput(this->ImageData);
1267     this->Properties->yzIPW->SetPlaneOrientationToXAxes();
1268     this->Properties->yzIPW->SetSlicePosition(center[0]);
1269     this->Properties->yzIPW->SetLookupTable(this->Properties->lut);
1270     this->Properties->yzIPW->On();
1271     this->RenYZ->GetActiveCamera()->SetFocalPoint( this->ImageData->GetDimensions()[0]/2,
1272                                                    this->ImageData->GetDimensions()[1]/2,
1273                                                    this->ImageData->GetDimensions()[2]/2 );
1274     this->RenYZ->GetActiveCamera()->SetPosition( this->ImageData->GetDimensions()[0]*10,
1275                                                  this->ImageData->GetDimensions()[1]/2,
1276                                                  this->ImageData->GetDimensions()[2]/2 );
1277     this->RenYZ->GetActiveCamera()->SetViewUp(0,0,-1);
1278     this->RenYZ->ResetCamera();
1279     this->RenYZ->GetActiveCamera()->Zoom(this->ZoomLabel);
1280
1281     /// Manage Bounding box around the volume for the 3D display
1282     vtkSmartPointer<vtkOutlineFilter> outlineData = vtkSmartPointer<vtkOutlineFilter>::New();
1283     outlineData->SetInput(this->ImageData);
1284     vtkSmartPointer<vtkPolyDataMapper> mapOutline = vtkSmartPointer<vtkPolyDataMapper>::New();
1285     mapOutline->SetInput(outlineData->GetOutput());
1286     this->Properties->BoundingBoxActor = vtkSmartPointer<vtkActor>::New();
1287     this->Properties->BoundingBoxActor->SetMapper(mapOutline);
1288
1289     /// Refresh YZ viewer
1290     this->GetRenderWindowYZ()->Render();
1291
1292 }
1293
1294
1295 void OpenHeartGui::InterpolationManagement()
1296 {
1297
1298     if ( this->FlagReslice == 0 )
1299     {
1300         if ( this->FlagInterpolation == 0 )
1301         {
1302             this->FlagInterpolation = 1;
1303             this->Properties->xIPW->TextureInterpolateOn();
1304             this->Properties->yIPW->TextureInterpolateOn();
1305             this->Properties->zIPW->TextureInterpolateOn();
1306         }
1307         else
1308         {
1309             this->FlagInterpolation = 0;
1310             this->Properties->xIPW->TextureInterpolateOff();
1311             this->Properties->yIPW->TextureInterpolateOff();
1312             this->Properties->zIPW->TextureInterpolateOff();
1313         }
1314
1315         /// Force to display the change on the XYZ planes
1316         this->Properties->xIPW->SetInput(this->ImageData);
1317         this->Properties->yIPW->SetInput(this->ImageData);
1318         this->Properties->zIPW->SetInput(this->ImageData);
1319         this->Properties->xIPW->SetSlicePosition(this->Properties->position[0]);
1320         this->Properties->yIPW->SetSlicePosition(this->Properties->position[1]);
1321         this->Properties->zIPW->SetSlicePosition(this->Properties->position[2]);
1322
1323         this->GetRenderWindow()->Render();
1324     }
1325
1326 }
1327
1328
1329 void OpenHeartGui::UpdateForwardViewers()
1330 {
1331
1332     if ( this->ImageData )
1333     {
1334
1335         ++(this->itStackVolume);
1336         ++(this->CurrentFrame);
1337         if (this->Properties->MeshActor) {
1338             ++(this->itStackMesh);
1339             ++(this->Properties->itStackMapperList);
1340             ++(this->Properties->itStackMapXCutter);
1341             ++(this->Properties->itStackMapYCutter);
1342             ++(this->Properties->itStackMapZCutter);
1343         }
1344
1345         if ( this->itStackVolume == this->StackVolume.end() ) {
1346             this->itStackVolume = this->StackVolume.begin();
1347             this->CurrentFrame = 0;
1348             if (this->Properties->MeshActor) {
1349                 this->itStackMesh = this->StackMesh.begin();
1350                 this->Properties->itStackMapperList = this->Properties->StackMapperList.begin();
1351                 this->Properties->itStackMapXCutter = this->Properties->StackMapXCutter.begin();
1352                 this->Properties->itStackMapYCutter = this->Properties->StackMapYCutter.begin();
1353                 this->Properties->itStackMapZCutter = this->Properties->StackMapZCutter.begin();
1354             }
1355         }
1356
1357         /// Update image data pointer
1358         this->ImageData = (*this->itStackVolume);
1359
1360         if ( this->FlagReslice == 0 )
1361         {
1362
1363             /// Update the 3 planes and the corresponding 2D plane windows
1364             this->Properties->xIPW->SetInput(this->ImageData);
1365             this->Properties->yIPW->SetInput(this->ImageData);
1366             this->Properties->zIPW->SetInput(this->ImageData);
1367             this->Properties->xyIPW->SetInput(this->ImageData);
1368             this->Properties->xzIPW->SetInput(this->ImageData);
1369             this->Properties->yzIPW->SetInput(this->ImageData);
1370             this->Properties->xIPW->SetSlicePosition(this->Properties->position[0]);
1371             this->Properties->yIPW->SetSlicePosition(this->Properties->position[1]);
1372             this->Properties->zIPW->SetSlicePosition(this->Properties->position[2]);
1373             this->Properties->xyIPW->SetSlicePosition(this->Properties->position[2]);
1374             this->Properties->xzIPW->SetSlicePosition(this->Properties->position[1]);
1375             this->Properties->yzIPW->SetSlicePosition(this->Properties->position[0]);
1376
1377         }
1378         else
1379         {
1380
1381             /// Update X plan
1382             double pto[3];
1383             double pt1[3];
1384             double pt2[3];
1385             for (int i=0;i<3; i++) {
1386                 pto[i] = this->Properties->xIPW->GetOrigin()[i];
1387                 pt1[i] = this->Properties->xIPW->GetPoint1()[i];
1388                 pt2[i] = this->Properties->xIPW->GetPoint2()[i];
1389             }
1390             double position = this->Properties->xIPW->GetSlicePosition();
1391             this->Properties->xIPW->SetInput(this->ImageData);
1392             this->Properties->yzIPW->SetInput(this->ImageData);
1393             this->Properties->xIPW->SetOrigin(pto);
1394             this->Properties->xIPW->SetPoint1(pt1);
1395             this->Properties->xIPW->SetPoint2(pt2);
1396             this->Properties->xIPW->UpdatePlacement();
1397             this->Properties->yzIPW->SetOrigin(pto);
1398             this->Properties->yzIPW->SetPoint1(pt1);
1399             this->Properties->yzIPW->SetPoint2(pt2);
1400             this->Properties->yzIPW->UpdatePlacement();
1401             this->Properties->xIPW->SetSlicePosition(position);
1402             this->Properties->yzIPW->SetSlicePosition(position);
1403
1404             /// Update Y plan
1405             for (int i=0;i<3; i++) {
1406                 pto[i] = this->Properties->yIPW->GetOrigin()[i];
1407                 pt1[i] = this->Properties->yIPW->GetPoint1()[i];
1408                 pt2[i] = this->Properties->yIPW->GetPoint2()[i];
1409             }
1410             position = this->Properties->yIPW->GetSlicePosition();
1411             this->Properties->yIPW->SetInput(this->ImageData);
1412             this->Properties->xzIPW->SetInput(this->ImageData);
1413             this->Properties->yIPW->SetOrigin(pto);
1414             this->Properties->yIPW->SetPoint1(pt1);
1415             this->Properties->yIPW->SetPoint2(pt2);
1416             this->Properties->yIPW->UpdatePlacement();
1417             this->Properties->xzIPW->SetOrigin(pto);
1418             this->Properties->xzIPW->SetPoint1(pt1);
1419             this->Properties->xzIPW->SetPoint2(pt2);
1420             this->Properties->xzIPW->UpdatePlacement();
1421             this->Properties->yIPW->SetSlicePosition(position);
1422             this->Properties->xzIPW->SetSlicePosition(position);
1423
1424             /// Update Z plan
1425             for (int i=0;i<3; i++) {
1426                 pto[i] = this->Properties->zIPW->GetOrigin()[i];
1427                 pt1[i] = this->Properties->zIPW->GetPoint1()[i];
1428                 pt2[i] = this->Properties->zIPW->GetPoint2()[i];
1429             }
1430             position = this->Properties->zIPW->GetSlicePosition();
1431             this->Properties->zIPW->SetInput(this->ImageData);
1432             this->Properties->xyIPW->SetInput(this->ImageData);
1433             this->Properties->zIPW->SetOrigin(pto);
1434             this->Properties->zIPW->SetPoint1(pt1);
1435             this->Properties->zIPW->SetPoint2(pt2);
1436             this->Properties->zIPW->UpdatePlacement();
1437             this->Properties->xyIPW->SetOrigin(pto);
1438             this->Properties->xyIPW->SetPoint1(pt1);
1439             this->Properties->xyIPW->SetPoint2(pt2);
1440             this->Properties->xyIPW->UpdatePlacement();
1441             this->Properties->zIPW->SetSlicePosition(position);
1442             this->Properties->xyIPW->SetSlicePosition(position);
1443
1444         }
1445
1446         /// Update the segmented mesh if needed
1447         if (this->Properties->MeshActor)
1448         {
1449             this->Properties->MeshActor->SetMapper(*this->Properties->itStackMapperList);
1450             vtkPolyDataMapper* cutMapperX = vtkPolyDataMapper::New();
1451             cutMapperX->SetInputConnection((*this->Properties->itStackMapXCutter)->GetOutputPort());
1452             this->Properties->xCutActor->SetMapper(cutMapperX);
1453             vtkPolyDataMapper* cutMapperY = vtkPolyDataMapper::New();
1454             cutMapperY->SetInputConnection((*this->Properties->itStackMapYCutter)->GetOutputPort());
1455             this->Properties->yCutActor->SetMapper(cutMapperY);
1456             vtkPolyDataMapper* cutMapperZ = vtkPolyDataMapper::New();
1457             cutMapperZ->SetInputConnection((*this->Properties->itStackMapZCutter)->GetOutputPort());
1458             this->Properties->zCutActor->SetMapper(cutMapperZ);
1459         }
1460
1461         /// Update viewers
1462         this->GetRenderWindow()->Render();
1463         this->GetXYRenderer()->ResetCameraClippingRange();
1464         this->GetRenderWindowXY()->Render();
1465         this->GetXZRenderer()->ResetCameraClippingRange();
1466         this->GetRenderWindowXZ()->Render();
1467         this->GetYZRenderer()->ResetCameraClippingRange();
1468         this->GetRenderWindowYZ()->Render();
1469
1470     }
1471
1472 }
1473
1474
1475 void OpenHeartGui::UpdateBackwardViewers()
1476 {
1477
1478     if ( this->ImageData )
1479     {
1480
1481         if ( this->itStackVolume == this->StackVolume.begin() )
1482         {
1483             this->itStackVolume = this->StackVolume.end();
1484             this->CurrentFrame = this->NumberOfVolumes;
1485             if (this->Properties->MeshActor) {
1486                 this->itStackMesh = this->StackMesh.end();
1487                 this->Properties->itStackMapperList = this->Properties->StackMapperList.end();
1488                 this->Properties->itStackMapXCutter = this->Properties->StackMapXCutter.end();
1489                 this->Properties->itStackMapYCutter = this->Properties->StackMapYCutter.end();
1490                 this->Properties->itStackMapZCutter = this->Properties->StackMapZCutter.end();
1491             }
1492         }
1493
1494         --(this->itStackVolume);
1495         --(this->CurrentFrame);
1496         if (this->Properties->MeshActor) {
1497             --(this->itStackMesh);
1498             --(this->Properties->itStackMapperList);
1499             --(this->Properties->itStackMapXCutter);
1500             --(this->Properties->itStackMapYCutter);
1501             --(this->Properties->itStackMapZCutter);
1502         }
1503
1504         /// Update image data pointer
1505         this->ImageData = (*this->itStackVolume);
1506
1507         if ( this->FlagReslice == 0 )
1508         {
1509
1510             /// Update the 3 planes
1511             this->Properties->xIPW->SetInput(this->ImageData);
1512             this->Properties->yIPW->SetInput(this->ImageData);
1513             this->Properties->zIPW->SetInput(this->ImageData);
1514             this->Properties->xyIPW->SetInput(this->ImageData);
1515             this->Properties->xzIPW->SetInput(this->ImageData);
1516             this->Properties->yzIPW->SetInput(this->ImageData);
1517             this->Properties->xIPW->SetSlicePosition(this->Properties->position[0]);
1518             this->Properties->yIPW->SetSlicePosition(this->Properties->position[1]);
1519             this->Properties->zIPW->SetSlicePosition(this->Properties->position[2]);
1520             this->Properties->xyIPW->SetSlicePosition(this->Properties->position[2]);
1521             this->Properties->xzIPW->SetSlicePosition(this->Properties->position[1]);
1522             this->Properties->yzIPW->SetSlicePosition(this->Properties->position[0]);
1523
1524         }
1525         else
1526         {
1527
1528             /// Update X plan
1529             double pto[3];
1530             double pt1[3];
1531             double pt2[3];
1532             for (int i=0;i<3; i++) {
1533                 pto[i] = this->Properties->xIPW->GetOrigin()[i];
1534                 pt1[i] = this->Properties->xIPW->GetPoint1()[i];
1535                 pt2[i] = this->Properties->xIPW->GetPoint2()[i];
1536             }
1537             double position = this->Properties->xIPW->GetSlicePosition();
1538             this->Properties->xIPW->SetInput(this->ImageData);
1539             this->Properties->yzIPW->SetInput(this->ImageData);
1540             this->Properties->xIPW->SetOrigin(pto);
1541             this->Properties->xIPW->SetPoint1(pt1);
1542             this->Properties->xIPW->SetPoint2(pt2);
1543             this->Properties->xIPW->UpdatePlacement();
1544             this->Properties->yzIPW->SetOrigin(pto);
1545             this->Properties->yzIPW->SetPoint1(pt1);
1546             this->Properties->yzIPW->SetPoint2(pt2);
1547             this->Properties->yzIPW->UpdatePlacement();
1548             this->Properties->xIPW->SetSlicePosition(position);
1549             this->Properties->yzIPW->SetSlicePosition(position);
1550
1551             /// Update Y plan
1552             for (int i=0;i<3; i++) {
1553                 pto[i] = this->Properties->yIPW->GetOrigin()[i];
1554                 pt1[i] = this->Properties->yIPW->GetPoint1()[i];
1555                 pt2[i] = this->Properties->yIPW->GetPoint2()[i];
1556             }
1557             position = this->Properties->yIPW->GetSlicePosition();
1558             this->Properties->yIPW->SetInput(this->ImageData);
1559             this->Properties->xzIPW->SetInput(this->ImageData);
1560             this->Properties->yIPW->SetOrigin(pto);
1561             this->Properties->yIPW->SetPoint1(pt1);
1562             this->Properties->yIPW->SetPoint2(pt2);
1563             this->Properties->yIPW->UpdatePlacement();
1564             this->Properties->xzIPW->SetOrigin(pto);
1565             this->Properties->xzIPW->SetPoint1(pt1);
1566             this->Properties->xzIPW->SetPoint2(pt2);
1567             this->Properties->xzIPW->UpdatePlacement();
1568             this->Properties->yIPW->SetSlicePosition(position);
1569             this->Properties->xzIPW->SetSlicePosition(position);
1570
1571             /// Update Z plan
1572             for (int i=0;i<3; i++) {
1573                 pto[i] = this->Properties->zIPW->GetOrigin()[i];
1574                 pt1[i] = this->Properties->zIPW->GetPoint1()[i];
1575                 pt2[i] = this->Properties->zIPW->GetPoint2()[i];
1576             }
1577             position = this->Properties->zIPW->GetSlicePosition();
1578             this->Properties->zIPW->SetInput(this->ImageData);
1579             this->Properties->xyIPW->SetInput(this->ImageData);
1580             this->Properties->zIPW->SetOrigin(pto);
1581             this->Properties->zIPW->SetPoint1(pt1);
1582             this->Properties->zIPW->SetPoint2(pt2);
1583             this->Properties->zIPW->UpdatePlacement();
1584             this->Properties->xyIPW->SetOrigin(pto);
1585             this->Properties->xyIPW->SetPoint1(pt1);
1586             this->Properties->xyIPW->SetPoint2(pt2);
1587             this->Properties->xyIPW->UpdatePlacement();
1588             this->Properties->zIPW->SetSlicePosition(position);
1589             this->Properties->xyIPW->SetSlicePosition(position);
1590
1591         }
1592
1593         /// Update the segmented mesh if needed
1594         if (this->Properties->MeshActor)
1595         {
1596             this->Properties->MeshActor->SetMapper(*this->Properties->itStackMapperList);
1597             vtkPolyDataMapper* cutMapperX = vtkPolyDataMapper::New();
1598             cutMapperX->SetInputConnection((*this->Properties->itStackMapXCutter)->GetOutputPort());
1599             this->Properties->xCutActor->SetMapper(cutMapperX);
1600             vtkPolyDataMapper* cutMapperY = vtkPolyDataMapper::New();
1601             cutMapperY->SetInputConnection((*this->Properties->itStackMapYCutter)->GetOutputPort());
1602             this->Properties->yCutActor->SetMapper(cutMapperY);
1603             vtkPolyDataMapper* cutMapperZ = vtkPolyDataMapper::New();
1604             cutMapperZ->SetInputConnection((*this->Properties->itStackMapZCutter)->GetOutputPort());
1605             this->Properties->zCutActor->SetMapper(cutMapperZ);
1606         }
1607
1608         this->GetRenderWindow()->Render();
1609         this->GetRenderWindowXY()->Render();
1610         this->GetRenderWindowXZ()->Render();
1611         this->GetRenderWindowYZ()->Render();
1612
1613     }
1614
1615 }
1616
1617
1618 void OpenHeartGui::slotMeshAlpha(int val)
1619 {
1620
1621     if ( this->Properties->MeshActor )
1622     {
1623         this->Properties->MeshActor->GetProperty()->SetOpacity(val/100.);
1624         this->GetRenderWindow()->Render();
1625     }
1626
1627 }
1628
1629
1630 void OpenHeartGui::slotRefreshViewer(int val)
1631 {
1632
1633     /// Loop cases
1634     while ( val != this->CurrentFrame )
1635     {
1636         if ( (this->FlagLoopEndToBegin == 0) && (this->FlagLoopBeginToEnd == 0) )
1637         {
1638             /// Normal transition
1639             if ( ( val-this->CurrentFrame ) > 0 )
1640                 UpdateForwardViewers();
1641             else
1642                 UpdateBackwardViewers();
1643         }
1644         else
1645         {
1646             /// Loop end to begin
1647             if ( this->FlagLoopEndToBegin == 1 ) {
1648                 this->FlagLoopEndToBegin = 0;
1649                 UpdateForwardViewers();
1650             }
1651             /// Loop begin to end
1652             if ( this->FlagLoopBeginToEnd == 1 ) {
1653                 this->FlagLoopBeginToEnd = 0;
1654                 UpdateBackwardViewers();
1655             }
1656         }
1657     }
1658
1659     /// Update Frame text
1660     if ( (this->FlagDisplayText) && (this->Properties->TextMapperNumFrame) )
1661     {
1662         QString str;
1663         str.sprintf("Frame: %d",this->CurrentFrame);
1664         this->Properties->TextMapperNumFrame->SetInput(str.toStdString().c_str());
1665         this->GetRenderWindow()->Render();
1666     }
1667
1668 }
1669
1670
1671 void OpenHeartGui::slotTabChange(int val)
1672 {
1673
1674     if (val==3)
1675     {
1676
1677         if ( this->Properties->ApexPointActor != 0 ) {
1678             this->GetMainRenderer()->AddActor(this->Properties->ApexPointActor);
1679             this->FlagDisplayApexPoint = 1;
1680         }
1681         if ( this->Properties->BasalPointActor != 0 ) {
1682             this->GetMainRenderer()->AddActor(this->Properties->BasalPointActor);
1683             this->FlagDisplayBasalPoint = 1;
1684         }
1685         if ( this->Properties->LongAxisActor != 0 ) {
1686             this->GetMainRenderer()->AddActor(this->Properties->LongAxisActor);
1687             this->FlagDisplayLongAxis = 1;
1688         }
1689
1690         this->slot3DView();
1691     }
1692     else
1693     {
1694
1695         if ( this->FlagDisplayApexPoint == 1 ) {
1696             this->GetMainRenderer()->RemoveActor(this->Properties->ApexPointActor);
1697             this->FlagDisplayApexPoint = 0;
1698             this->GetRenderWindow()->Render();
1699         }
1700         if ( this->FlagDisplayBasalPoint == 1 ) {
1701             this->GetMainRenderer()->RemoveActor(this->Properties->BasalPointActor);
1702             this->FlagDisplayBasalPoint = 0;
1703             this->GetRenderWindow()->Render();
1704         }
1705         if ( this->FlagDisplayLongAxis == 1 ) {
1706             this->GetMainRenderer()->RemoveActor(this->Properties->LongAxisActor);
1707             this->FlagDisplayLongAxis = 0;
1708             this->GetRenderWindow()->Render();
1709         }
1710
1711     }
1712
1713 }
1714
1715
1716
1717 void OpenHeartGui::slotPlay()
1718 {
1719     if ( this->FlagPlay == 0 ) {
1720         this->FlagPlay = 1;
1721         this->pushButtonPlay->setText("Pause");
1722         this->scrollBar->setEnabled(false);
1723         this->Timer->start(40);
1724     }
1725     else {
1726         this->FlagPlay = 0;
1727         this->Timer->stop();
1728         this->pushButtonPlay->setText("Play");
1729         this->scrollBar->setEnabled(true);
1730     }
1731 }
1732
1733
1734 void OpenHeartGui::slotTimerEvent()
1735 {
1736
1737     int val = this->CurrentFrame;
1738     if ( val < (this->NumberOfVolumes-1) )
1739         this->scrollBar->setSliderPosition(val+1);
1740     else {
1741         this->FlagLoopEndToBegin = 1;
1742         this->scrollBar->setSliderPosition(0);
1743     }
1744
1745 }
1746
1747
1748 void OpenHeartGui::slotBasalPoint()
1749 {
1750
1751     if ( this->Properties->BasalPointActor == 0 ) {
1752         this->Properties->BasalPointActor = vtkSmartPointer<vtkActor>::New();
1753     }
1754     else {
1755         this->GetMainRenderer()->RemoveActor(this->Properties->BasalPointActor);
1756     }
1757
1758     vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New();
1759     sphereSource->SetCenter(this->Properties->position[0],
1760                             this->Properties->position[1],
1761                             this->Properties->position[2]);
1762     sphereSource->SetRadius(5.0*this->ImageData->GetSpacing()[0]);
1763     sphereSource->Update();
1764
1765     for (int i=0; i<3; i++)
1766         this->BasalPoint[i] = this->Properties->position[i];
1767
1768     vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
1769     mapper->SetInput(sphereSource->GetOutput());
1770
1771     this->Properties->BasalPointActor->SetMapper(mapper);
1772     this->Properties->BasalPointActor->GetProperty()->SetColor(0,1,0);
1773
1774     this->GetMainRenderer()->AddActor(this->Properties->BasalPointActor);
1775     this->FlagDisplayBasalPoint = 1;
1776
1777     if ( this->Properties->ApexPointActor != 0 )
1778     {
1779         this->CreateLongAxisActor();
1780         this->FlagLongAxis = 1;
1781         this->GetMainRenderer()->AddActor(this->Properties->LongAxisActor);
1782         this->FlagDisplayLongAxis = 1;
1783         this->pushButtonReslice->setEnabled(true);
1784     }
1785
1786     this->GetRenderWindow()->Render();
1787
1788 }
1789
1790
1791 void OpenHeartGui::slotApexPoint()
1792 {
1793
1794     if ( this->Properties->ApexPointActor == 0 ) {
1795         this->Properties->ApexPointActor = vtkSmartPointer<vtkActor>::New();
1796     }
1797     else {
1798         this->GetMainRenderer()->RemoveActor(this->Properties->ApexPointActor);
1799     }
1800
1801     vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New();
1802     sphereSource->SetCenter(this->Properties->position[0],
1803                             this->Properties->position[1],
1804                             this->Properties->position[2]);
1805     sphereSource->SetRadius(5.0*this->ImageData->GetSpacing()[0]);
1806     sphereSource->Update();
1807
1808     for (int i=0; i<3; i++)
1809         this->ApexPoint[i] = this->Properties->position[i];
1810
1811     vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
1812     mapper->SetInput(sphereSource->GetOutput());
1813
1814     this->Properties->ApexPointActor->SetMapper(mapper);
1815     this->Properties->ApexPointActor->GetProperty()->SetColor(0,1,0);
1816
1817     this->GetMainRenderer()->AddActor(this->Properties->ApexPointActor);
1818     this->FlagDisplayApexPoint = 1;
1819
1820     if ( this->Properties->BasalPointActor != 0 )
1821     {
1822         this->CreateLongAxisActor();
1823         this->FlagLongAxis = 1;
1824         this->GetMainRenderer()->AddActor(this->Properties->LongAxisActor);
1825         this->FlagDisplayLongAxis = 1;
1826         this->pushButtonReslice->setEnabled(true);
1827     }
1828
1829     this->GetRenderWindow()->Render();
1830
1831 }
1832
1833
1834 void OpenHeartGui::CreateLongAxisActor()
1835 {
1836
1837     if ( this->Properties->LongAxisActor == 0 ) {
1838         this->Properties->LongAxisActor = vtkSmartPointer<vtkActor>::New();
1839     }
1840     else {
1841         this->GetMainRenderer()->RemoveActor(this->Properties->LongAxisActor);
1842     }
1843
1844     vtkSmartPointer<vtkLineSource> lineSource = vtkSmartPointer<vtkLineSource>::New();
1845     lineSource->SetPoint1(this->BasalPoint);
1846     lineSource->SetPoint2(this->ApexPoint);
1847     lineSource->Update();
1848
1849     vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
1850     mapper->SetInputConnection(lineSource->GetOutputPort());
1851
1852     this->Properties->LongAxisActor->SetMapper(mapper);
1853     this->Properties->LongAxisActor->GetProperty()->SetLineWidth(2);
1854     this->Properties->LongAxisActor->GetProperty()->SetColor(0,1,0);
1855
1856 }
1857
1858
1859 void OpenHeartGui::DisplayMainAxisManagement()
1860 {
1861
1862 }
1863
1864
1865 void OpenHeartGui::DisplayMeshManagement()
1866 {
1867
1868     if ( this->Properties->MeshActor != 0 )
1869     {
1870
1871         if ( this->FlagDisplayMesh == 0 )
1872         {
1873             this->GetMeshRenderer()->AddActor(this->Properties->MeshActor);
1874             this->FlagDisplayMesh = 1;
1875         }
1876         else
1877         {
1878             this->GetMeshRenderer()->RemoveActor(this->Properties->MeshActor);
1879             this->FlagDisplayMesh = 0;
1880         }
1881         this->GetRenderWindow()->Render();
1882
1883     }
1884
1885 }
1886
1887 void OpenHeartGui::DisplayModeManagement()
1888 {
1889
1890     if ( this->FlagDisplayText == 0 )
1891     {
1892
1893         this->FlagDisplayText = 1;
1894         if ( this->Properties->TextMapperPixel ) {
1895             this->Properties->TextMapperPixel->SetInput("Display on");
1896         }
1897         if ( this->Properties->TextMapperNumFrame ) {
1898             QString str;
1899             str.sprintf("f = %d",this->CurrentFrame);
1900             this->Properties->TextMapperNumFrame->SetInput(str.toStdString().c_str());
1901         }
1902         if ( this->Properties->TextMapperResolution ) {
1903             QString str;
1904             str.sprintf("Resolution: %.2f x %.2f x %.2f mm",this->ImageData->GetSpacing()[0]*1000,this->ImageData->GetSpacing()[1]*1000,this->ImageData->GetSpacing()[2]*1000);
1905             this->Properties->TextMapperResolution->SetInput(str.toStdString().c_str());
1906         }
1907         if ( this->Properties->TextMapperSlice ) {
1908             int slice = (int)( (this->Properties->position[1] - this->ImageData->GetOrigin()[1]) / this->ImageData->GetSpacing()[1] + 0.5f );
1909             QString strSlice;
1910             strSlice.sprintf("Slice: %d",slice);
1911             this->Properties->TextMapperSlice->SetInput(strSlice.toStdString().c_str());
1912         }
1913
1914         this->GetRenderWindow()->Render();
1915
1916     }
1917     else
1918     {
1919
1920         this->FlagDisplayText = 0;
1921         if ( this->Properties->TextMapperPixel ) {
1922             this->Properties->TextMapperPixel->SetInput("Display off");
1923         }
1924         if ( this->Properties->TextMapperNumFrame ) {
1925             this->Properties->TextMapperNumFrame->SetInput("");
1926         }
1927         if ( this->Properties->TextMapperResolution ) {
1928             this->Properties->TextMapperResolution->SetInput("");
1929         }
1930         if ( this->Properties->TextMapperSlice ) {
1931             this->Properties->TextMapperSlice->SetInput("");
1932         }
1933         if ( this->Properties->TextMapperMM ) {
1934             this->Properties->TextMapperMM->SetInput("");
1935         }
1936         if ( this->Properties->TextMapperValue ) {
1937             this->Properties->TextMapperValue->SetInput("");
1938         }
1939         this->GetRenderWindow()->Render();
1940
1941     }
1942
1943 }
1944
1945
1946 vtkActor2D* OpenHeartGui::AddFixedText(const char *text, float x, float y, float R,float G, float B, int Size)
1947 {
1948
1949     vtkTextMapper *Mapper = vtkTextMapper::New();
1950     vtkActor2D *Actor = vtkActor2D::New();
1951     Mapper->SetInput(text);
1952     Mapper->GetTextProperty()->SetColor(R, G, B);
1953     Mapper->GetTextProperty()->SetFontSize(Size);
1954     Mapper->GetTextProperty()->SetJustificationToLeft();
1955     Mapper->GetTextProperty()->ShadowOff();
1956     Actor->SetPosition(x, y);
1957     Actor->SetMapper(Mapper);
1958     return Actor;
1959
1960 }
1961
1962
1963 void OpenHeartGui::resizeEvent(QResizeEvent* event)
1964 {
1965     int sizeX = this->qVTK->GetRenderWindow()->GetSize()[0];
1966     int sizeY = this->qVTK->GetRenderWindow()->GetSize()[1];
1967     if ( (sizeX!=382) || (sizeY!=462) ) {
1968         this->Properties->TextActorSlice->SetPosition(10,this->GetRenderWindow()->GetSize()[1]-20);
1969         this->Properties->TextActorPixel->SetPosition(this->GetRenderWindow()->GetSize()[0]-10,this->GetRenderWindow()->GetSize()[1]-20);
1970         this->Properties->TextActorMM->SetPosition(this->GetRenderWindow()->GetSize()[0]-10,this->GetRenderWindow()->GetSize()[1]-45);
1971         this->Properties->TextActorValue->SetPosition(this->GetRenderWindow()->GetSize()[0]-10,this->GetRenderWindow()->GetSize()[1]-70);
1972         this->GetRenderWindow()->Render();
1973         QMainWindow::resizeEvent(event);
1974     }
1975 }
1976
1977
1978 void OpenHeartGui::HidePlanModeManagement()
1979 {
1980
1981     if ( this->FlagHidePlan == 0 )
1982     {
1983         this->FlagHidePlan = 1;
1984         this->Properties->xIPW->SetTextureVisibility(0);
1985         this->Properties->xIPW->GetPlaneProperty()->SetOpacity(0);
1986         this->Properties->yIPW->SetTextureVisibility(0);
1987         this->Properties->yIPW->GetPlaneProperty()->SetOpacity(0);
1988         this->Properties->zIPW->SetTextureVisibility(0);
1989         this->Properties->zIPW->GetPlaneProperty()->SetOpacity(0);
1990
1991         if ( (this->FlagDisplayMesh==0) && (this->FlagDisplayMeshContours==0) ) {
1992             this->GetMeshRenderer()->AddActor(this->Properties->MeshActor);
1993             this->FlagDisplayMesh = 1;
1994         }
1995         /*
1996         if ( this->FlagDisplayMeshContours == 1 ) {
1997             this->GetMeshRenderer()->RemoveActor(this->Properties->xCutActor);
1998             this->GetMeshRenderer()->RemoveActor(this->Properties->yCutActor);
1999             this->GetMeshRenderer()->RemoveActor(this->Properties->zCutActor);
2000             this->FlagDisplayMeshContours = 0;
2001         }
2002         */
2003         this->GetRenderWindow()->Render();
2004
2005     }
2006     else
2007     {
2008         if ( this->FlagDisplayMesh == 1 )
2009             this->GetMeshRenderer()->RemoveActor(this->Properties->MeshActor);
2010         if ( this->FlagDisplayMeshContours == 1 ) {
2011             this->GetMeshRenderer()->RemoveActor(this->Properties->xCutActor);
2012             this->GetMeshRenderer()->RemoveActor(this->Properties->yCutActor);
2013             this->GetMeshRenderer()->RemoveActor(this->Properties->zCutActor);
2014         }
2015         this->FlagHidePlan = 0;
2016
2017         switch (this->ViewButton) {
2018         case 0:  /// 3D view
2019             this->Properties->xIPW->SetTextureVisibility(1);
2020             this->Properties->xIPW->GetPlaneProperty()->SetOpacity(1);
2021             this->Properties->yIPW->SetTextureVisibility(1);
2022             this->Properties->yIPW->GetPlaneProperty()->SetOpacity(1);
2023             this->Properties->zIPW->SetTextureVisibility(1);
2024             this->Properties->zIPW->GetPlaneProperty()->SetOpacity(1);
2025             if ( this->FlagDisplayMeshContours == 1 ) {
2026                 this->GetMeshRenderer()->AddActor(this->Properties->xCutActor);
2027                 this->GetMeshRenderer()->AddActor(this->Properties->yCutActor);
2028                 this->GetMeshRenderer()->AddActor(this->Properties->zCutActor);
2029             }
2030             break;
2031         case 1:  /// XY view
2032             this->Properties->xIPW->SetTextureVisibility(1);
2033             this->Properties->xIPW->GetPlaneProperty()->SetOpacity(1);
2034             if ( this->FlagDisplayMeshContours == 1 ) {
2035                 this->GetMeshRenderer()->AddActor(this->Properties->xCutActor);
2036             }
2037             break;
2038         case 2:  /// XZ view
2039             this->Properties->yIPW->SetTextureVisibility(1);
2040             this->Properties->yIPW->GetPlaneProperty()->SetOpacity(1);
2041             if ( this->FlagDisplayMeshContours == 1 ) {
2042                 this->GetMeshRenderer()->AddActor(this->Properties->yCutActor);
2043             }
2044             break;
2045         case 3:  /// YZ view
2046             this->Properties->zIPW->SetTextureVisibility(1);
2047             this->Properties->zIPW->GetPlaneProperty()->SetOpacity(1);
2048             if ( this->FlagDisplayMeshContours == 1 ) {
2049                 this->GetMeshRenderer()->AddActor(this->Properties->zCutActor);
2050             }
2051             break;
2052         default:
2053             break;
2054         }
2055
2056         if ( this->FlagDisplayMesh == 1 )
2057             this->GetMeshRenderer()->AddActor(this->Properties->MeshActor);
2058         this->GetRenderWindow()->Render();
2059     }
2060
2061 }
2062
2063
2064 void OpenHeartGui::UpdateClinicalIndices()
2065 {
2066
2067     float EDV = 0;
2068     float ESV = 1000000;
2069     int NbElements = this->TableChart->GetNumberOfRows();
2070     for ( int k=0; k<NbElements; k++)
2071     {
2072         float val = this->TableChart->GetValue(k,1).ToFloat();
2073         if ( val > EDV )
2074             EDV = val;
2075         if ( val < ESV )
2076             ESV = val;
2077     }
2078     /// End Diastolic and End systolic volume
2079     QString strESV;
2080     strESV.sprintf("%2.1f ml",ESV);
2081     QString strEDV;
2082     strEDV.sprintf("%2.1f ml",EDV);
2083     this->labelESVValue->setText(strESV);
2084     this->labelEDVValue->setText(strEDV);
2085     /// Ejection fraction indice
2086     float EF = 100 * (EDV-ESV) / (EDV+1e-6);
2087     QString strEF;
2088     strEF.sprintf("%2.1f %%",EF);
2089     this->labelEFValue->setText(strEF);
2090     /// Stroke volume indice
2091     float SV = EDV-ESV;
2092     QString strSV;
2093     strSV.sprintf("%2.1f ml",SV);
2094     this->labelSVValue->setText(strSV);
2095
2096 }
2097
2098
2099 /// Custimize interface colors
2100 void OpenHeartGui::SetInterfaceColors()
2101 {
2102     this->tabMesh->setStyleSheet("background-color: rgb(0,0,0);");
2103     this->widgetXY->setStyleSheet("border-style: solid; border-width: 2px;  border-color: blue;");
2104     this->widgetXZ->setStyleSheet("border-style: solid; border-width: 2px;  border-color: yellow;");
2105     this->widgetYZ->setStyleSheet("border-style: solid; border-width: 2px;  border-color: red;");
2106 }
2107
2108
2109 void OpenHeartGui::slotReslice()
2110 {
2111
2112     if ( this->pushButtonReslice->isEnabled() )
2113     {
2114         if ( this->FlagReslice == 0 )
2115         {
2116             /// Reslice planes according to the main axis
2117             this->SetLongAxisView();
2118             /// Display off the Slice text actor
2119             this->GetMainRenderer()->RemoveActor(this->Properties->TextActorSlice);
2120             /// Replace Reslice text by Reset one into the push button
2121             this->pushButtonReslice->setText("Reset");
2122             /// Set corresponding flag to 1
2123             this->FlagReslice = 1;
2124         }
2125         else
2126         {
2127             /// Reset the reslicing operation
2128             this->ResetReslicing();
2129             /// Display on the Slice text actor
2130             this->GetMainRenderer()->AddActor(this->Properties->TextActorSlice);
2131             /// Replace Reslice text by Reset one into the push button
2132             this->pushButtonReslice->setText("Reslice");
2133             /// Set corresponding flag to 0
2134             this->FlagReslice = 0;
2135         }
2136
2137     }
2138
2139 }
2140
2141
2142 void OpenHeartGui::SetLongAxisView()
2143 {
2144
2145     /// Compute the rotation matrix between the Z-axis and the long axis of the heart
2146     this->ComputeRotationMatrix();
2147
2148     /// Set the corresponding vtkTransform object
2149     this->TransformViewOrientation->SetMatrix(this->RotationMatrix);
2150     this->TransformViewOrientationInv->SetMatrix(this->RotationMatrixInv);
2151
2152     /// Set the plans at the center of the volume
2153     double center[3];
2154     for ( int i=0; i<3; i++ )
2155         center[i] = 0.5*(this->ImageData->GetDimensions()[i])*(this->ImageData->GetSpacing()[i]);
2156     this->Properties->xIPW->SetSlicePosition(center[0]);
2157     this->Properties->yIPW->SetSlicePosition(center[1]);
2158     this->Properties->zIPW->SetSlicePosition(center[2]);
2159     this->Properties->yzIPW->SetSlicePosition(center[0]);
2160     this->Properties->xzIPW->SetSlicePosition(center[1]);
2161     this->Properties->xyIPW->SetSlicePosition(center[2]);
2162
2163     /////////////////////////////////////////////////
2164     /////////////////////////////////////////////////
2165     /////////////////////////////////////////////////
2166     /// Process XZ-plans
2167
2168     /// Apply the rotation to the points defining the cartesian plan of interest
2169     //double *cy = this->Properties->yIPW->GetCenter();
2170     double *pt1 = this->Properties->yIPW->GetPoint1();
2171     double *pt2 = this->Properties->yIPW->GetPoint2();
2172     double *pto = this->Properties->yIPW->GetOrigin();
2173     double newpt1[3];
2174     double newpt2[3];
2175     double newpto[3];
2176
2177     /// Do this to ensure that the center of the rotation corresponds to the center of the volume
2178     for (int i=0; i<3; i++) {
2179         pt1[i] -= center[i];
2180         pt2[i] -= center[i];
2181         pto[i] -= center[i];
2182     }
2183
2184     /// Apply transformation
2185     this->TransformViewOrientation->TransformPoint(pt1,newpt1);
2186     this->TransformViewOrientation->TransformPoint(pt2,newpt2);
2187     this->TransformViewOrientation->TransformPoint(pto,newpto);
2188     for (int i=0; i<3; i++) {
2189         newpt1[i] += center[i];
2190         newpt2[i] += center[i];
2191         newpto[i] += center[i];
2192     }
2193     ///
2194     this->Properties->yIPW->SetOrigin(newpto);
2195     this->Properties->yIPW->SetPoint1(newpt1);
2196     this->Properties->yIPW->SetPoint2(newpt2);
2197     this->Properties->yIPW->UpdatePlacement();
2198     ///
2199     this->Properties->xzIPW->SetOrigin(newpto);
2200     this->Properties->xzIPW->SetPoint1(newpt1);
2201     this->Properties->xzIPW->SetPoint2(newpt2);
2202     this->Properties->xzIPW->UpdatePlacement();
2203
2204
2205     /////////////////////////////////////////////////
2206     /////////////////////////////////////////////////
2207     /////////////////////////////////////////////////
2208     /// Process YZ-plans
2209
2210     pt1 = this->Properties->xIPW->GetPoint1();
2211     pt2 = this->Properties->xIPW->GetPoint2();
2212     pto = this->Properties->xIPW->GetOrigin();
2213
2214     /// Do this to ensure that the center of the rotation corresponds to the center of the volume
2215     for (int i=0; i<3; i++) {
2216         pt1[i] -= center[i];
2217         pt2[i] -= center[i];
2218         pto[i] -= center[i];
2219     }
2220
2221     /// Apply transformation
2222     this->TransformViewOrientation->TransformPoint(pt1,newpt1);
2223     this->TransformViewOrientation->TransformPoint(pt2,newpt2);
2224     this->TransformViewOrientation->TransformPoint(pto,newpto);
2225     for (int i=0; i<3; i++) {
2226         newpt1[i] += center[i];
2227         newpt2[i] += center[i];
2228         newpto[i] += center[i];
2229     }
2230     ///
2231     this->Properties->xIPW->SetOrigin(newpto);
2232     this->Properties->xIPW->SetPoint1(newpt1);
2233     this->Properties->xIPW->SetPoint2(newpt2);
2234     this->Properties->xIPW->UpdatePlacement();
2235     ///
2236     this->Properties->yzIPW->SetOrigin(newpto);
2237     this->Properties->yzIPW->SetPoint1(newpt1);
2238     this->Properties->yzIPW->SetPoint2(newpt2);
2239     this->Properties->yzIPW->UpdatePlacement();
2240
2241
2242     /////////////////////////////////////////////////
2243     /////////////////////////////////////////////////
2244     /////////////////////////////////////////////////
2245     /// Process XY-plans
2246
2247     pt1 = this->Properties->zIPW->GetPoint1();
2248     pt2 = this->Properties->zIPW->GetPoint2();
2249     pto = this->Properties->zIPW->GetOrigin();
2250
2251     /// Do this to ensure that the center of the rotation corresponds to the center of the volume
2252     for (int i=0; i<3; i++) {
2253         pt1[i] -= center[i];
2254         pt2[i] -= center[i];
2255         pto[i] -= center[i];
2256     }
2257
2258     /// Apply transformation
2259     this->TransformViewOrientation->TransformPoint(pt1,newpt1);
2260     this->TransformViewOrientation->TransformPoint(pt2,newpt2);
2261     this->TransformViewOrientation->TransformPoint(pto,newpto);
2262     for (int i=0; i<3; i++) {
2263         newpt1[i] += center[i];
2264         newpt2[i] += center[i];
2265         newpto[i] += center[i];
2266     }
2267     ///
2268     this->Properties->zIPW->SetOrigin(newpto);
2269     this->Properties->zIPW->SetPoint1(newpt1);
2270     this->Properties->zIPW->SetPoint2(newpt2);
2271     this->Properties->zIPW->UpdatePlacement();
2272     ///
2273     this->Properties->xyIPW->SetOrigin(newpto);
2274     this->Properties->xyIPW->SetPoint1(newpt1);
2275     this->Properties->xyIPW->SetPoint2(newpt2);
2276     this->Properties->xyIPW->UpdatePlacement();
2277
2278     /////////////////////////////////////////////////
2279     /////////////////////////////////////////////////
2280     /////////////////////////////////////////////////
2281     /// Final translation to match the Long axis
2282
2283     /// XZ plan translation
2284     double *ncy = this->Properties->yIPW->GetCenter();
2285     double t;
2286     double closest[3];
2287     vtkLine::DistanceToLine(ncy, this->BasalPoint, this->ApexPoint, t, closest);
2288     double offset = this->Properties->yIPW->GetSlicePosition() + (closest[1] - ncy[1]);
2289     this->Properties->yIPW->SetSlicePosition(offset);
2290     this->Properties->xzIPW->SetSlicePosition(offset);
2291
2292     /// YZ plan translation
2293     double *ncx = this->Properties->xIPW->GetCenter();
2294     vtkLine::DistanceToLine(ncx, this->BasalPoint, this->ApexPoint, t, closest);
2295     offset = this->Properties->xIPW->GetSlicePosition() + (closest[0] - ncx[0]);
2296     this->Properties->xIPW->SetSlicePosition(offset);
2297     this->Properties->yzIPW->SetSlicePosition(offset);
2298
2299     /// XY plan translation
2300     double *ncz = this->Properties->zIPW->GetCenter();
2301     double mid[3];
2302     for (int i=0; i<3; i++)
2303         mid[i] = this->BasalPoint[i] + 0.5 * (this->ApexPoint[i]-this->BasalPoint[i]);
2304     offset = this->Properties->zIPW->GetSlicePosition() + (mid[2] - ncz[2]);
2305     this->Properties->zIPW->SetSlicePosition(offset);
2306     this->Properties->xyIPW->SetSlicePosition(offset);
2307
2308     /// Update Properties->position to fit to the new position
2309     this->Properties->position[0] = this->Properties->xIPW->GetSlicePosition();
2310     this->Properties->position[1] = this->Properties->yIPW->GetSlicePosition();
2311     this->Properties->position[2] = this->Properties->zIPW->GetSlicePosition();
2312
2313
2314     /////////////////////////////////////////////////
2315     /////////////////////////////////////////////////
2316     /////////////////////////////////////////////////
2317     /// Update renderer
2318     this->UpdateViewer(0,this->ZoomLabel,this->RenXY);
2319     this->UpdateViewer(1,this->ZoomLabel,this->RenXZ);
2320     this->UpdateViewer(2,this->ZoomLabel,this->RenYZ);
2321     this->GetRenderWindow()->Render();
2322
2323 }
2324
2325
2326 /// Compute the rotation matrix between the Z-axis and the long axis of the heart
2327 void OpenHeartGui::ComputeRotationMatrix()
2328 {
2329
2330     double ZAxis[] = {0,0,1};
2331     double MainAxis[3];
2332     for (int i=0; i<3; i++)
2333         MainAxis[i] = this->BasalPoint[i] - this->ApexPoint[i];
2334     vtkMath::Normalize(MainAxis);
2335
2336     /// Compute rotation matrix between two vectors: MainAxis and ZAxis
2337     double normal1[3];
2338     double normal2[3];
2339     for (int i=0; i<3; i++) {
2340         normal1[i] = ZAxis[i];
2341         normal2[i] = MainAxis[i];
2342     }
2343
2344     double vec[3];
2345     vtkMath::Cross(normal1, normal2, vec);
2346     double costheta = vtkMath::Dot(normal1, normal2);
2347     double sintheta = vtkMath::Norm(vec);
2348     double theta = atan2(sintheta, costheta);
2349     if (sintheta != 0)
2350     {
2351         vec[0] /= sintheta;
2352         vec[1] /= sintheta;
2353         vec[2] /= sintheta;
2354     }
2355
2356     /// convert to quaternion
2357     costheta = cos(0.5*theta);
2358     sintheta = sin(0.5*theta);
2359     double quat[4];
2360     quat[0] = costheta;
2361     quat[1] = vec[0]*sintheta;
2362     quat[2] = vec[1]*sintheta;
2363     quat[3] = vec[2]*sintheta;
2364
2365     /// convert to matrix
2366     double mat[3][3];
2367     vtkMath::QuaternionToMatrix3x3(quat,mat);
2368
2369     /// Create corresponding 4x4 matrix
2370     this->RotationMatrix->Identity();
2371     this->RotationMatrixInv->Identity();
2372     for (unsigned int i = 0; i < 3; i++) {
2373         for (unsigned int j = 0; j < 3; j++) {
2374             this->RotationMatrix->SetElement(i, j, mat[i][j]);
2375             this->RotationMatrixInv->SetElement(i, j, mat[i][j]);
2376         }
2377     }
2378     this->RotationMatrixInv->Invert();
2379
2380 }
2381
2382
2383 /// Reset the reslicing operation
2384 void OpenHeartGui::ResetReslicing()
2385 {
2386
2387     /// Set the rotation matrix to identity
2388     this->RotationMatrix->Identity();
2389     this->RotationMatrixInv->Identity();
2390
2391     /// Set the corresponding vtkTransform object
2392     this->TransformViewOrientation->SetMatrix(this->RotationMatrix);
2393     this->TransformViewOrientationInv->SetMatrix(this->RotationMatrixInv);
2394
2395     /// Switch off the oblique orientation of each plan
2396     this->Properties->xIPW->SetPlaneOrientationToXAxes();
2397     this->Properties->yzIPW->SetPlaneOrientationToXAxes();
2398     this->Properties->yIPW->SetPlaneOrientationToYAxes();
2399     this->Properties->xzIPW->SetPlaneOrientationToYAxes();
2400     this->Properties->zIPW->SetPlaneOrientationToZAxes();
2401     this->Properties->xyIPW->SetPlaneOrientationToZAxes();
2402
2403     /// Set the plans at the center of the volume
2404     double center[3];
2405     for ( unsigned int k=0; k<3; k++ )
2406         center[k] = ((this->ImageData->GetDimensions()[k])*(this->ImageData->GetSpacing()[k]))/2;
2407
2408     this->Properties->xIPW->SetSlicePosition(center[0]);
2409     this->Properties->yzIPW->SetSlicePosition(center[0]);
2410     this->Properties->yIPW->SetSlicePosition(center[1]);
2411     this->Properties->xzIPW->SetSlicePosition(center[1]);
2412     this->Properties->zIPW->SetSlicePosition(center[2]);
2413     this->Properties->xyIPW->SetSlicePosition(center[2]);
2414
2415     /// Update Properties->position to fit to the new position
2416     this->Properties->position[0] = center[0];
2417     this->Properties->position[1] = center[1];
2418     this->Properties->position[2] = center[2];
2419
2420     /// Update renderer
2421     this->UpdateViewer(0,this->ZoomLabel,this->RenXY);
2422     this->UpdateViewer(1,this->ZoomLabel,this->RenXZ);
2423     this->UpdateViewer(2,this->ZoomLabel,this->RenYZ);
2424     this->GetRenderWindow()->Render();
2425
2426 }
2427
2428
2429 void OpenHeartGui::UpdateViewer(int view, double zoom, vtkRenderer *ren)
2430 {
2431
2432     /// Set Focal Point
2433     double center[3];
2434     for (int i=0; i<3; i++)
2435         center[i] = 0.5 * this->ImageData->GetDimensions()[i] * this->ImageData->GetSpacing()[i];
2436     ren->GetActiveCamera()->SetFocalPoint(center);
2437
2438     /// Set Position
2439     double position[3];
2440     double newPosition[3];
2441     switch (view)
2442     {
2443     case 0: /// XY view
2444         position[0] = 0.5 * this->ImageData->GetDimensions()[0] * this->ImageData->GetSpacing()[0];
2445         position[1] = 0.5 * this->ImageData->GetDimensions()[1] * this->ImageData->GetSpacing()[1];
2446         position[2] = 10  * this->ImageData->GetDimensions()[2] * this->ImageData->GetSpacing()[2];
2447         break;
2448     case 1: /// XZ view
2449         position[0] = 0.5 * this->ImageData->GetDimensions()[0] * this->ImageData->GetSpacing()[0];
2450         position[1] = 10  * this->ImageData->GetDimensions()[1] * this->ImageData->GetSpacing()[1];
2451         position[2] = 0.5 * this->ImageData->GetDimensions()[2] * this->ImageData->GetSpacing()[2];
2452         break;
2453     case 2: /// YZ view
2454         position[0] = 10  * this->ImageData->GetDimensions()[0] * this->ImageData->GetSpacing()[0];
2455         position[1] = 0.5 * this->ImageData->GetDimensions()[1] * this->ImageData->GetSpacing()[1];
2456         position[2] = 0.5 * this->ImageData->GetDimensions()[2] * this->ImageData->GetSpacing()[2];
2457     }
2458     for (int i=0; i<3; i++)
2459         position[i]  = position[i] - center[i];
2460     this->TransformViewOrientation->TransformPoint(position,newPosition);
2461     for (int i=0; i<3; i++)
2462         newPosition[i]  = newPosition[i] + center[i];
2463     ren->GetActiveCamera()->SetPosition(newPosition);
2464
2465     /// Set ViewUp
2466     double pt[] = {0,0,-1};
2467     double viewup[3];
2468     this->TransformViewOrientation->TransformPoint(pt,viewup);
2469     ren->GetActiveCamera()->SetViewUp(viewup);
2470     ren->ResetCamera();
2471     ren->GetActiveCamera()->Zoom(zoom);
2472     ren->GetRenderWindow()->Render();
2473
2474 }
2475
2476
2477 void OpenHeartGui::ComputePointBeforeRotation(double *position)
2478 {
2479
2480     double center[3];
2481     double newPosition[3];
2482     for (int i=0; i<3; i++)
2483         center[i] = 0.5 * this->ImageData->GetDimensions()[i] * this->ImageData->GetSpacing()[i];
2484
2485     for (int i=0; i<3; i++)
2486         position[i]  = position[i] - center[i];
2487     this->TransformViewOrientationInv->TransformPoint(position,newPosition);
2488     for (int i=0; i<3; i++)
2489         position[i]  = newPosition[i] + center[i];
2490
2491 }