1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
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
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.
13 It is distributed under dual licence
15 - BSD See included LICENSE.txt file
16 - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================**/
19 #include "vvImageContour.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>
32 //------------------------------------------------------------------------------
33 vvImageContour::vvImageContour()
37 mHiddenImageIsUsed = false;
38 mDisplayModeIsPreserveMemory = true;
39 SetPreserveMemoryModeEnabled(true);
40 mPreviousOrientation = -1;
44 //------------------------------------------------------------------------------
47 //------------------------------------------------------------------------------
48 vvImageContour::~vvImageContour()
50 mSquaresActorList.clear();
52 //------------------------------------------------------------------------------
55 //------------------------------------------------------------------------------
56 void vvImageContour::RemoveActors()
58 for (unsigned int i = 0; i < mSquaresActorList.size(); i++) {
61 if (mSlicer->GetRenderer() != NULL) {
62 if (mSquaresActorList[i] != NULL) {
63 mSlicer->GetRenderer()->RemoveActor(mSquaresActorList[i]);
70 //------------------------------------------------------------------------------
73 //------------------------------------------------------------------------------
74 void vvImageContour::SetSlicer(vvSlicer * slicer)
77 // Create an actor for each time slice
78 for (unsigned int numImage = 0; numImage < mSlicer->GetImage()->GetVTKImages().size(); numImage++) {
79 CreateNewActor(numImage);
82 //------------------------------------------------------------------------------
85 //------------------------------------------------------------------------------
86 void vvImageContour::SetImage(vvImage::Pointer image)
88 for (unsigned int numImage = 0; numImage < image->GetVTKImages().size(); numImage++) {
89 #if VTK_MAJOR_VERSION <= 5
90 mClipperList[numImage]->SetInput(image->GetVTKImages()[numImage]);
92 mClipperList[numImage]->SetInputData(image->GetVTKImages()[numImage]);
95 mHiddenImageIsUsed = true;
98 //------------------------------------------------------------------------------
101 //------------------------------------------------------------------------------
102 void vvImageContour::SetPreserveMemoryModeEnabled(bool b)
104 // FastCache mode work only if threshold is always the same
105 if (mDisplayModeIsPreserveMemory == b) return;
106 mDisplayModeIsPreserveMemory = b;
108 clitkExceptionMacro("TODO : not implemented yet");
110 InitializeCacheMode();
113 for(unsigned int d=0; d<mListOfCachedContourActors.size(); d++)
114 mListOfCachedContourActors[d].clear();
115 mListOfCachedContourActors.clear();
119 //------------------------------------------------------------------------------
122 //------------------------------------------------------------------------------
123 void vvImageContour::SetColor(double r, double g, double b)
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
130 //------------------------------------------------------------------------------
133 //------------------------------------------------------------------------------
134 void vvImageContour::SetLineWidth(double w)
136 for(unsigned int i=0; i<mSquaresActorList.size(); i++) {
137 mSquaresActorList[i]->GetProperty()->SetLineWidth(w);
140 //------------------------------------------------------------------------------
143 //------------------------------------------------------------------------------
144 void vvImageContour::HideActors()
146 if (!mSlicer) return;
147 mSlice = mSlicer->GetSlice();
148 for(unsigned int i=0; i<mSquaresActorList.size(); i++) {
149 mSquaresActorList[i]->VisibilityOff();
152 //------------------------------------------------------------------------------
155 //------------------------------------------------------------------------------
156 void vvImageContour::ShowActors()
158 if (!mSlicer) return;
159 mSlice = mSlicer->GetSlice();
160 mTSlice = mSlicer->GetTSlice();
161 mSquaresActorList[mTSlice]->VisibilityOn();
164 //------------------------------------------------------------------------------
167 //------------------------------------------------------------------------------
168 void vvImageContour::SetDepth(double d)
171 // Move the actor to be visible
172 double position[3] = {0, 0, 0};
173 int orientation = ComputeCurrentOrientation();
174 position[orientation] = -mDepth;
176 for(unsigned int i=0; i<mSquaresActorList.size(); i++)
177 mSquaresActorList[i]->SetPosition(position);
179 //------------------------------------------------------------------------------
181 //------------------------------------------------------------------------------
182 void vvImageContour::Update(double value)
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
195 // Get current threshold value
199 mSlice = mSlicer->GetSlice();
201 if (mDisplayModeIsPreserveMemory) {
202 UpdateWithPreserveMemoryMode();
205 UpdateWithFastCacheMode();
208 //mSlicer->Render(); //DS ---> REMOVE ??
210 mPreviousTSlice = mSlicer->GetTSlice();
211 mPreviousSlice = mSlicer->GetSlice();
212 mPreviousValue = value;
213 mPreviousOrientation = ComputeCurrentOrientation();
215 //------------------------------------------------------------------------------
218 //------------------------------------------------------------------------------
219 void vvImageContour::UpdateWithPreserveMemoryMode()
221 // Only change actor visibility if tslice change
222 mPreviousTslice = mTSlice;
223 mTSlice = mSlicer->GetTSlice();
225 vtkMarchingSquares * mSquares = mSquaresList[mTSlice];
226 vtkPolyDataMapper* mapper = mSquaresMapperList[mTSlice];
227 vtkImageClip * mClipper = mClipperList[mTSlice];
228 vtkActor * mSquaresActor = mSquaresActorList[mTSlice];
229 int orientation = ComputeCurrentOrientation();
231 UpdateActor(mSquaresActor, mapper, mSquares, mClipper, mValue, orientation, mSlice);
233 if (mPreviousTslice != mTSlice) {
234 if (mPreviousTslice != -1) mSquaresActorList[mPreviousTslice]->VisibilityOff();
239 //------------------------------------------------------------------------------
242 //------------------------------------------------------------------------------
243 void vvImageContour::InitializeCacheMode()
245 clitkExceptionMacro("TODO : not implemented yet");
246 mPreviousSlice = mPreviousOrientation = 0;
247 int dim = mSlicer->GetImage()->GetNumberOfDimensions();
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;
258 //------------------------------------------------------------------------------
261 //------------------------------------------------------------------------------
262 int vvImageContour::ComputeCurrentOrientation()
264 // Get extent of image in the slicer
265 int* extent = mSlicer->GetImageActor()->GetDisplayExtent();
267 // Compute orientation
269 for (orientation = 0; orientation < 6; orientation = orientation+2) {
270 if (extent[orientation] == extent[orientation+1]) {
274 orientation = orientation/2;
277 //------------------------------------------------------------------------------
280 //------------------------------------------------------------------------------
281 void vvImageContour::UpdateWithFastCacheMode()
283 clitkExceptionMacro("TODO : not implemented yet");
285 // Compute orientation
286 int orientation = ComputeCurrentOrientation();
288 if ((mPreviousSlice == mSlice) && (mPreviousOrientation == orientation)) return;
290 vtkActor * actor = mListOfCachedContourActors[orientation][mSlice];
292 mListOfCachedContourActors[orientation][mSlice]->VisibilityOn();
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();
301 if (mListOfCachedContourActors[mPreviousOrientation][mPreviousSlice] != NULL)
302 mListOfCachedContourActors[mPreviousOrientation][mPreviousSlice]->VisibilityOff();
303 mPreviousSlice = mSlice;
304 mPreviousOrientation = orientation;
306 //------------------------------------------------------------------------------
309 //------------------------------------------------------------------------------
310 void vvImageContour::CreateNewActor(int numImage)
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();
317 if (mHiddenImageIsUsed) {
318 #if VTK_MAJOR_VERSION <= 5
319 clipper->SetInput(mHiddenImage->GetVTKImages()[0]);
321 clipper->SetInputData(mHiddenImage->GetVTKImages()[0]);
324 #if VTK_MAJOR_VERSION <= 5
325 clipper->SetInput(mSlicer->GetImage()->GetVTKImages()[numImage]);
327 clipper->SetInputData(mSlicer->GetImage()->GetVTKImages()[numImage]);
330 #if VTK_MAJOR_VERSION <= 5
331 squares->SetInput(clipper->GetOutput());
332 squaresMapper->SetInput(squares->GetOutput());
334 squares->SetInputConnection(clipper->GetOutputPort(0));
335 squaresMapper->SetInputConnection(squares->GetOutputPort(0));
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);
345 mSquaresActorList.push_back(squaresActor);
346 mClipperList.push_back(clipper);
347 mSquaresList.push_back(squares);
348 mSquaresMapperList.push_back(squaresMapper);
350 //------------------------------------------------------------------------------
353 //------------------------------------------------------------------------------
354 void vvImageContour::UpdateActor(vtkActor * actor,
355 vtkPolyDataMapper * mapper,
356 vtkMarchingSquares * squares,
357 vtkImageClip * clipper,
358 double threshold, int orientation, int slice)
360 // Set parameter for the MarchigSquare
361 squares->SetValue(0, threshold);
364 int* extent = mSlicer->GetImageActor()->GetDisplayExtent();
366 // Change extent if needed
368 if (mHiddenImageIsUsed) {
369 extent2 = new int[6];
371 extent3 = mHiddenImage->GetFirstVTKImageData()->GetExtent();
373 for(int i=0; i<6; i++) extent2[i] = extent3[i];
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
380 // Rint to the closest slice
381 extent2[orientation*2+1] = extent2[orientation*2] = (int)lrint(s);
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();
393 else actor->VisibilityOn();
397 actor->VisibilityOn();
400 clipper->SetOutputWholeExtent(extent2[0],extent2[1],extent2[2],
401 extent2[3],extent2[4],extent2[5]);
403 if (mHiddenImageIsUsed) delete extent2;
405 // Move the actor to be visible
407 // double position[3] = {0, 0, 0};
409 // position[orientation] = -mDepth;
410 // actor->SetPosition(position);
413 //------------------------------------------------------------------------------