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