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