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