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;
45 //------------------------------------------------------------------------------
48 //------------------------------------------------------------------------------
49 vvImageContour::~vvImageContour()
51 mSquaresActorList.clear();
53 //------------------------------------------------------------------------------
56 //------------------------------------------------------------------------------
57 void vvImageContour::RemoveActors()
59 for (unsigned int i = 0; i < mSquaresActorList.size(); i++) {
62 if (mSlicer->GetRenderer() != NULL) {
63 if (mSquaresActorList[i] != NULL) {
64 mSlicer->GetRenderer()->RemoveActor(mSquaresActorList[i]);
71 //------------------------------------------------------------------------------
74 //------------------------------------------------------------------------------
75 void vvImageContour::SetSlicer(vvSlicer * slicer)
78 // Create an actor for each time slice
79 for (unsigned int numImage = 0; numImage < mSlicer->GetImage()->GetVTKImages().size(); numImage++) {
80 CreateNewActor(numImage);
83 //------------------------------------------------------------------------------
86 //------------------------------------------------------------------------------
87 void vvImageContour::SetImage(vvImage::Pointer image)
89 for (unsigned int numImage = 0; numImage < image->GetVTKImages().size(); numImage++) {
90 #if VTK_MAJOR_VERSION <= 5
91 mClipperList[numImage]->SetInput(image->GetVTKImages()[numImage]);
93 mClipperList[numImage]->SetInputData(image->GetVTKImages()[numImage]);
96 mHiddenImageIsUsed = true;
99 //------------------------------------------------------------------------------
102 //------------------------------------------------------------------------------
103 void vvImageContour::SetPreserveMemoryModeEnabled(bool b)
105 // FastCache mode work only if threshold is always the same
106 if (mDisplayModeIsPreserveMemory == b) return;
107 mDisplayModeIsPreserveMemory = b;
109 clitkExceptionMacro("TODO : not implemented yet");
111 InitializeCacheMode();
114 for(unsigned int d=0; d<mListOfCachedContourActors.size(); d++)
115 mListOfCachedContourActors[d].clear();
116 mListOfCachedContourActors.clear();
120 //------------------------------------------------------------------------------
123 //------------------------------------------------------------------------------
124 void vvImageContour::SetColor(double r, double g, double b)
126 for(unsigned int i=0; i<mSquaresActorList.size(); i++) {
127 mSquaresActorList[i]->GetProperty()->SetColor(r,g,b);
128 mSquaresActorList[i]->GetProperty()->SetOpacity(0.995); //in order to get VTK to turn on the alpha-blending in OpenGL
131 //------------------------------------------------------------------------------
134 //------------------------------------------------------------------------------
135 void vvImageContour::SetLineWidth(double w)
137 for(unsigned int i=0; i<mSquaresActorList.size(); i++) {
138 mSquaresActorList[i]->GetProperty()->SetLineWidth(w);
141 //------------------------------------------------------------------------------
144 //------------------------------------------------------------------------------
145 void vvImageContour::HideActors()
147 if (!mSlicer) return;
148 mSlice = mSlicer->GetSlice();
149 for(unsigned int i=0; i<mSquaresActorList.size(); i++) {
150 mSquaresActorList[i]->VisibilityOff();
153 //------------------------------------------------------------------------------
156 //------------------------------------------------------------------------------
157 void vvImageContour::ShowActors()
159 if (!mSlicer) return;
160 mSlice = mSlicer->GetSlice();
161 mTSlice = mSlicer->GetTSlice();
162 mSquaresActorList[mTSlice]->VisibilityOn();
165 //------------------------------------------------------------------------------
168 //------------------------------------------------------------------------------
169 void vvImageContour::SetDepth(double d)
172 // Move the actor to be visible
173 double position[3] = {0, 0, 0};
174 int orientation = ComputeCurrentOrientation();
175 position[orientation] = -mDepth;
177 for(unsigned int i=0; i<mSquaresActorList.size(); i++)
178 mSquaresActorList[i]->SetPosition(position);
180 //------------------------------------------------------------------------------
182 //------------------------------------------------------------------------------
183 void vvImageContour::Update(double value)
185 if (!mSlicer) return;
186 if (mPreviousValue == value) {
187 if (mPreviousSlice == mSlicer->GetSlice()) {
188 if (mPreviousTSlice == mSlicer->GetTSlice()) {
189 if (mPreviousOrientation == ComputeCurrentOrientation()) {
190 return; // Nothing to do
196 // Get current threshold value
200 mSlice = mSlicer->GetSlice();
202 if (mDisplayModeIsPreserveMemory) {
203 UpdateWithPreserveMemoryMode();
206 UpdateWithFastCacheMode();
209 //mSlicer->Render(); //DS ---> REMOVE ??
211 mPreviousTSlice = mSlicer->GetTSlice();
212 mPreviousSlice = mSlicer->GetSlice();
213 mPreviousValue = value;
214 mPreviousOrientation = ComputeCurrentOrientation();
216 //------------------------------------------------------------------------------
219 //------------------------------------------------------------------------------
220 void vvImageContour::UpdateWithPreserveMemoryMode()
222 // Only change actor visibility if tslice change
223 mPreviousTslice = mTSlice;
224 mTSlice = mSlicer->GetTSlice();
226 vtkMarchingSquares * mSquares = mSquaresList[mTSlice];
227 vtkPolyDataMapper* mapper = mSquaresMapperList[mTSlice];
228 vtkImageClip * mClipper = mClipperList[mTSlice];
229 vtkActor * mSquaresActor = mSquaresActorList[mTSlice];
230 int orientation = ComputeCurrentOrientation();
232 UpdateActor(mSquaresActor, mapper, mSquares, mClipper, mValue, orientation, mSlice);
234 if (mPreviousTslice != mTSlice) {
235 if (mPreviousTslice != -1) mSquaresActorList[mPreviousTslice]->VisibilityOff();
240 //------------------------------------------------------------------------------
243 //------------------------------------------------------------------------------
244 void vvImageContour::InitializeCacheMode()
246 clitkExceptionMacro("TODO : not implemented yet");
247 mPreviousSlice = mPreviousOrientation = 0;
248 int dim = mSlicer->GetImage()->GetNumberOfDimensions();
250 mListOfCachedContourActors.resize(dim);
251 for(int d=0; d<dim; d++) {
252 int size = mSlicer->GetImage()->GetSize()[d];
253 mListOfCachedContourActors[d].resize(size);
254 for(int j=0; j<size; j++) {
255 mListOfCachedContourActors[d][j] = NULL;
259 //------------------------------------------------------------------------------
262 //------------------------------------------------------------------------------
263 int vvImageContour::ComputeCurrentOrientation()
265 // Get extent of image in the slicer
266 int* extent = mSlicer->GetImageActor()->GetDisplayExtent();
268 // Compute orientation
270 for (orientation = 0; orientation < 6; orientation = orientation+2) {
271 if (extent[orientation] == extent[orientation+1]) {
275 orientation = orientation/2;
278 //------------------------------------------------------------------------------
281 //------------------------------------------------------------------------------
282 void vvImageContour::UpdateWithFastCacheMode()
284 clitkExceptionMacro("TODO : not implemented yet");
286 // Compute orientation
287 int orientation = ComputeCurrentOrientation();
289 if ((mPreviousSlice == mSlice) && (mPreviousOrientation == orientation)) return;
291 vtkActor * actor = mListOfCachedContourActors[orientation][mSlice];
293 mListOfCachedContourActors[orientation][mSlice]->VisibilityOn();
296 //SR: commented out, this code is never reached anyway
297 //UpdateActor(mSquaresActor, mSquares, mClipper, mValue, orientation, mSlice);
298 //mListOfCachedContourActors[orientation][mSlice] = mSquaresActor;
299 //mSquaresActor->VisibilityOn();
302 if (mListOfCachedContourActors[mPreviousOrientation][mPreviousSlice] != NULL)
303 mListOfCachedContourActors[mPreviousOrientation][mPreviousSlice]->VisibilityOff();
304 mPreviousSlice = mSlice;
305 mPreviousOrientation = orientation;
307 //------------------------------------------------------------------------------
310 //------------------------------------------------------------------------------
311 void vvImageContour::CreateNewActor(int numImage)
313 vtkSmartPointer<vtkActor> squaresActor = vtkSmartPointer<vtkActor>::New();
314 vtkSmartPointer<vtkImageClip> clipper = vtkSmartPointer<vtkImageClip>::New();
315 vtkSmartPointer<vtkMarchingSquares> squares = vtkSmartPointer<vtkMarchingSquares>::New();
316 vtkSmartPointer<vtkPolyDataMapper> squaresMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
318 if (mHiddenImageIsUsed) {
319 #if VTK_MAJOR_VERSION <= 5
320 clipper->SetInput(mHiddenImage->GetVTKImages()[0]);
322 clipper->SetInputData(mHiddenImage->GetVTKImages()[0]);
325 #if VTK_MAJOR_VERSION <= 5
326 clipper->SetInput(mSlicer->GetImage()->GetVTKImages()[numImage]);
328 clipper->SetInputData(mSlicer->GetImage()->GetVTKImages()[numImage]);
331 #if VTK_MAJOR_VERSION <= 5
332 squares->SetInput(clipper->GetOutput());
333 squaresMapper->SetInput(squares->GetOutput());
335 squares->SetInputConnection(clipper->GetOutputPort(0));
336 squaresMapper->SetInputConnection(squares->GetOutputPort(0));
338 squaresMapper->ScalarVisibilityOff();
339 squaresActor->SetMapper(squaresMapper);
340 squaresActor->GetProperty()->SetColor(1.0,0,0);
341 squaresActor->GetProperty()->SetOpacity(0.995); //in order to get VTK to turn on the alpha-blending in OpenGL
342 squaresActor->SetPickable(0);
343 squaresActor->VisibilityOff();
344 mSlicer->GetRenderer()->AddActor(squaresActor);
346 mSquaresActorList.push_back(squaresActor);
347 mClipperList.push_back(clipper);
348 mSquaresList.push_back(squares);
349 mSquaresMapperList.push_back(squaresMapper);
351 //------------------------------------------------------------------------------
354 //------------------------------------------------------------------------------
355 void vvImageContour::UpdateActor(vtkActor * actor,
356 vtkPolyDataMapper * mapper,
357 vtkMarchingSquares * squares,
358 vtkImageClip * clipper,
359 double threshold, int orientation, int slice)
361 // Set parameter for the MarchigSquare
362 squares->SetValue(0, threshold);
365 int* extent = mSlicer->GetImageActor()->GetDisplayExtent();
367 // Change extent if needed
369 if (mHiddenImageIsUsed) {
370 extent2 = new int[6];
372 extent3 = mHiddenImage->GetFirstVTKImageData()->GetExtent();
374 for(int i=0; i<6; i++) extent2[i] = extent3[i];
376 double s = (double)extent[orientation*2]*(double)mSlicer->GetImage()->GetSpacing()[orientation]; // in mm
377 s = s+mSlicer->GetImage()->GetOrigin()[orientation]; // from origin
378 s = s-mHiddenImage->GetFirstVTKImageData()->GetOrigin()[orientation]; // from corner second image
379 s = s/mHiddenImage->GetFirstVTKImageData()->GetSpacing()[orientation]; // in voxel
381 // Rint to the closest slice
382 extent2[orientation*2+1] = extent2[orientation*2] = (int)lrint(s);
384 // Do not display a contour if there is no contour on this slice
385 // DD(extent2[orientation*2+1]);
386 // DD(extent3[orientation*2+1]);
387 // DD(extent2[orientation*2]);
388 // DD(extent3[orientation*2]);
389 if ((extent2[orientation*2+1] > extent3[orientation*2+1]) ||
390 (extent2[orientation*2] < extent3[orientation*2])) {
391 actor->VisibilityOff();
394 else actor->VisibilityOn();
398 actor->VisibilityOn();
401 clipper->SetOutputWholeExtent(extent2[0],extent2[1],extent2[2],
402 extent2[3],extent2[4],extent2[5]);
404 if (mHiddenImageIsUsed) delete extent2;
406 // Move the actor to be visible
408 // double position[3] = {0, 0, 0};
410 // position[orientation] = -mDepth;
411 // actor->SetPosition(position);
414 //------------------------------------------------------------------------------