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