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