]> Creatis software - clitk.git/blob - vv/vvImageContour.cxx
aa7b8d7c852e37dfe0c757faa6c136a256840c29
[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   // Move the actor to be visible
158   double position[3] = {0, 0, 0};
159   int orientation = ComputeCurrentOrientation();
160   position[orientation] = -mDepth;
161
162   for(unsigned int i=0; i<mSquaresActorList.size(); i++)
163     mSquaresActorList[i]->SetPosition(position);
164 }
165 //------------------------------------------------------------------------------
166
167 //------------------------------------------------------------------------------
168 void vvImageContour::Update(double value) {
169   if (!mSlicer) return;
170   if (mPreviousValue == value) {
171     if (mPreviousSlice == mSlicer->GetSlice()) {
172       if (mPreviousTSlice == mSlicer->GetTSlice()) {
173         if (mPreviousOrientation == ComputeCurrentOrientation()) {
174           return; // Nothing to do
175         }
176       }
177     }
178   }
179
180   // Get current threshold value
181   mValue = value;
182
183   // Get current slice
184   mSlice = mSlicer->GetSlice();
185
186   if (mDisplayModeIsPreserveMemory) {
187     UpdateWithPreserveMemoryMode();
188   }
189   else {
190     UpdateWithFastCacheMode();
191   }
192
193   //mSlicer->Render(); //DS ---> REMOVE ??
194
195   mPreviousTSlice = mSlicer->GetTSlice();
196   mPreviousSlice  = mSlicer->GetSlice();
197   mPreviousValue  = value;
198   mPreviousOrientation = ComputeCurrentOrientation();
199 }
200 //------------------------------------------------------------------------------
201
202
203 //------------------------------------------------------------------------------
204 void vvImageContour::UpdateWithPreserveMemoryMode() {
205   // Only change actor visibility if tslice change
206   mPreviousTslice = mTSlice;
207   mTSlice = mSlicer->GetTSlice();
208
209   vtkMarchingSquares * mSquares = mSquaresList[mTSlice];
210   vtkPolyDataMapper* mapper = mSquaresMapperList[mTSlice];
211   vtkImageClip * mClipper = mClipperList[mTSlice];
212   vtkActor * mSquaresActor = mSquaresActorList[mTSlice];
213   int orientation = ComputeCurrentOrientation();
214
215   UpdateActor(mSquaresActor, mapper, mSquares, mClipper, mValue, orientation, mSlice);
216
217   if (mPreviousTslice != mTSlice) {
218     if (mPreviousTslice != -1) mSquaresActorList[mPreviousTslice]->VisibilityOff();
219   }
220   
221   mSlicer->Render();
222 }
223 //------------------------------------------------------------------------------
224
225
226 //------------------------------------------------------------------------------
227 void vvImageContour::InitializeCacheMode() {
228 clitkExceptionMacro("TODO : not implemented yet");
229   mPreviousSlice = mPreviousOrientation = 0;
230   int dim = mSlicer->GetImage()->GetNumberOfDimensions();
231
232   mListOfCachedContourActors.resize(dim);
233   for(int d=0; d<dim; d++) {
234     int size = mSlicer->GetImage()->GetSize()[d];
235     mListOfCachedContourActors[d].resize(size);
236     for(int j=0; j<size; j++) {
237       mListOfCachedContourActors[d][j] = NULL;
238     }
239   }
240 }
241 //------------------------------------------------------------------------------
242
243
244 //------------------------------------------------------------------------------
245 int vvImageContour::ComputeCurrentOrientation() {
246   // Get extent of image in the slicer
247   int* extent = mSlicer->GetImageActor()->GetDisplayExtent();
248
249   // Compute orientation
250   int orientation;
251   for (orientation = 0; orientation < 6; orientation = orientation+2) {
252     if (extent[orientation] == extent[orientation+1]) {
253       break;
254     }
255   }
256   orientation = orientation/2;
257   return orientation;
258 }
259 //------------------------------------------------------------------------------
260
261
262 //------------------------------------------------------------------------------
263 void vvImageContour::UpdateWithFastCacheMode() {
264 clitkExceptionMacro("TODO : not implemented yet");
265
266   // Compute orientation
267   int orientation = ComputeCurrentOrientation();
268
269   if ((mPreviousSlice == mSlice) && (mPreviousOrientation == orientation)) return;
270
271   vtkActor * actor = mListOfCachedContourActors[orientation][mSlice];
272   if (actor != NULL) {
273     mListOfCachedContourActors[orientation][mSlice]->VisibilityOn();
274   } else {
275     CreateNewActor(0);
276     //SR: commented out, this code is never reached anyway
277     //UpdateActor(mSquaresActor, mSquares, mClipper, mValue, orientation, mSlice);
278     //mListOfCachedContourActors[orientation][mSlice] = mSquaresActor;
279     //mSquaresActor->VisibilityOn();
280   }
281
282   if (mListOfCachedContourActors[mPreviousOrientation][mPreviousSlice] != NULL)
283     mListOfCachedContourActors[mPreviousOrientation][mPreviousSlice]->VisibilityOff();
284   mPreviousSlice = mSlice;
285   mPreviousOrientation = orientation;
286 }
287 //------------------------------------------------------------------------------
288
289
290 //------------------------------------------------------------------------------
291 void vvImageContour::CreateNewActor(int numImage) {
292   vtkSmartPointer<vtkActor> squaresActor = vtkSmartPointer<vtkActor>::New();
293   vtkSmartPointer<vtkImageClip> clipper = vtkSmartPointer<vtkImageClip>::New();
294   vtkSmartPointer<vtkMarchingSquares> squares = vtkSmartPointer<vtkMarchingSquares>::New();
295   vtkSmartPointer<vtkPolyDataMapper> squaresMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
296
297   if (mHiddenImageIsUsed)
298     clipper->SetInput(mHiddenImage->GetVTKImages()[0]);
299   else
300     clipper->SetInput(mSlicer->GetImage()->GetVTKImages()[numImage]);
301   
302   squares->SetInput(clipper->GetOutput());
303   squaresMapper->SetInput(squares->GetOutput());
304   squaresMapper->ScalarVisibilityOff();
305   squaresActor->SetMapper(squaresMapper);
306   squaresActor->GetProperty()->SetColor(1.0,0,0);
307   squaresActor->SetPickable(0);
308   squaresActor->VisibilityOff();
309   mSlicer->GetRenderer()->AddActor(squaresActor);
310
311   mSquaresActorList.push_back(squaresActor);
312   mClipperList.push_back(clipper);
313   mSquaresList.push_back(squares);
314   mSquaresMapperList.push_back(squaresMapper);
315 }
316 //------------------------------------------------------------------------------
317
318
319 //------------------------------------------------------------------------------
320 void vvImageContour::UpdateActor(vtkActor * actor, 
321                                  vtkPolyDataMapper * mapper, 
322                                  vtkMarchingSquares * squares, 
323                                  vtkImageClip * clipper, 
324                                  double threshold, int orientation, int slice) {
325   // Set parameter for the MarchigSquare
326   squares->SetValue(0, threshold);
327
328   // Get image extent
329   int* extent = mSlicer->GetImageActor()->GetDisplayExtent();
330
331   // Change extent if needed
332   int* extent2;
333   if (mHiddenImageIsUsed) {
334     extent2 = new int[6];
335     int * extent3;
336     extent3 = mHiddenImage->GetFirstVTKImageData()->GetExtent();
337
338     for(int i=0; i<6; i++) extent2[i] = extent3[i];
339
340     double s = (double)extent[orientation*2]*(double)mSlicer->GetImage()->GetSpacing()[orientation]; // in mm
341     s = s+mSlicer->GetImage()->GetOrigin()[orientation]; // from origin
342     s = s-mHiddenImage->GetFirstVTKImageData()->GetOrigin()[orientation]; // from corner second image
343     s = s/mHiddenImage->GetFirstVTKImageData()->GetSpacing()[orientation]; // in voxel
344
345     // Rint to the closest slice
346     extent2[orientation*2+1] = extent2[orientation*2] = (int)lrint(s);
347
348     // Do not display a contour if there is no contour on this slice
349     // DD(extent2[orientation*2+1]);
350     // DD(extent3[orientation*2+1]);
351     // DD(extent2[orientation*2]);
352     // DD(extent3[orientation*2]);
353     if ((extent2[orientation*2+1] > extent3[orientation*2+1]) ||
354         (extent2[orientation*2] < extent3[orientation*2])) {
355       actor->VisibilityOff();
356       return;
357     }
358     else actor->VisibilityOn();
359
360   } else {
361     extent2 = extent;
362     actor->VisibilityOn();
363   }
364  
365   clipper->SetOutputWholeExtent(extent2[0],extent2[1],extent2[2],
366                                 extent2[3],extent2[4],extent2[5]);
367
368   if (mHiddenImageIsUsed) delete extent2;
369
370   // Move the actor to be visible
371   SetDepth(mDepth);
372   // double position[3] = {0, 0, 0};
373   // DD(mDepth);
374   // position[orientation] = -mDepth;
375   // actor->SetPosition(position);
376   
377   mapper->Update();
378 }
379 //------------------------------------------------------------------------------
380
381