]> Creatis software - clitk.git/blob - vv/vvImageContour.cxx
Correct Bounds in Input Contour Mapper
[clitk.git] / vv / vvImageContour.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 "vvImageContour.h"
20 #include "vvImage.h"
21 #include <vtkVersion.h>
22 #include <vtkImageActor.h>
23 #include <vtkCamera.h>
24 #include <vtkRenderer.h>
25 #include <vtkMarchingSquares.h>
26 #include <vtkImageClip.h>
27 #include <vtkImageData.h>
28 #include <vtkPolyDataMapper.h>
29 #include <vtkProperty.h>
30 #include <vtkInformation.h>
31
32 //------------------------------------------------------------------------------
33 vvImageContour::vvImageContour()
34 { //out << __func__ << endl;
35   mTSlice = -1;
36   mSlice = 0;
37   mHiddenImageIsUsed = false;
38   mDisplayModeIsPreserveMemory = true;
39   SetPreserveMemoryModeEnabled(true);
40   mPreviousOrientation = -1;
41   mDepth = 1.0;
42   mSlice = 0;
43 }
44 //------------------------------------------------------------------------------
45
46
47 //------------------------------------------------------------------------------
48 vvImageContour::~vvImageContour()
49 { //out << __func__ << endl;
50   mSquaresActorList.clear();
51 }
52 //------------------------------------------------------------------------------
53
54
55 //------------------------------------------------------------------------------
56 void vvImageContour::RemoveActors()
57 { //out << __func__ << endl;
58   for (unsigned int i = 0; i < mSquaresActorList.size(); i++) {
59     if (mSlicer != 0) {
60       if (mSlicer!= NULL) {
61         if (mSlicer->GetRenderer() != NULL) {
62           if (mSquaresActorList[i] != NULL)  {
63             mSlicer->GetRenderer()->RemoveActor(mSquaresActorList[i]);
64           }
65         }
66       }   
67     }
68   }
69 }
70 //------------------------------------------------------------------------------
71
72
73 //------------------------------------------------------------------------------
74 void vvImageContour::SetSlicer(vvSlicer * slicer) 
75 { //out << __func__ << endl;
76   mSlicer = slicer;  
77   // Create an actor for each time slice
78   for (unsigned int numImage = 0; numImage < mSlicer->GetImage()->GetVTKImages().size(); numImage++) {
79     CreateNewActor(numImage);
80   }
81 }
82 //------------------------------------------------------------------------------
83
84
85 //------------------------------------------------------------------------------
86 void vvImageContour::SetImage(vvImage::Pointer image) 
87 { //out << __func__ << endl;
88   for (unsigned int numImage = 0; numImage < image->GetVTKImages().size(); numImage++) {
89 #if VTK_MAJOR_VERSION <= 5
90     mClipperList[numImage]->SetInput(image->GetVTKImages()[numImage]);
91 #else
92     mClipperList[numImage]->SetInputData(image->GetVTKImages()[numImage]);
93 #endif
94   }
95   mHiddenImageIsUsed = true;
96   mHiddenImage = image;
97 }
98 //------------------------------------------------------------------------------
99
100
101 //------------------------------------------------------------------------------
102 void vvImageContour::SetPreserveMemoryModeEnabled(bool b) 
103 { //out << __func__ << endl;
104   // FastCache mode work only if threshold is always the same
105   if (mDisplayModeIsPreserveMemory == b) return;
106   mDisplayModeIsPreserveMemory = b;
107   if (!b) {
108     clitkExceptionMacro("TODO : not implemented yet");
109     HideActors();
110     InitializeCacheMode();
111   }
112   else {
113     for(unsigned int d=0; d<mListOfCachedContourActors.size(); d++)
114       mListOfCachedContourActors[d].clear();
115     mListOfCachedContourActors.clear();
116     ShowActors();
117   }
118 }
119 //------------------------------------------------------------------------------
120
121
122 //------------------------------------------------------------------------------
123 void vvImageContour::SetColor(double r, double g, double b) 
124 { //out << __func__ << endl;
125   for(unsigned int i=0; i<mSquaresActorList.size(); i++) {
126     mSquaresActorList[i]->GetProperty()->SetColor(r,g,b);
127   }
128 }
129 //------------------------------------------------------------------------------
130
131
132 //------------------------------------------------------------------------------
133 void vvImageContour::SetLineWidth(double w)
134 { //out << __func__ << endl;
135   for(unsigned int i=0; i<mSquaresActorList.size(); i++) {
136     mSquaresActorList[i]->GetProperty()->SetLineWidth(w);
137   }
138 }
139 //------------------------------------------------------------------------------
140
141
142 //------------------------------------------------------------------------------
143 void vvImageContour::HideActors() 
144 { //out << __func__ << endl;
145   if (!mSlicer) return;
146   mSlice = mSlicer->GetSlice();
147   for(unsigned int i=0; i<mSquaresActorList.size(); i++) {
148     mSquaresActorList[i]->VisibilityOff();
149   }
150 }
151 //------------------------------------------------------------------------------
152
153
154 //------------------------------------------------------------------------------
155 void vvImageContour::ShowActors() 
156 { //out << __func__ << endl;
157   if (!mSlicer) return;
158   mSlice = mSlicer->GetSlice();
159   mTSlice = mSlicer->GetTSlice();
160   mSquaresActorList[mTSlice]->VisibilityOn();
161   Update(mValue);
162 }
163 //------------------------------------------------------------------------------
164
165
166 //------------------------------------------------------------------------------
167 void vvImageContour::SetDepth(double d) 
168 { //out << __func__ << endl;
169   mDepth = d;
170   // Move the actor to be visible
171   double position[3] = {0, 0, 0};
172   int orientation = ComputeCurrentOrientation();
173   position[orientation] = -mDepth;
174
175   for(unsigned int i=0; i<mSquaresActorList.size(); i++)
176     mSquaresActorList[i]->SetPosition(position);
177 }
178 //------------------------------------------------------------------------------
179
180 //------------------------------------------------------------------------------
181 void vvImageContour::Update(double value) 
182 { //out << __func__ << endl;
183   if (!mSlicer) return;
184   if (mPreviousValue == value) {
185     if (mPreviousSlice == mSlicer->GetSlice()) {
186       if (mPreviousTSlice == mSlicer->GetTSlice()) {
187         if (mPreviousOrientation == ComputeCurrentOrientation()) {
188           return; // Nothing to do
189         }
190       }
191     }
192   }
193
194   // Get current threshold value
195   mValue = value;
196
197   // Get current slice
198   mSlice = mSlicer->GetSlice();
199
200   if (mDisplayModeIsPreserveMemory) {
201     UpdateWithPreserveMemoryMode();
202   }
203   else {
204     UpdateWithFastCacheMode();
205   }
206
207   //mSlicer->Render(); //DS ---> REMOVE ??
208
209   mPreviousTSlice = mSlicer->GetTSlice();
210   mPreviousSlice  = mSlicer->GetSlice();
211   mPreviousValue  = value;
212   mPreviousOrientation = ComputeCurrentOrientation();
213 }
214 //------------------------------------------------------------------------------
215
216
217 //------------------------------------------------------------------------------
218 void vvImageContour::UpdateWithPreserveMemoryMode() 
219 { //out << __func__ << endl;
220   // Only change actor visibility if tslice change
221   mPreviousTslice = mTSlice;
222   mTSlice = mSlicer->GetTSlice();
223
224   vtkMarchingSquares * mSquares = mSquaresList[mTSlice];
225   vtkPolyDataMapper* mapper = mSquaresMapperList[mTSlice];
226   vtkImageClip * mClipper = mClipperList[mTSlice];
227   vtkActor * mSquaresActor = mSquaresActorList[mTSlice];
228   int orientation = ComputeCurrentOrientation();
229
230   UpdateActor(mSquaresActor, mapper, mSquares, mClipper, mValue, orientation, mSlice);
231
232   if (mPreviousTslice != mTSlice) {
233     if (mPreviousTslice != -1) mSquaresActorList[mPreviousTslice]->VisibilityOff();
234   }
235
236   mSlicer->Render();
237 }
238 //------------------------------------------------------------------------------
239
240
241 //------------------------------------------------------------------------------
242 void vvImageContour::InitializeCacheMode() 
243 { //out << __func__ << endl;
244 clitkExceptionMacro("TODO : not implemented yet");
245   mPreviousSlice = mPreviousOrientation = 0;
246   int dim = mSlicer->GetImage()->GetNumberOfDimensions();
247
248   mListOfCachedContourActors.resize(dim);
249   for(int d=0; d<dim; d++) {
250     int size = mSlicer->GetImage()->GetSize()[d];
251     mListOfCachedContourActors[d].resize(size);
252     for(int j=0; j<size; j++) {
253       mListOfCachedContourActors[d][j] = NULL;
254     }
255   }
256 }
257 //------------------------------------------------------------------------------
258
259
260 //------------------------------------------------------------------------------
261 int vvImageContour::ComputeCurrentOrientation() 
262 { //out << __func__ << endl;
263   // Get extent of image in the slicer
264   int* extent = mSlicer->GetImageActor()->GetDisplayExtent();
265
266   // Compute orientation
267   int orientation;
268   for (orientation = 0; orientation < 6; orientation = orientation+2) {
269     if (extent[orientation] == extent[orientation+1]) {
270       break;
271     }
272   }
273   orientation = orientation/2;
274   return orientation;
275 }
276 //------------------------------------------------------------------------------
277
278
279 //------------------------------------------------------------------------------
280 void vvImageContour::UpdateWithFastCacheMode() 
281 { //out << __func__ << endl;
282 clitkExceptionMacro("TODO : not implemented yet");
283
284   // Compute orientation
285   int orientation = ComputeCurrentOrientation();
286
287   if ((mPreviousSlice == mSlice) && (mPreviousOrientation == orientation)) return;
288
289   vtkActor * actor = mListOfCachedContourActors[orientation][mSlice];
290   if (actor != NULL) {
291     mListOfCachedContourActors[orientation][mSlice]->VisibilityOn();
292   } else {
293     CreateNewActor(0);
294     //SR: commented out, this code is never reached anyway
295     //UpdateActor(mSquaresActor, mSquares, mClipper, mValue, orientation, mSlice);
296     //mListOfCachedContourActors[orientation][mSlice] = mSquaresActor;
297     //mSquaresActor->VisibilityOn();
298   }
299
300   if (mListOfCachedContourActors[mPreviousOrientation][mPreviousSlice] != NULL)
301     mListOfCachedContourActors[mPreviousOrientation][mPreviousSlice]->VisibilityOff();
302   mPreviousSlice = mSlice;
303   mPreviousOrientation = orientation;
304 }
305 //------------------------------------------------------------------------------
306
307
308 //------------------------------------------------------------------------------
309 void vvImageContour::CreateNewActor(int numImage) 
310 { //out << __func__ << endl;
311   vtkSmartPointer<vtkActor> squaresActor = vtkSmartPointer<vtkActor>::New();
312   vtkSmartPointer<vtkImageClip> clipper = vtkSmartPointer<vtkImageClip>::New();
313   vtkSmartPointer<vtkMarchingSquares> squares = vtkSmartPointer<vtkMarchingSquares>::New();
314   vtkSmartPointer<vtkPolyDataMapper> squaresMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
315
316   if (mHiddenImageIsUsed) {
317 #if VTK_MAJOR_VERSION <= 5
318     clipper->SetInput(mHiddenImage->GetVTKImages()[0]);
319 #else
320     clipper->SetInputData(mHiddenImage->GetVTKImages()[0]);
321 #endif
322   } else {
323 #if VTK_MAJOR_VERSION <= 5
324     clipper->SetInput(mSlicer->GetImage()->GetVTKImages()[numImage]);
325 #else
326     clipper->SetInputData(mSlicer->GetImage()->GetVTKImages()[numImage]);
327 #endif
328   }
329 #if VTK_MAJOR_VERSION <= 5
330   squares->SetInput(clipper->GetOutput());
331   squaresMapper->SetInput(squares->GetOutput());
332 #else
333   squares->SetInputConnection(clipper->GetOutputPort(0));
334   squaresMapper->SetInputConnection(squares->GetOutputPort(0));
335 #endif
336   squaresMapper->ScalarVisibilityOff();
337   squaresActor->SetMapper(squaresMapper);
338   squaresActor->GetProperty()->SetColor(1.0,0,0);
339   squaresActor->SetPickable(0);
340   squaresActor->VisibilityOff();
341   mSlicer->GetRenderer()->AddActor(squaresActor);
342
343   mSquaresActorList.push_back(squaresActor);
344   mClipperList.push_back(clipper);
345   mSquaresList.push_back(squares);
346   mSquaresMapperList.push_back(squaresMapper);
347 }
348 //------------------------------------------------------------------------------
349
350
351 //------------------------------------------------------------------------------
352 void vvImageContour::UpdateActor(vtkActor * actor, 
353                                  vtkPolyDataMapper * mapper, 
354                                  vtkMarchingSquares * squares, 
355                                  vtkImageClip * clipper, 
356                                  double threshold, int orientation, int slice) 
357 { //out << __func__ << endl;
358   // Set parameter for the MarchigSquare
359   squares->SetValue(0, threshold);
360   
361   // Get image extent
362   int* extent = mSlicer->GetImageActor()->GetDisplayExtent();
363
364   // Change extent if needed
365   int* extent2;
366   if (mHiddenImageIsUsed) {
367     extent2 = new int[6];
368     int * extent3;
369     extent3 = mHiddenImage->GetFirstVTKImageData()->GetExtent();
370
371     for(int i=0; i<6; i++) extent2[i] = extent3[i];
372
373     double s = (double)extent[orientation*2]*(double)mSlicer->GetImage()->GetSpacing()[orientation]; // in mm
374     s = s+mSlicer->GetImage()->GetOrigin()[orientation]; // from origin
375     s = s-mHiddenImage->GetFirstVTKImageData()->GetOrigin()[orientation]; // from corner second image
376     s = s/mHiddenImage->GetFirstVTKImageData()->GetSpacing()[orientation]; // in voxel
377
378     // Rint to the closest slice
379     extent2[orientation*2+1] = extent2[orientation*2] = (int)lrint(s);
380
381     // Do not display a contour if there is no contour on this slice
382     // DD(extent2[orientation*2+1]);
383     // DD(extent3[orientation*2+1]);
384     // DD(extent2[orientation*2]);
385     // DD(extent3[orientation*2]);
386     if ((extent2[orientation*2+1] > extent3[orientation*2+1]) ||
387         (extent2[orientation*2] < extent3[orientation*2])) {
388       actor->VisibilityOff();
389       return;
390     }
391     else actor->VisibilityOn();
392
393   } else {
394     extent2 = extent;
395     actor->VisibilityOn();
396   }
397   
398   clipper->SetOutputWholeExtent(extent2[0],extent2[1],extent2[2],
399                                 extent2[3],extent2[4],extent2[5]);
400                                 
401   if (mHiddenImageIsUsed) delete extent2;
402
403   // Move the actor to be visible
404   SetDepth(mDepth);
405   // double position[3] = {0, 0, 0};
406   // DD(mDepth);
407   // position[orientation] = -mDepth;
408   // actor->SetPosition(position);
409   
410   mapper->Update();
411 }
412 //------------------------------------------------------------------------------
413
414