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