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