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