]> Creatis software - clitk.git/blob - vv/vvSlicer.cxx
Fix for bug 1882
[clitk.git] / vv / vvSlicer.cxx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to:
5   - University of LYON              http://www.universite-lyon.fr/
6   - Léon Bérard cancer center       http://www.centreleonberard.fr
7   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
9   This software is distributed WITHOUT ANY WARRANTY; without even
10   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11   PURPOSE.  See the copyright notices for more information.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17   ===========================================================================**/
18
19 #include <QMessageBox>
20 #include <QString>
21
22 #include "vvSlicer.h"
23 #include "vvImage.h"
24 #include "vvSlicerManagerCommand.h"
25 #include "vvGlyphSource.h"
26 #include "vvGlyph2D.h"
27
28 #include <vtkTextProperty.h>
29 #include <vtkTextActor.h>
30 #include <vtkTextSource.h>
31 #include <vtkActor2D.h>
32 #include <vtkCursor2D.h>
33 #include <vtkPolyDataMapper2D.h>
34 #include <vtkProperty2D.h>
35 #include <vtkCornerAnnotation.h>
36 #include <vtkImageMapToWindowLevelColors.h>
37 #include <vtkImageData.h>
38 #include <vtkImageActor.h>
39 #include <vvBlendImageActor.h>
40 #include <vtkToolkits.h>
41 #include <vtkObjectFactory.h>
42 #include <vtkPointData.h>
43 #include <vtkDataArray.h>
44 #include <vtkFloatArray.h>
45 #include <vtkClipPolyData.h>
46 #include <vtkActor2DCollection.h>
47 #include <vtkGlyph3D.h>
48 #include <vtkMath.h>
49 #include <vtkCursor3D.h>
50 #include <vtkProperty.h>
51 #include <vtkLight.h>
52 #include <vtkLightCollection.h>
53 #include <vtkScalarBarActor.h>
54 #include <vtkLookupTable.h>
55
56 #include <vtkRenderer.h>
57 #include <vtkRendererCollection.h>
58 #include <vtkRenderWindow.h>
59 #include <vtkRenderWindowInteractor.h>
60 #include <vtkCamera.h>
61 #include <vtkCallbackCommand.h>
62 #include <vtkCommand.h>
63 #include <vtkPolyDataMapper.h>
64 #include <vtkBox.h>
65
66 #include <vtkExtractVOI.h>
67 #include <vtkSphereSource.h>
68 #include <vtkCutter.h>
69 #include <vtkAssignAttribute.h>
70 #include <vtkImageAccumulate.h>
71 #include <vtkImageReslice.h>
72 #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10)
73 #  include <vtkImageMapper3D.h>
74 #  include <vtkImageSliceMapper.h>
75 #endif
76
77 vtkCxxRevisionMacro(vvSlicer, "DummyRevision");
78 vtkStandardNewMacro(vvSlicer);
79 static void copyExtent(int* in, int* to){
80  for(int i=0; i<6; ++i) to[i]=in[i]; 
81 }
82 //------------------------------------------------------------------------------
83 vvSlicer::vvSlicer()
84 {
85         mFusionSequenceCode = -1;
86   this->UnInstallPipeline();
87   mImage = NULL;
88   mReducedExtent = new int[6];
89   mCurrentTSlice = 0;
90   mCurrentFusionTSlice = 0;
91   mCurrentOverlayTSlice = 0;
92   mUseReducedExtent = false;
93
94   mCurrent[0] = -VTK_DOUBLE_MAX;
95   mCurrent[1] = -VTK_DOUBLE_MAX;
96   mCurrent[2] = -VTK_DOUBLE_MAX;
97
98   mCursor[0] = 0;//-VTK_DOUBLE_MAX;
99   mCursor[1] = 0;//-VTK_DOUBLE_MAX;
100   mCursor[2] = 0;//-VTK_DOUBLE_MAX;
101   mCursor[3] = 0;//-VTK_DOUBLE_MAX;
102
103   mSubSampling = 5;
104   mScale = 1;
105   mVFLog = 0;
106   mVFWidth = 1;
107   mVFColor[0] = 0;
108   mVFColor[1] = 1;
109   mVFColor[2] = 0;
110
111   crossCursor = vtkSmartPointer<vtkCursor2D>::New();
112   crossCursor->AllOff();
113   crossCursor->AxesOn();
114   crossCursor->SetTranslationMode(1);
115   crossCursor->SetRadius(2);
116
117   pdm = vtkSmartPointer<vtkPolyDataMapper2D>::New();
118   pdm->SetInput(crossCursor->GetOutput());
119
120   pdmA = vtkSmartPointer<vtkActor2D>::New();
121   pdmA->SetMapper(pdm);
122   pdmA->GetProperty()->SetColor(255,10,212);
123   pdmA->SetVisibility(0);
124   pdmA->SetPickable(0);
125
126   ca = vtkSmartPointer<vtkCornerAnnotation>::New();
127   ca->GetTextProperty()->SetColor(255,10,212);
128   ca->SetVisibility(1);
129   mFileName = "";
130
131   mVF = NULL;
132   mOverlay = NULL;
133   mFusion = NULL;
134   mLandmarks = NULL;
135
136   legend = vtkSmartPointer<vtkScalarBarActor>::New();
137   //legend->SetTitle("test!");
138   legend->SetPosition(0.82,0.18);
139   legend->SetWidth(0.1);
140   legend->SetVisibility(0);
141   legend->SetLabelFormat("%.1f");
142   this->GetRenderer()->AddActor(legend);
143   showFusionLegend = false;
144
145   this->InstallPipeline();
146
147   mLinkOverlayWindowLevel = true;
148
149 #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10)
150   this->GetImageActor()->GetMapper()->BorderOn();
151 #endif
152
153   mSlicingTransform = vtkSmartPointer<vtkTransform>::New();
154   mConcatenatedTransform = vtkSmartPointer<vtkTransform>::New();
155   mConcatenatedFusionTransform = vtkSmartPointer<vtkTransform>::New();
156   mConcatenatedOverlayTransform = vtkSmartPointer<vtkTransform>::New();
157 }
158 //------------------------------------------------------------------------------
159
160
161 //------------------------------------------------------------------------------
162 vtkImageMapToWindowLevelColors* vvSlicer::GetOverlayMapper()
163 {
164   return mOverlayMapper.GetPointer();
165 }
166 //------------------------------------------------------------------------------
167
168
169 //------------------------------------------------------------------------------
170 vvBlendImageActor* vvSlicer::GetOverlayActor()
171 {
172   return mOverlayActor.GetPointer();
173 }
174 //------------------------------------------------------------------------------
175
176
177 //------------------------------------------------------------------------------
178 vtkImageMapToColors* vvSlicer::GetFusionMapper()
179 {
180   return mFusionMapper.GetPointer();
181 }
182 //------------------------------------------------------------------------------
183
184
185 //------------------------------------------------------------------------------
186 vtkImageActor* vvSlicer::GetFusionActor()
187 {
188   return mFusionActor.GetPointer();
189 }
190 //------------------------------------------------------------------------------
191
192
193 //------------------------------------------------------------------------------
194 vtkActor* vvSlicer::GetVFActor()
195 {
196   return mVFActor.GetPointer();
197 }
198 //------------------------------------------------------------------------------
199
200
201 //------------------------------------------------------------------------------
202 vtkCornerAnnotation* vvSlicer::GetAnnotation()
203 {
204   return ca.GetPointer();
205 }
206 //------------------------------------------------------------------------------
207
208
209 //------------------------------------------------------------------------------
210 void vvSlicer::EnableReducedExtent(bool b)
211 {
212   mUseReducedExtent = b;
213 }
214 //------------------------------------------------------------------------------
215
216
217 //------------------------------------------------------------------------------
218 void vvSlicer::SetReducedExtent(int * ext)
219 {
220   copyExtent(ext, mReducedExtent);
221 }
222 //------------------------------------------------------------------------------
223
224
225 //------------------------------------------------------------------------------
226 void vvSlicer::AddContour(vvMesh::Pointer contour,bool propagate)
227 {
228
229   mSurfaceCutActors.push_back(new vvMeshActor());
230   if (propagate)
231     mSurfaceCutActors.back()->Init(contour,mCurrentTSlice,mVF);
232   else
233     mSurfaceCutActors.back()->Init(contour,mCurrentTSlice);
234   mSurfaceCutActors.back()->SetSlicingOrientation(SliceOrientation);
235   this->GetRenderer()->AddActor(mSurfaceCutActors.back()->GetActor());
236
237   SetContourSlice();
238 }
239 //------------------------------------------------------------------------------
240
241
242 //------------------------------------------------------------------------------
243 void vvSlicer::ToggleContourSuperposition()
244 {
245   for (std::vector<vvMeshActor*>::iterator i=mSurfaceCutActors.begin();
246        i!=mSurfaceCutActors.end(); i++)
247     (*i)->ToggleSuperposition();
248 }
249 //------------------------------------------------------------------------------
250
251
252 //------------------------------------------------------------------------------
253 void vvSlicer::SetCursorColor(int r,int g, int b)
254 {
255   pdmA->GetProperty()->SetColor(r,g,b);
256 }
257 //------------------------------------------------------------------------------
258
259
260 //------------------------------------------------------------------------------
261 void vvSlicer::SetCursorVisibility(bool s)
262 {
263   pdmA->SetVisibility(s);
264 }
265 //------------------------------------------------------------------------------
266
267
268 //------------------------------------------------------------------------------
269 bool vvSlicer::GetCursorVisibility()
270 {
271   return pdmA->GetVisibility();
272 }
273 //------------------------------------------------------------------------------
274
275
276 //------------------------------------------------------------------------------
277 void vvSlicer::SetCornerAnnotationVisibility(bool s)
278 {
279   ca->SetVisibility(s);
280 }
281 //------------------------------------------------------------------------------
282
283
284 //------------------------------------------------------------------------------
285 bool vvSlicer::GetCornerAnnotationVisibility()
286 {
287   return ca->GetVisibility();
288 }
289 //------------------------------------------------------------------------------
290
291
292 //------------------------------------------------------------------------------
293 vvSlicer::~vvSlicer()
294 {
295   for (std::vector<vvMeshActor*>::iterator i=mSurfaceCutActors.begin();
296        i!=mSurfaceCutActors.end(); i++)
297     delete (*i);
298   delete [] mReducedExtent;
299 }
300 //------------------------------------------------------------------------------
301
302 //------------------------------------------------------------------------------
303 double* vvSlicer::GetCurrentPosition()
304 {
305   return mCurrentBeforeSlicingTransform;
306 }
307 //------------------------------------------------------------------------------
308
309 //------------------------------------------------------------------------------
310 void vvSlicer::SetCurrentPosition(double x, double y, double z, int t)
311 {
312   mCurrentBeforeSlicingTransform[0]=x;
313   mCurrentBeforeSlicingTransform[1]=y;
314   mCurrentBeforeSlicingTransform[2]=z;
315   mSlicingTransform->GetInverse()->TransformPoint(mCurrentBeforeSlicingTransform,mCurrent);
316   if (t>=0) SetTSlice(t);
317 }
318 //------------------------------------------------------------------------------
319
320
321 //------------------------------------------------------------------------------
322 void vvSlicer::SetImage(vvImage::Pointer image)
323 {
324   if (image->GetVTKImages().size()) {
325     mImage = image;
326
327     if (!mImageReslice) {
328       mImageReslice = vtkSmartPointer<vtkImageReslice>::New();
329       mImageReslice->SetInterpolationModeToLinear();
330       mImageReslice->AutoCropOutputOn();
331       mImageReslice->SetBackgroundColor(-1000,-1000,-1000,1);
332     }
333
334     mConcatenatedTransform->Identity();
335     mConcatenatedTransform->Concatenate(mImage->GetTransform()[0]);
336     mConcatenatedTransform->Concatenate(mSlicingTransform);
337     mImageReslice->SetResliceTransform(mConcatenatedTransform);
338     mImageReslice->SetInput(0, mImage->GetFirstVTKImageData());
339     mImageReslice->UpdateInformation();
340
341     this->Superclass::SetInput(mImageReslice->GetOutput());
342
343     int extent[6];
344     this->GetInput()->GetWholeExtent(extent);
345
346     // Prevent crash when reload -> change slice if outside extent
347     if (Slice < extent[SliceOrientation*2] || Slice>=extent[SliceOrientation*2+1]) {
348       Slice = (extent[SliceOrientation*2+1]+extent[SliceOrientation*2])/2.0;
349     }
350
351     // Make sure that the required part image has been computed
352     extent[SliceOrientation*2] = Slice;
353     extent[SliceOrientation*2+1] = Slice;
354     mImageReslice->GetOutput()->SetUpdateExtent(extent);
355     mImageReslice->GetOutput()->Update();
356
357     this->UpdateDisplayExtent();
358
359     mCurrentTSlice = 0;
360     ca->SetText(0,mFileName.c_str());
361   }
362 }
363 //------------------------------------------------------------------------------
364
365
366 //------------------------------------------------------------------------------
367 void vvSlicer::SetOverlay(vvImage::Pointer overlay)
368 {
369   if (overlay->GetVTKImages().size()) {
370     mOverlay = overlay;
371     
372     if (!mOverlayReslice) {
373       mOverlayReslice = vtkSmartPointer<vtkImageReslice>::New();
374       mOverlayReslice->SetInterpolationModeToLinear();
375       mOverlayReslice->AutoCropOutputOn();
376       mOverlayReslice->SetBackgroundColor(-1000,-1000,-1000,1);
377     }
378
379     mConcatenatedOverlayTransform->Identity();
380     mConcatenatedOverlayTransform->Concatenate(mOverlay->GetTransform()[0]);
381     mConcatenatedOverlayTransform->Concatenate(mSlicingTransform);
382     mOverlayReslice->SetResliceTransform(mConcatenatedOverlayTransform);
383     mOverlayReslice->SetInput(0, mOverlay->GetFirstVTKImageData());
384     mImageReslice->UpdateInformation();
385
386     if (!mOverlayMapper)
387       mOverlayMapper = vtkSmartPointer<vtkImageMapToWindowLevelColors>::New();
388     mOverlayMapper->SetInput(mOverlayReslice->GetOutput());
389
390     if (!mOverlayActor) {
391       mOverlayActor = vtkSmartPointer<vvBlendImageActor>::New();
392       mOverlayActor->SetInput(mOverlayMapper->GetOutput());
393       mOverlayActor->SetPickable(0);
394       mOverlayActor->SetVisibility(true);
395       mOverlayActor->SetOpacity(0.5);
396 #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10)
397       mOverlayActor->GetMapper()->BorderOn();
398 #endif
399       }
400
401     //stupid but necessary : the Overlay need to be rendered before fusion
402     if (mFusionActor) {
403       this->GetRenderer()->RemoveActor(mFusionActor);
404       this->GetRenderer()->AddActor(mOverlayActor);
405       this->GetRenderer()->AddActor(mFusionActor);
406     } else
407       this->GetRenderer()->AddActor(mOverlayActor);
408
409     //Synchronize orientation and slice
410     AdjustResliceToSliceOrientation(mOverlayReslice);
411     this->UpdateDisplayExtent();
412     this->SetTSlice(mCurrentTSlice);
413   }
414 }
415 //------------------------------------------------------------------------------
416
417
418 //------------------------------------------------------------------------------
419 void vvSlicer::SetFusion(vvImage::Pointer fusion, int fusionSequenceCode)
420 {
421         mFusionSequenceCode = fusionSequenceCode;
422   if (fusion->GetVTKImages().size()) {
423     mFusion = fusion;
424
425     if (!mFusionReslice) {
426       mFusionReslice = vtkSmartPointer<vtkImageReslice>::New();
427       mFusionReslice->SetInterpolationModeToLinear();
428       mFusionReslice->AutoCropOutputOn();
429       mFusionReslice->SetBackgroundColor(-1000,-1000,-1000,1);
430     }
431
432     mConcatenatedFusionTransform->Identity();
433     mConcatenatedFusionTransform->Concatenate(mFusion->GetTransform()[0]);
434     mConcatenatedFusionTransform->Concatenate(mSlicingTransform);
435     mFusionReslice->SetResliceTransform(mConcatenatedFusionTransform);
436     mFusionReslice->SetInput(0, mFusion->GetFirstVTKImageData());
437     mFusionReslice->UpdateInformation();
438
439     if (!mFusionMapper)
440       mFusionMapper = vtkSmartPointer<vtkImageMapToColors>::New();
441
442     vtkSmartPointer<vtkLookupTable> lut = vtkLookupTable::New();
443     lut->SetRange(0, 1);
444     lut->SetValueRange(0, 1);
445     lut->SetSaturationRange(0, 0);
446     lut->Build();
447     mFusionMapper->SetLookupTable(lut);
448     mFusionMapper->SetInput(mFusionReslice->GetOutput());
449
450     if (!mFusionActor) {
451       mFusionActor = vtkSmartPointer<vtkImageActor>::New();
452       mFusionActor->SetInput(mFusionMapper->GetOutput());
453       mFusionActor->SetPickable(0);
454       mFusionActor->SetVisibility(true);
455       mFusionActor->SetOpacity(0.7);
456 #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10)
457       mFusionActor->GetMapper()->BorderOn();
458 #endif
459       this->GetRenderer()->AddActor(mFusionActor);
460     }
461
462     //Synchronize orientation and slice
463     AdjustResliceToSliceOrientation(mFusionReslice);
464     this->UpdateDisplayExtent();
465     this->SetTSlice(mCurrentTSlice);
466   }
467 }
468 //------------------------------------------------------------------------------
469
470
471 //------------------------------------------------------------------------------
472 bool vvSlicer::GetActorVisibility(const std::string& actor_type, int overlay_index)
473 {
474   bool vis = false;
475   if (actor_type == "image") {
476     vis = this->ImageActor->GetVisibility();
477   }
478   else if (actor_type == "vector") {
479     vis = this->mVFActor->GetVisibility();
480   }
481   else if (actor_type == "overlay") {
482     vis = this->mOverlayActor->GetVisibility();
483   }
484   else if ( (actor_type == "fusion") || (actor_type == "fusionSequence") ){
485     vis = this->mFusionActor->GetVisibility();
486   }
487   else if (actor_type == "contour")
488     vis = this->mSurfaceCutActors[overlay_index]->GetActor()->GetVisibility();
489
490   return vis;
491 }
492 //------------------------------------------------------------------------------
493
494 //------------------------------------------------------------------------------
495 void vvSlicer::SetActorVisibility(const std::string& actor_type, int overlay_index ,bool vis)
496 {
497   if (actor_type == "image") {
498     this->ImageActor->SetVisibility(vis);
499   }
500   else if (actor_type == "vector") {
501     this->mVFActor->SetVisibility(vis);
502   }
503   else if (actor_type == "overlay") {
504     this->mOverlayActor->SetVisibility(vis);
505   }
506   else if ( (actor_type == "fusion") || (actor_type == "fusionSequence") ){
507     this->mFusionActor->SetVisibility(vis);
508   }
509   else if (actor_type == "contour")
510     this->mSurfaceCutActors[overlay_index]->GetActor()->SetVisibility(vis);
511   UpdateDisplayExtent();
512 }
513 //------------------------------------------------------------------------------
514
515 //------------------------------------------------------------------------------
516 void vvSlicer::SetVF(vvImage::Pointer vf)
517 {
518   if (vf->GetVTKImages().size()) {
519     mVF = vf;
520
521     if (!mAAFilter) {
522       mAAFilter= vtkSmartPointer<vtkAssignAttribute>::New();
523       mVOIFilter = vtkSmartPointer<vtkExtractVOI>::New();
524       mVOIFilter->SetSampleRate(mSubSampling,mSubSampling,mSubSampling);
525     }
526     mVOIFilter->SetInput(vf->GetFirstVTKImageData());
527     mAAFilter->SetInput(mVOIFilter->GetOutput());
528     ///This tells VTK to use the scalar (pixel) data of the image to draw the little arrows
529     mAAFilter->Assign(vtkDataSetAttributes::SCALARS, vtkDataSetAttributes::VECTORS, vtkAssignAttribute::POINT_DATA);
530
531     if (!mArrow)
532       mArrow = vtkSmartPointer<vvGlyphSource>::New();
533     mArrow->SetGlyphTypeToSpecificArrow();
534     mArrow->SetScale(mScale);
535     mArrow->FilledOff();
536
537     // Glyph the gradient vector (with arrows)
538     if (!mGlyphFilter)
539       mGlyphFilter = vtkSmartPointer<vvGlyph2D>::New();
540     mGlyphFilter->SetInput(mAAFilter->GetOutput());
541     mGlyphFilter->SetSource(mArrow->GetOutput());
542     mGlyphFilter->ScalingOn();
543     mGlyphFilter->SetScaleModeToScaleByVector();
544     mGlyphFilter->OrientOn();
545     mGlyphFilter->SetVectorModeToUseVector();
546     mGlyphFilter->SetColorModeToColorByVector();
547
548     if (!mVFColorLUT)
549       mVFColorLUT = vtkSmartPointer<vtkLookupTable>::New();
550
551     double mVFColorHSV[3];
552     vtkMath::RGBToHSV(mVFColor, mVFColorHSV);
553     mVFColorLUT->SetHueRange(mVFColorHSV[0], mVFColorHSV[0]);
554     mVFColorLUT->SetSaturationRange(mVFColorHSV[1],mVFColorHSV[1]);
555     mVFColorLUT->SetValueRange(mVFColorHSV[2], mVFColorHSV[2]);
556
557     if (!mVFMapper)
558       mVFMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
559     mVFMapper->SetInput(mGlyphFilter->GetOutput());
560     mVFMapper->ImmediateModeRenderingOn();
561     mVFMapper->SetLookupTable(mVFColorLUT);
562
563     if (!mVFActor)
564       mVFActor = vtkSmartPointer<vtkActor>::New();
565     mVFActor->SetMapper(mVFMapper);
566     mVFActor->SetPickable(0);
567     mVFActor->GetProperty()->SetLineWidth(mVFWidth);
568     this->UpdateDisplayExtent();
569     this->GetRenderer()->AddActor(mVFActor);
570
571     //Synchronize slice
572     SetTSlice(mCurrentTSlice);
573   }
574 }
575 //------------------------------------------------------------------------------
576
577
578 //------------------------------------------------------------------------------
579 void vvSlicer::SetLandmarks(vvLandmarks* landmarks)
580 {
581   mLandmarks = landmarks;
582   if (landmarks) {
583
584     if (!mCross)
585       mCross = vtkSmartPointer<vtkCursor3D>::New();
586         if (!mClipBox)
587       mClipBox = vtkSmartPointer<vtkBox>::New();
588     if (!mLandClipper)
589       mLandClipper = vtkSmartPointer<vvClipPolyData>::New();
590     if (!mLandGlyph)
591       mLandGlyph = vtkSmartPointer<vtkGlyph3D>::New();
592     if (!mLandMapper)
593       mLandMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
594     if (!mLandActor)
595       mLandActor = vtkSmartPointer<vtkActor>::New();
596
597     mCross->SetFocalPoint(0.0,0.0,0.0);
598     mCross->SetModelBounds(-10,10,-10,10,-10,10);
599     mCross->AllOff();
600     mCross->AxesOn();
601
602     mLandClipper->SetClipFunction(mClipBox);
603     mLandClipper->InsideOutOn();
604     mLandClipper->SetInput(mLandmarks->GetOutput());
605
606     mLandGlyph->SetSource(mCross->GetOutput());
607     mLandGlyph->SetInput(mLandClipper->GetOutput());
608     //mLandGlyph->SetIndexModeToScalar();
609     //mLandGlyph->SetRange(0,1);
610     //mLandGlyph->ScalingOff();
611
612     //mLandGlyph->SetColorModeToColorByScalar();
613     
614     mLandGlyph->SetScaleModeToDataScalingOff();
615     mLandGlyph->SetIndexModeToOff();
616
617     mLandMapper->SetInputConnection(mLandGlyph->GetOutputPort());
618     //mLandMapper->ScalarVisibilityOff();
619
620     mLandActor->SetMapper(mLandMapper);
621     mLandActor->GetProperty()->SetColor(255,10,212);
622     mLandActor->SetPickable(0);
623     mLandActor->SetVisibility(true);
624     this->UpdateDisplayExtent();
625     this->GetRenderer()->AddActor(mLandActor);
626   }
627 }
628 //------------------------------------------------------------------------------
629
630 //------------------------------------------------------------------------------
631 //FIXME: this function leaks memory, we should fix it someday :)
632 void vvSlicer::RemoveActor(const std::string& actor_type, int overlay_index)
633 {
634   if (actor_type == "vector") {
635     Renderer->RemoveActor(mVFActor);
636     mGlyphFilter=NULL;
637     mVF = NULL;
638     mArrow = NULL;
639     mAAFilter=NULL;
640     mVOIFilter = NULL;
641     mVFMapper = NULL;
642     mVFActor = NULL;
643   }
644   if (actor_type == "overlay") {
645     Renderer->RemoveActor(mOverlayActor);
646     mOverlay = NULL;
647     mOverlayActor = NULL;
648     mOverlayMapper = NULL;
649   }
650   if ( (actor_type == "fusion") || (actor_type == "fusionSequence") ) {
651     Renderer->RemoveActor(mFusionActor);
652     mFusion = NULL;
653     mFusionActor = NULL;
654     mFusionMapper = NULL;
655   }
656   if (actor_type == "contour") {
657     Renderer->RemoveActor(this->mSurfaceCutActors[overlay_index]->GetActor());
658     mSurfaceCutActors.erase(mSurfaceCutActors.begin()+overlay_index);
659   }
660 }
661 //------------------------------------------------------------------------------
662
663
664 //------------------------------------------------------------------------------
665 void vvSlicer::SetVFSubSampling(int sub)
666 {
667   if (mVOIFilter) {
668     mVOIFilter->SetSampleRate(mSubSampling,mSubSampling,mSubSampling);
669     mSubSampling = sub;
670   }
671   UpdateDisplayExtent();
672   Render();
673 }
674 //------------------------------------------------------------------------------
675
676
677 //------------------------------------------------------------------------------
678 void vvSlicer::SetVFScale(int scale)
679 {
680   mScale = scale;
681   if (mArrow)
682     mArrow->SetScale(mScale);
683   UpdateDisplayExtent();
684   Render();
685 }
686 //------------------------------------------------------------------------------
687
688 //------------------------------------------------------------------------------
689 void vvSlicer::SetVFWidth(int width)
690 {
691   mVFWidth = width;
692   if (mVFActor)
693     mVFActor->GetProperty()->SetLineWidth(mVFWidth);
694   UpdateDisplayExtent();
695   Render();
696 }
697 //------------------------------------------------------------------------------
698
699
700 //------------------------------------------------------------------------------
701 void vvSlicer::SetVFLog(int log)
702 {
703   mVFLog = log;
704   if (mGlyphFilter) {
705     mGlyphFilter->SetUseLog(mVFLog);
706     mGlyphFilter->Modified();
707   }
708   UpdateDisplayExtent();
709   Render();
710 }
711 //------------------------------------------------------------------------------
712
713
714 //------------------------------------------------------------------------------
715 void vvSlicer::SetTSlice(int t, bool updateLinkedImages)
716 {
717         if (!updateLinkedImages) {
718                 mCurrentTSlice = t;
719                 mImageReslice->SetInput( mImage->GetVTKImages()[mCurrentTSlice] );
720                 // Update transform
721                 mConcatenatedTransform->Identity();
722                 mConcatenatedTransform->Concatenate(mImage->GetTransform()[mCurrentTSlice]);
723                 mConcatenatedTransform->Concatenate(mSlicingTransform);
724                 UpdateDisplayExtent();
725                 return;
726         }
727
728   if (t < 0)
729     mCurrentTSlice = 0;
730   else if ((unsigned int)t >= mImage->GetVTKImages().size())
731     mCurrentTSlice = mImage->GetVTKImages().size() -1;
732   else
733     mCurrentTSlice = t;
734
735   // Update transform
736   mConcatenatedTransform->Identity();
737   mConcatenatedTransform->Concatenate(mImage->GetTransform()[mCurrentTSlice]);
738   mConcatenatedTransform->Concatenate(mSlicingTransform);
739
740   // Update image data
741   mImageReslice->SetInput( mImage->GetVTKImages()[mCurrentTSlice] );
742   if (mVF && mVFActor->GetVisibility()) {
743     if (mVF->GetVTKImages().size() > (unsigned int)mCurrentTSlice)
744       mVOIFilter->SetInput(mVF->GetVTKImages()[mCurrentTSlice]);
745   }
746   //update the overlay
747   if (mOverlay && mOverlayActor->GetVisibility()) {
748     if (mOverlay->GetVTKImages().size() > (unsigned int)t) {
749       mCurrentOverlayTSlice = t;
750       mOverlayReslice->SetInput( mOverlay->GetVTKImages()[mCurrentOverlayTSlice] );
751
752       // Update overlay transform
753       mConcatenatedOverlayTransform->Identity();
754       mConcatenatedOverlayTransform->Concatenate(mOverlay->GetTransform()[mCurrentOverlayTSlice]);
755       mConcatenatedOverlayTransform->Concatenate(mSlicingTransform);
756     }
757   }
758   //update the fusion ; except in case this is a fusionSequence, in which case both 'times' should be independent.
759   if (mFusion && mFusionActor->GetVisibility() && (mFusionSequenceCode<0)) {
760     if (mFusion->GetVTKImages().size() > (unsigned int)t) {
761       mCurrentFusionTSlice = t;
762       mFusionReslice->SetInput( mFusion->GetVTKImages()[mCurrentFusionTSlice]);
763
764       // Update fusion transform
765       mConcatenatedFusionTransform->Identity();
766       mConcatenatedFusionTransform->Concatenate(mFusion->GetTransform()[mCurrentFusionTSlice]);
767       mConcatenatedFusionTransform->Concatenate(mSlicingTransform);
768     }
769   }
770   if (mSurfaceCutActors.size() > 0)
771     for (std::vector<vvMeshActor*>::iterator i=mSurfaceCutActors.begin();
772          i!=mSurfaceCutActors.end(); i++)
773       (*i)->SetTimeSlice(mCurrentTSlice);
774   UpdateDisplayExtent();
775 }
776 //------------------------------------------------------------------------------
777
778
779 //------------------------------------------------------------------------------
780 void vvSlicer::SetFusionSequenceTSlice(int t)
781 {
782   if (mFusion && mFusionActor->GetVisibility() && (mFusionSequenceCode>=0)) {
783     if (mFusion->GetVTKImages().size() > (unsigned int)t) {
784       mCurrentFusionTSlice = t;
785       mFusionReslice->SetInput( mFusion->GetVTKImages()[mCurrentFusionTSlice] );
786       // Update fusion transform
787       mConcatenatedFusionTransform->Identity();
788       mConcatenatedFusionTransform->Concatenate(mFusion->GetTransform()[mCurrentFusionTSlice]); //not really useful...
789       mConcatenatedFusionTransform->Concatenate(mSlicingTransform);
790     }
791   }
792
793   UpdateDisplayExtent();
794 }
795 //------------------------------------------------------------------------------
796
797
798 //------------------------------------------------------------------------------
799 int vvSlicer::GetTSlice()
800 {
801   return mCurrentTSlice;
802 }
803 //------------------------------------------------------------------------------
804
805 //------------------------------------------------------------------------------
806 int vvSlicer::GetMaxCurrentTSlice()
807 {
808   int t = mCurrentTSlice;
809   if(mOverlay)
810     t = std::max(t, mCurrentOverlayTSlice);
811   if(mFusion&& (mFusionSequenceCode<0)) //ignore fusionSequence data: for these, the times are not to be related (this way)
812     t = std::max(t, mCurrentFusionTSlice);
813   return t;
814 }
815 //------------------------------------------------------------------------------
816
817 //------------------------------------------------------------------------------
818 int vvSlicer::GetFusionTSlice()
819 {
820   return mCurrentFusionTSlice;
821 }
822 //------------------------------------------------------------------------------
823
824 //------------------------------------------------------------------------------
825 int vvSlicer::GetOverlayTSlice()
826 {
827   return mCurrentOverlayTSlice;
828 }
829 //------------------------------------------------------------------------------
830
831 //------------------------------------------------------------------------------
832 void vvSlicer::SetSliceOrientation(int orientation)
833 {
834   //if 2D image, force to watch in Axial View
835   int extent[6];
836   this->GetInput()->GetWholeExtent(extent);
837   if (extent[5]-extent[4] <= 2)
838     orientation = vtkImageViewer2::SLICE_ORIENTATION_XY;
839
840   if (orientation < vtkImageViewer2::SLICE_ORIENTATION_YZ ||
841       orientation > vtkImageViewer2::SLICE_ORIENTATION_XY) {
842     vtkErrorMacro("Error - invalid slice orientation " << orientation);
843     return;
844   }
845   
846   this->SliceOrientation = orientation;
847
848   if(mFusion)
849     AdjustResliceToSliceOrientation(mFusionReslice);
850
851   if(mOverlay)
852     AdjustResliceToSliceOrientation(mOverlayReslice);
853
854   // Update the viewer
855   
856   // Go to current cursor position
857   // double* cursorPos = GetCursorPosition();
858   // DDV(cursorPos, 3);
859   // SetCurrentPosition(cursorPos[0],cursorPos[1],cursorPos[2],cursorPos[3]);
860
861   if (this->Renderer && this->GetInput()) {
862     double s = mCursor[orientation];
863     double sCursor = (s - this->GetInput()->GetOrigin()[orientation])/this->GetInput()->GetSpacing()[orientation];
864     this->Slice = static_cast<int>(sCursor);
865   }
866   
867 //   int *range = this->GetSliceRange();
868 //   if (range)
869 //     this->Slice = static_cast<int>((range[0] + range[1]) * 0.5);
870
871   this->UpdateOrientation();
872   this->UpdateDisplayExtent();
873
874   if (this->Renderer && this->GetInput()) {
875     double scale = this->Renderer->GetActiveCamera()->GetParallelScale();
876     this->Renderer->ResetCamera();
877     this->Renderer->GetActiveCamera()->SetParallelScale(scale);
878   }
879
880   SetContourSlice();
881 }
882 //----------------------------------------------------------------------------
883
884 //------------------------------------------------------------------------------
885 // This function ensures that we sample the slices of a vtkImageReslice filter
886 // in the direction of the slicer (SliceOrientation) similarly as mImageReslice.
887 // In other words, we change the grid of the reslice in the same way as the grid
888 // of the displayed image in the slicing direction.
889 void vvSlicer::AdjustResliceToSliceOrientation(vtkImageReslice *reslice)
890 {
891   // Reset autocrop and update output information
892   reslice->SetOutputOriginToDefault();
893   reslice->SetOutputSpacingToDefault();
894   reslice->GetOutput()->UpdateInformation();
895
896   // Ge new origin / spacing
897   double origin[3];
898   double spacing[3];
899   reslice->GetOutput()->GetOrigin(origin);
900   reslice->GetOutput()->GetSpacing(spacing);
901
902   // Use similar spacing as the image in the direction SliceOrientation
903   spacing[this->SliceOrientation] = mImageReslice->GetOutput()->GetSpacing()[this->SliceOrientation];
904
905   // Modify origin to be on the image grid in the direction SliceOrientation in 3 steps
906   // Step 1: from world coordinates to image coordinates
907   origin[this->SliceOrientation] -= mImageReslice->GetOutput()->GetOrigin()[this->SliceOrientation];
908   origin[this->SliceOrientation] /= mImageReslice->GetOutput()->GetSpacing()[this->SliceOrientation];
909   // Step 2: round to superior grid positionInc
910   origin[this->SliceOrientation] = itk::Math::Ceil<double>(origin[this->SliceOrientation]);
911   // Step 3: back to world coordinates
912   origin[this->SliceOrientation] *= mImageReslice->GetOutput()->GetSpacing()[this->SliceOrientation];
913   origin[this->SliceOrientation] += mImageReslice->GetOutput()->GetOrigin()[this->SliceOrientation];
914
915   // Set new spacing and origin
916   reslice->SetOutputOrigin(origin);
917   reslice->SetOutputSpacing(spacing);
918   reslice->UpdateInformation();
919   reslice->GetOutput()->UpdateInformation();
920 }
921 //------------------------------------------------------------------------------
922
923 //----------------------------------------------------------------------------
924 int * vvSlicer::GetExtent(){
925   int *w_ext;
926   if (mUseReducedExtent) {
927     w_ext = mReducedExtent;
928   } else w_ext = GetInput()->GetWholeExtent();
929   return w_ext;
930 }
931 //----------------------------------------------------------------------------
932
933
934 //----------------------------------------------------------------------------
935 int vvSlicer::GetOrientation()
936 {
937   return this->SliceOrientation;
938 }
939 //----------------------------------------------------------------------------
940
941
942 //----------------------------------------------------------------------------
943 void vvSlicer::UpdateDisplayExtent()
944 {
945   vtkImageData *input = this->GetInput();
946   if (!input || !this->ImageActor) {
947     return;
948   }
949   input->UpdateInformation();
950   this->SetSlice( this->GetSlice() ); //SR: make sure the update let the slice in extents
951
952   // Local copy of extent
953   int w_ext[6];
954   int* ext = GetExtent();
955   copyExtent(ext, w_ext);
956   // Set slice value
957   w_ext[ this->SliceOrientation*2   ] = this->Slice;
958   w_ext[ this->SliceOrientation*2+1 ] = this->Slice;
959   
960   // Image actor
961   this->ImageActor->SetDisplayExtent(w_ext);
962 #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10)
963   // Fix for bug #1882
964   dynamic_cast<vtkImageSliceMapper *>(this->ImageActor->GetMapper())->SetOrientation(this->GetOrientation());
965 #endif
966
967   // Overlay image actor
968   if (mOverlay && mOverlayActor->GetVisibility()) {
969     AdjustResliceToSliceOrientation(mOverlayReslice);
970     int overExtent[6];
971     this->ConvertImageToImageDisplayExtent(input, w_ext, mOverlayReslice->GetOutput(), overExtent);
972     ClipDisplayedExtent(overExtent, mOverlayMapper->GetInput()->GetWholeExtent());
973     mOverlayActor->SetDisplayExtent( overExtent );
974 #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10)
975     // Fix for bug #1882
976     dynamic_cast<vtkImageSliceMapper *>(mOverlayActor->GetMapper())->SetOrientation(this->GetOrientation());
977 #endif
978   }
979
980   // Fusion image actor
981   if (mFusion && mFusionActor->GetVisibility()) {
982     AdjustResliceToSliceOrientation(mFusionReslice);
983     int fusExtent[6];
984     this->ConvertImageToImageDisplayExtent(input, w_ext, mFusionReslice->GetOutput(), fusExtent);
985     ClipDisplayedExtent(fusExtent, mFusionMapper->GetInput()->GetWholeExtent());
986     mFusionActor->SetDisplayExtent(fusExtent);
987 #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10)
988     // Fix for bug #1882
989     dynamic_cast<vtkImageSliceMapper *>(mFusionActor->GetMapper())->SetOrientation(this->GetOrientation());
990 #endif
991   }
992
993   // Vector field actor
994   double* camera = Renderer->GetActiveCamera()->GetPosition();
995   double* image_bounds = ImageActor->GetBounds();
996   double position[3] = {0, 0, 0};
997   position[this->SliceOrientation] = image_bounds[this->SliceOrientation*2]; 
998
999   //print_vector<double, 6>("camera", camera);
1000   //print_vector<double, 6>("image_bounds", image_bounds);
1001   //print_vector<double, 3>("position", position);
1002
1003   // find where to place the VF actor. to deal with
1004   // z-buffer issues, the VF is placed right in front of the image,
1005   // subject to a small offset. the position actually depends on the
1006   // the location of the camera relative to the image. 
1007   double offset = 1;
1008   if (camera[this->SliceOrientation] < image_bounds[this->SliceOrientation*2])
1009     offset = -1;
1010   
1011   if (mVF && mVFActor->GetVisibility()) {
1012     int vfExtent[6];
1013     mVF->GetVTKImages()[0]->UpdateInformation();
1014     this->ConvertImageToImageDisplayExtent(input, w_ext, mVF->GetVTKImages()[0], vfExtent);
1015     ClipDisplayedExtent(vfExtent, mVOIFilter->GetInput()->GetWholeExtent());
1016     mVOIFilter->SetVOI(vfExtent);
1017     int orientation[3] = {1,1,1};
1018     orientation[this->SliceOrientation] = 0;
1019     mGlyphFilter->SetOrientation(orientation[0], orientation[1], orientation[2]);
1020     mVFMapper->Update();
1021
1022     position[this->SliceOrientation] += offset;
1023     mVFActor->SetPosition(position);
1024   }
1025   
1026   // Landmarks actor
1027   if (mLandActor) {
1028     if (mClipBox) {
1029       double bounds [6];
1030       for(unsigned int i=0; i<6; i++)
1031         bounds[i] = ImageActor->GetBounds()[i];
1032       bounds[ this->SliceOrientation*2   ] = ImageActor->GetBounds()[ this->SliceOrientation*2  ]-fabs(this->GetInput()->GetSpacing()[this->SliceOrientation]);
1033       bounds[ this->SliceOrientation*2+1 ] = ImageActor->GetBounds()[ this->SliceOrientation*2+1 ]+fabs(this->GetInput()->GetSpacing()[this->SliceOrientation]);
1034       mClipBox->SetBounds(bounds);
1035       UpdateLandmarks();
1036     }
1037     
1038     position[this->SliceOrientation] = offset;
1039     mLandActor->SetPosition(position);
1040   }
1041
1042   // Figure out the correct clipping range
1043   if (this->Renderer) {
1044     if (this->InteractorStyle &&
1045         this->InteractorStyle->GetAutoAdjustCameraClippingRange()) {
1046       this->Renderer->ResetCameraClippingRange();
1047     } else {
1048       vtkCamera *cam = this->Renderer->GetActiveCamera();
1049       if (cam) {
1050         double bounds[6];
1051         this->ImageActor->GetBounds(bounds);
1052         double spos = (double)bounds[this->SliceOrientation * 2];
1053         double cpos = (double)cam->GetPosition()[this->SliceOrientation];
1054         double range = fabs(spos - cpos);
1055         double *spacing = input->GetSpacing();
1056         double sumSpacing = spacing[0] + spacing[1] + spacing[2];
1057         cam->SetClippingRange(range - sumSpacing, range + sumSpacing);
1058       }
1059     }
1060   }
1061 }
1062 //----------------------------------------------------------------------------
1063
1064 //----------------------------------------------------------------------------
1065 void vvSlicer::ConvertImageToImageDisplayExtent(vtkImageData *sourceImage, const int sourceExtent[6],
1066                                                 vtkImageData *targetImage, int targetExtent[6])
1067 {
1068   double dExtents[6];
1069   for(unsigned int i=0; i<6; i++) {
1070     // From source voxel coordinates to world coordinates
1071     dExtents[i] = sourceImage->GetOrigin()[i/2] + sourceImage->GetSpacing()[i/2] * sourceExtent[i];
1072
1073     // From world coordinates to floating point target voxel coordinates
1074     dExtents[i] = (dExtents[i]- targetImage->GetOrigin()[i/2]) / targetImage->GetSpacing()[i/2];
1075     
1076     // Round to nearest
1077     //targetExtent[i] = itk::Math::Round<double>(dExtents[i]);
1078     targetExtent[i] = itk::Math::Floor<double>(dExtents[i]);
1079   }
1080 }
1081 //----------------------------------------------------------------------------
1082
1083 //----------------------------------------------------------------------------
1084 void vvSlicer::ClipDisplayedExtent(int extent[6], int refExtent[6])
1085 {
1086   bool out = false;
1087   int maxBound = 6;
1088
1089   //2D overlay on 3D image specific case
1090   if (refExtent[4] == refExtent[5]) {
1091     maxBound = 4;
1092     extent[4] = refExtent[4];
1093     extent[5] = refExtent[5];
1094   }
1095
1096   for (int i = 0; i < maxBound; i = i+2) {
1097     //if we are totally outside the image
1098     if ( extent[i] > refExtent[i+1] || extent[i+1] < refExtent[i] ) {
1099       out = true;
1100       break;
1101     }
1102     //crop to the limit of the image
1103     extent[i] = (extent[i] > refExtent[i]) ? extent[i] : refExtent[i];
1104     extent[i] = (extent[i] < refExtent[i+1]) ? extent[i] : refExtent[i+1];
1105     extent[i+1] = (extent[i+1] > refExtent[i]) ? extent[i+1] : refExtent[i];
1106     extent[i+1] = (extent[i+1] < refExtent[i+1]) ? extent[i+1] : refExtent[i+1];
1107   }
1108   if (out)
1109     for (int i = 0; i < maxBound; i = i+2) {
1110       extent[i] = refExtent[i];
1111       extent[i+1] = refExtent[i];
1112     }
1113 }
1114 //----------------------------------------------------------------------------
1115
1116
1117 //----------------------------------------------------------------------------
1118 void vvSlicer::UpdateOrientation()
1119 {
1120   // Set the camera position
1121   vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : NULL;
1122   if (cam) {
1123     switch (this->SliceOrientation) {
1124     case vtkImageViewer2::SLICE_ORIENTATION_XY:
1125       cam->SetFocalPoint(0,0,0);
1126       cam->SetPosition(0,0,-1); // -1 if medical ?
1127       cam->SetViewUp(0,-1,0);
1128       break;
1129
1130     case vtkImageViewer2::SLICE_ORIENTATION_XZ:
1131       cam->SetFocalPoint(0,0,0);
1132       cam->SetPosition(0,-1,0); // 1 if medical ?
1133       cam->SetViewUp(0,0,1);
1134       break;
1135
1136     case vtkImageViewer2::SLICE_ORIENTATION_YZ:
1137       cam->SetFocalPoint(0,0,0);
1138       cam->SetPosition(-1,0,0); // -1 if medical ?
1139       cam->SetViewUp(0,0,1);
1140       break;
1141     }
1142   }
1143 }
1144 //----------------------------------------------------------------------------
1145
1146
1147 //----------------------------------------------------------------------------
1148 void vvSlicer::SetOpacity(double s)
1149 {
1150   this->GetImageActor()->SetOpacity(s);
1151 }
1152 //----------------------------------------------------------------------------
1153
1154
1155 //----------------------------------------------------------------------------
1156 void vvSlicer::SetRenderWindow(int orientation, vtkRenderWindow * rw)
1157 {
1158   this->Superclass::SetRenderWindow(rw);
1159   this->SetupInteractor(rw->GetInteractor());
1160   ca->SetImageActor(this->GetImageActor());
1161   ca->SetWindowLevel(this->GetWindowLevel());
1162   ca->SetText(2, "<slice>");
1163   ca->SetText(3, "<window>\n<level>");
1164
1165   double bounds[6];
1166   double max = 65000;
1167
1168   bounds[0] = -max;
1169   bounds[1] = max;
1170   bounds[2] = -max;
1171   bounds[3] = max;
1172   bounds[4] = -max;
1173   bounds[5] = max;
1174
1175   crossCursor->SetModelBounds(bounds);
1176   this->GetRenderer()->AddActor(pdmA);
1177   this->GetRenderer()->AddActor(ca);
1178   this->GetRenderer()->ResetCamera();
1179
1180   //this is just a mapping between the labeling of the orientations presented to the user and
1181   //the one used by vtk
1182   SetSliceOrientation(2-(orientation%3));
1183   ResetCamera();
1184 }
1185 //----------------------------------------------------------------------------
1186
1187
1188 //----------------------------------------------------------------------------
1189 void vvSlicer::ResetCamera()
1190 {
1191   this->GetRenderer()->ResetCamera();
1192 }
1193 //----------------------------------------------------------------------------
1194
1195
1196 //----------------------------------------------------------------------------
1197 void vvSlicer::SetDisplayMode(bool i)
1198 {
1199         this->GetRenderer()->SetDraw(i);
1200         if (i) UpdateDisplayExtent();
1201 }
1202 //----------------------------------------------------------------------------
1203
1204
1205 //----------------------------------------------------------------------------
1206 void vvSlicer::FlipHorizontalView()
1207 {
1208   vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : NULL;
1209   if (cam) {
1210     double *position = cam->GetPosition();
1211     double factor[3] = {1, 1, 1};
1212     factor[this->SliceOrientation] = -1;
1213     cam->SetPosition(factor[0]*position[0],factor[1]*position[1],factor[2]*position[2]);
1214     
1215 /*    switch (this->SliceOrientation) {
1216     case vtkImageViewer2::SLICE_ORIENTATION_XY:
1217       cam->SetPosition(position[0],position[1],-position[2]);
1218       break;
1219
1220     case vtkImageViewer2::SLICE_ORIENTATION_XZ:
1221       cam->SetPosition(position[0],-position[1],position[2]);
1222       break;
1223
1224     case vtkImageViewer2::SLICE_ORIENTATION_YZ:
1225       cam->SetPosition(-position[0],position[1],position[2]);
1226       break;
1227     }*/
1228
1229     this->Renderer->ResetCameraClippingRange();
1230     this->UpdateDisplayExtent();
1231   }
1232 }
1233 //----------------------------------------------------------------------------
1234
1235
1236 //----------------------------------------------------------------------------
1237 void vvSlicer::FlipVerticalView()
1238 {
1239   vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : NULL;
1240   if (cam) {
1241     FlipHorizontalView();
1242     double *viewup = cam->GetViewUp();
1243     cam->SetViewUp(-viewup[0],-viewup[1],-viewup[2]);
1244     this->UpdateDisplayExtent();
1245   }
1246 }
1247 //----------------------------------------------------------------------------
1248
1249
1250 //----------------------------------------------------------------------------
1251 void vvSlicer::SetColorWindow(double window)
1252 {
1253   vtkLookupTable* LUT = static_cast<vtkLookupTable*>(this->GetWindowLevel()->GetLookupTable());
1254   if ( LUT ) {
1255     double level = this->GetWindowLevel()->GetLevel();
1256     LUT->SetTableRange(level-fabs(window)/2,level+fabs(window)/2);
1257     LUT->Build();
1258   }
1259   this->vtkImageViewer2::SetColorWindow(window);
1260 }
1261 //----------------------------------------------------------------------------
1262
1263 //----------------------------------------------------------------------------
1264 void vvSlicer::SetColorLevel(double level)
1265 {
1266   vtkLookupTable* LUT = static_cast<vtkLookupTable*>(this->GetWindowLevel()->GetLookupTable());
1267   if ( LUT ) {
1268     double window = this->GetWindowLevel()->GetWindow();
1269     LUT->SetTableRange(level-fabs(window)/2,level+fabs(window)/2);
1270     LUT->Build();
1271   }
1272   this->vtkImageViewer2::SetColorLevel(level);
1273 }
1274 //----------------------------------------------------------------------------
1275
1276 //----------------------------------------------------------------------------
1277 double vvSlicer::GetOverlayColorWindow()
1278 {
1279   if(mOverlayMapper)
1280     return mOverlayMapper->GetWindow();
1281   else
1282     return 0.;
1283 }
1284 //----------------------------------------------------------------------------
1285
1286 //----------------------------------------------------------------------------
1287 double vvSlicer::GetOverlayColorLevel()
1288 {
1289   if(mOverlayMapper)
1290     return mOverlayMapper->GetLevel();
1291   else
1292     return 0.;
1293 }
1294 //----------------------------------------------------------------------------
1295
1296 //----------------------------------------------------------------------------
1297 void vvSlicer::SetOverlayColorWindow(double window)
1298 {
1299   mOverlayMapper->SetWindow(window);
1300 }
1301 //----------------------------------------------------------------------------
1302
1303 //----------------------------------------------------------------------------
1304 void vvSlicer::SetOverlayColorLevel(double level)
1305 {
1306   mOverlayMapper->SetLevel(level);
1307 }
1308 //----------------------------------------------------------------------------
1309
1310 //----------------------------------------------------------------------------
1311 // Returns the min an the max value in a 20%x20% region around the mouse pointer
1312 void vvSlicer::GetExtremasAroundMousePointer(double & min, double & max, vtkImageData *image, vtkTransform *transform)
1313 {
1314   //Get mouse pointer position in view coordinates
1315   double corner1[3];
1316   double corner2[3];
1317   for(int i=0; i<3; i++) {
1318     corner1[i] = mCurrent[i];
1319     corner2[i] = mCurrent[i];
1320   }
1321
1322   this->Renderer->WorldToView(corner1[0], corner1[1], corner1[2]);
1323   this->Renderer->WorldToView(corner2[0], corner2[1], corner2[2]);
1324
1325   // In view coordinates, x is the slicer width and y is the slicer height are the in-plane axis
1326   int w, h;
1327   this->Renderer->GetTiledSize(&w, &h);
1328   corner1[0] -= 0.2*h/(double)w;
1329   corner2[0] += 0.2*h/(double)w;
1330   corner1[1] -= 0.2;
1331   corner2[1] += 0.2;
1332   this->Renderer->ViewToWorld(corner1[0], corner1[1], corner1[2]);
1333   this->Renderer->ViewToWorld(corner2[0], corner2[1], corner2[2]);
1334
1335   //Convert to image pixel coordinates (rounded)
1336   transform->TransformPoint(corner1, corner1);
1337   transform->TransformPoint(corner2, corner2);
1338   int iLocalExtents[6];
1339   for(int i=0; i<3; i++) {
1340     corner1[i] = (corner1[i] - image->GetOrigin()[i])/image->GetSpacing()[i];
1341     corner2[i] = (corner2[i] - image->GetOrigin()[i])/image->GetSpacing()[i];
1342
1343     iLocalExtents[i*2  ] = lrint(corner1[i]);
1344     iLocalExtents[i*2+1] = lrint(corner2[i]);
1345
1346     if(iLocalExtents[i*2  ]>iLocalExtents[i*2+1])
1347       std::swap(iLocalExtents[i*2], iLocalExtents[i*2+1]);
1348   }
1349
1350   vtkSmartPointer<vtkExtractVOI> voiFilter = vtkSmartPointer<vtkExtractVOI>::New();
1351   voiFilter->SetInput(image);
1352   voiFilter->SetVOI(iLocalExtents);
1353   voiFilter->Update();
1354   if (!voiFilter->GetOutput()->GetNumberOfPoints()) {
1355     min = 0;
1356     max = 0;
1357     return;
1358   }
1359
1360   vtkSmartPointer<vtkImageAccumulate> accFilter = vtkSmartPointer<vtkImageAccumulate>::New();
1361   accFilter->SetInput(voiFilter->GetOutput());
1362   accFilter->Update();
1363
1364   min = *(accFilter->GetMin());
1365   max = *(accFilter->GetMax());
1366 }
1367 //----------------------------------------------------------------------------
1368
1369 //----------------------------------------------------------------------------
1370 double vvSlicer::GetScalarComponentAsDouble(vtkImageData *image, double X, double Y, double Z, int &ix, int &iy, int &iz, int component)
1371 {
1372   ix = lrint(X);
1373   iy = lrint(Y);
1374   iz = lrint(Z);
1375
1376   if (ix < image->GetWholeExtent()[0] ||
1377       ix > image->GetWholeExtent()[1] ||
1378       iy < image->GetWholeExtent()[2] ||
1379       iy > image->GetWholeExtent()[3] ||
1380       iz < image->GetWholeExtent()[4] ||
1381       iz > image->GetWholeExtent()[5] )
1382     return std::numeric_limits<double>::quiet_NaN();
1383
1384   image->SetUpdateExtent(ix, ix, iy, iy, iz, iz);
1385   image->Update();
1386   return image->GetScalarComponentAsDouble(ix, iy, iz, component);
1387 }
1388 //----------------------------------------------------------------------------
1389
1390 //----------------------------------------------------------------------------
1391 void vvSlicer::Render()
1392 {
1393   if (this->mFusion && mFusionActor->GetVisibility() && showFusionLegend) {
1394     legend->SetLookupTable(this->GetFusionMapper()->GetLookupTable());
1395     legend->UseOpacityOn();
1396     legend->SetVisibility(1);
1397   }
1398   else if (this->GetWindowLevel()->GetLookupTable() && !this->mOverlay)  {
1399     legend->SetLookupTable(this->GetWindowLevel()->GetLookupTable());
1400     legend->UseOpacityOff();
1401     legend->SetVisibility(1);
1402   } else legend->SetVisibility(0);
1403
1404   if (ca->GetVisibility()) {
1405     std::stringstream worldPos;
1406     double pt[3];
1407     mConcatenatedTransform->TransformPoint(mCurrent, pt);
1408     double X = (pt[0] - mImage->GetVTKImages()[mCurrentTSlice]->GetOrigin()[0])/mImage->GetVTKImages()[mCurrentTSlice]->GetSpacing()[0];
1409     double Y = (pt[1] - mImage->GetVTKImages()[mCurrentTSlice]->GetOrigin()[1])/mImage->GetVTKImages()[mCurrentTSlice]->GetSpacing()[1];
1410     double Z = (pt[2] - mImage->GetVTKImages()[mCurrentTSlice]->GetOrigin()[2])/mImage->GetVTKImages()[mCurrentTSlice]->GetSpacing()[2];
1411
1412     if (X >= mImage->GetVTKImages()[mCurrentTSlice]->GetWholeExtent()[0]-0.5 &&
1413         X <= mImage->GetVTKImages()[mCurrentTSlice]->GetWholeExtent()[1]+0.5 &&
1414         Y >= mImage->GetVTKImages()[mCurrentTSlice]->GetWholeExtent()[2]-0.5 &&
1415         Y <= mImage->GetVTKImages()[mCurrentTSlice]->GetWholeExtent()[3]+0.5 &&
1416         Z >= mImage->GetVTKImages()[mCurrentTSlice]->GetWholeExtent()[4]-0.5 &&
1417         Z <= mImage->GetVTKImages()[mCurrentTSlice]->GetWholeExtent()[5]+0.5) {
1418
1419       
1420       int ix, iy, iz;
1421       double value = this->GetScalarComponentAsDouble(mImage->GetVTKImages()[mCurrentTSlice], X, Y, Z, ix, iy, iz);
1422
1423       if(ImageActor->GetVisibility())
1424         worldPos << "data value : " << value << std::endl;
1425
1426       worldPos << "mm : " << lrint(mCurrentBeforeSlicingTransform[0]) << ' '
1427                           << lrint(mCurrentBeforeSlicingTransform[1]) << ' '
1428                           << lrint(mCurrentBeforeSlicingTransform[2]) << ' '
1429                           << mCurrentTSlice
1430                           << std::endl;
1431       worldPos << "pixel : " << ix << ' '
1432                              << iy << ' '
1433                              << iz << ' '
1434                              << mCurrentTSlice
1435                              << std::endl;
1436     }
1437     ca->SetText(1,worldPos.str().c_str());
1438   }
1439
1440   if (pdmA->GetVisibility()) {
1441     double x = mCursor[0];
1442     double y = mCursor[1];
1443     double z = mCursor[2];
1444     double xCursor = (x - this->GetInput()->GetOrigin()[0])/this->GetInput()->GetSpacing()[0];
1445     double yCursor = (y - this->GetInput()->GetOrigin()[1])/this->GetInput()->GetSpacing()[1];
1446     double zCursor = (z - this->GetInput()->GetOrigin()[2])/this->GetInput()->GetSpacing()[2];
1447
1448     if (xCursor >= this->GetImageActor()->GetDisplayExtent()[0]-0.5 &&
1449         xCursor < this->GetImageActor()->GetDisplayExtent()[1]+0.5 &&
1450         yCursor >= this->GetImageActor()->GetDisplayExtent()[2]-0.5 &&
1451         yCursor < this->GetImageActor()->GetDisplayExtent()[3]+0.5 &&
1452         zCursor >= this->GetImageActor()->GetDisplayExtent()[4]-0.5 &&
1453         zCursor < this->GetImageActor()->GetDisplayExtent()[5]+0.5 ) {
1454       vtkRenderer * renderer = this->Renderer;
1455
1456       renderer->WorldToView(x,y,z);
1457       renderer->ViewToNormalizedViewport(x,y,z);
1458       renderer->NormalizedViewportToViewport(x,y);
1459       renderer->ViewportToNormalizedDisplay(x,y);
1460       renderer->NormalizedDisplayToDisplay(x,y);
1461       crossCursor->SetFocalPoint(x,y,z);
1462     } else
1463       crossCursor->SetFocalPoint(-1,-1,z);
1464   }
1465
1466
1467   if (mOverlay && mOverlayActor->GetVisibility()) {
1468     if(mLinkOverlayWindowLevel) {
1469       mOverlayMapper->SetWindow(this->GetColorWindow());
1470       mOverlayMapper->SetLevel(this->GetColorLevel());
1471     }
1472     mOverlayMapper->GetOutput()->SetUpdateExtent(mOverlayActor->GetDisplayExtent());
1473     mOverlayMapper->GetOutput()->Update();
1474     mOverlayMapper->Update();
1475   }
1476   if (mLandMapper)
1477     UpdateLandmarks();
1478
1479   this->GetRenderWindow()->Render();
1480 }
1481 //----------------------------------------------------------------------------
1482
1483
1484 //----------------------------------------------------------------------------
1485 void vvSlicer::UpdateCursorPosition()
1486 {
1487   pdmA->SetVisibility(true);
1488   mCursor[0] = mCurrent[0];
1489   mCursor[1] = mCurrent[1];
1490   mCursor[2] = mCurrent[2];
1491   mCursor[3] = mCurrentTSlice;
1492 }
1493 //----------------------------------------------------------------------------
1494
1495
1496 //----------------------------------------------------------------------------
1497 void vvSlicer::UpdateLandmarks()
1498 {
1499   vtkPolyData *pd = static_cast<vtkPolyData*>(mLandClipper->GetInput());
1500   if (pd->GetPoints()) {
1501     //mLandGlyph->SetRange(0,1);
1502     //mLandGlyph->Modified();
1503     //mLandGlyph->Update();
1504
1505     mClipBox->Modified();
1506     mLandClipper->Update();
1507     mLandMapper->Update();
1508     //Let's add the captions
1509     //First remove all captions:
1510     for(unsigned int i=0;i<mLandLabelActors.size();i++) {
1511         this->Renderer->RemoveActor2D(mLandLabelActors[i]);
1512         //allActors2D->Remove (mLandLabelActors[i]);
1513     }
1514     mLandLabelActors.clear();
1515     //Next add the captions to the displayed points
1516     for (vtkIdType id=0; id<mLandClipper->GetOutput()->GetNumberOfPoints(); id++) {
1517           double *position = mLandClipper->GetOutput()->GetPoint(id);
1518       vtkStdString label = static_cast<vtkStringArray*>(mLandClipper->GetOutput()->GetPointData()->GetAbstractArray("labels"))->GetValue(id);
1519       vtkSmartPointer<vtkCaptionActor2D> label_actor = vtkSmartPointer<vtkCaptionActor2D>::New();
1520       label_actor->SetCaption(label);
1521       label_actor->SetAttachmentPoint(position);
1522       label_actor->GetCaptionTextProperty()->SetColor(1,0,0);
1523       label_actor->GetCaptionTextProperty()->SetOrientation(33.333333);
1524       label_actor->GetCaptionTextProperty()->SetFontFamilyToTimes();
1525       label_actor->GetCaptionTextProperty()->SetBold(0);
1526       label_actor->GetCaptionTextProperty()->SetFontSize(6);
1527       label_actor->BorderOff();
1528       label_actor->LeaderOff();
1529       label_actor->ThreeDimensionalLeaderOff();
1530       mLandLabelActors.push_back(label_actor);
1531       this->Renderer->AddActor2D(mLandLabelActors[id]);
1532      }
1533   }
1534
1535 }
1536 //----------------------------------------------------------------------------
1537
1538
1539 //----------------------------------------------------------------------------
1540 void vvSlicer::SetSlice(int slice)
1541 {
1542   int *range = this->GetSliceRange();
1543   if (range) {
1544     if (slice < range[0]) {
1545       slice = range[0];
1546     } else if (slice > range[1]) {
1547       slice = range[1];
1548     }
1549   }
1550
1551   if (this->Slice == slice) {
1552     return;
1553   }
1554
1555   this->Slice = slice;
1556   SetContourSlice();
1557   this->Modified();
1558   this->UpdateDisplayExtent();
1559
1560   // Seems to work without this line
1561   //this->Render();
1562 }
1563 //----------------------------------------------------------------------------
1564
1565 //----------------------------------------------------------------------------
1566 int vvSlicer::GetTMax() {
1567   int tmax = (int)mImage->GetVTKImages().size() - 1;
1568   if(mOverlay)
1569     tmax = std::max(tmax, (int)mOverlay->GetVTKImages().size()-1);
1570   return tmax;
1571 }
1572 //----------------------------------------------------------------------------
1573
1574 //----------------------------------------------------------------------------
1575 void vvSlicer::SetContourSlice()
1576 {
1577   if (mSurfaceCutActors.size() > 0)
1578     for (std::vector<vvMeshActor*>::iterator i=mSurfaceCutActors.begin();
1579          i!=mSurfaceCutActors.end(); i++) {
1580          
1581       (*i)->SetSlicingOrientation(this->SliceOrientation);
1582       (*i)->SetCutSlice((this->Slice)*this->GetImage()->GetSpacing()[this->SliceOrientation]+
1583                         this->GetImage()->GetOrigin()[this->SliceOrientation]);
1584     }
1585 }
1586 //----------------------------------------------------------------------------
1587
1588
1589 //----------------------------------------------------------------------------
1590 void vvSlicer::ForceUpdateDisplayExtent()
1591 {
1592   this->UpdateDisplayExtent();
1593 }
1594 //----------------------------------------------------------------------------
1595
1596
1597 //----------------------------------------------------------------------------
1598 int* vvSlicer::GetDisplayExtent()
1599 {
1600   return this->GetImageActor()->GetDisplayExtent();
1601 }
1602 //----------------------------------------------------------------------------
1603
1604
1605 //----------------------------------------------------------------------------
1606 void vvSlicer::PrintSelf(ostream& os, vtkIndent indent)
1607 {
1608   this->Superclass::PrintSelf(os, indent);
1609 }
1610 //----------------------------------------------------------------------------
1611
1612 //----------------------------------------------------------------------------
1613 void vvSlicer::SetVFColor(double r, double g, double b)
1614 {
1615   double mVFColorHSV[3];
1616   mVFColor[0] = r;
1617   mVFColor[1] = g;
1618   mVFColor[2] = b;
1619
1620   vtkMath::RGBToHSV(mVFColor, mVFColorHSV);
1621   mVFColorLUT->SetHueRange(mVFColorHSV[0], mVFColorHSV[0]);
1622   mVFColorLUT->SetSaturationRange(mVFColorHSV[1],mVFColorHSV[1]);
1623   mVFColorLUT->SetValueRange(mVFColorHSV[2], mVFColorHSV[2]);
1624
1625   this->Render();
1626 }  
1627