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