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()
34 { //out << __func__ << endl;
37 mHiddenImageIsUsed = false;
38 mDisplayModeIsPreserveMemory = true;
39 SetPreserveMemoryModeEnabled(true);
40 mPreviousOrientation = -1;
44 //------------------------------------------------------------------------------
47 //------------------------------------------------------------------------------
48 vvImageContour::~vvImageContour()
49 { //out << __func__ << endl;
50 mSquaresActorList.clear();
52 //------------------------------------------------------------------------------
55 //------------------------------------------------------------------------------
56 void vvImageContour::RemoveActors()
57 { //out << __func__ << endl;
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)
75 { //out << __func__ << endl;
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)
87 { //out << __func__ << endl;
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)
103 { //out << __func__ << endl;
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)
124 { //out << __func__ << endl;
125 for(unsigned int i=0; i<mSquaresActorList.size(); i++) {
126 mSquaresActorList[i]->GetProperty()->SetColor(r,g,b);
129 //------------------------------------------------------------------------------
132 //------------------------------------------------------------------------------
133 void vvImageContour::SetLineWidth(double w)
134 { //out << __func__ << endl;
135 for(unsigned int i=0; i<mSquaresActorList.size(); i++) {
136 mSquaresActorList[i]->GetProperty()->SetLineWidth(w);
139 //------------------------------------------------------------------------------
142 //------------------------------------------------------------------------------
143 void vvImageContour::HideActors()
144 { //out << __func__ << endl;
145 if (!mSlicer) return;
146 mSlice = mSlicer->GetSlice();
147 for(unsigned int i=0; i<mSquaresActorList.size(); i++) {
148 mSquaresActorList[i]->VisibilityOff();
151 //------------------------------------------------------------------------------
154 //------------------------------------------------------------------------------
155 void vvImageContour::ShowActors()
156 { //out << __func__ << endl;
157 if (!mSlicer) return;
158 mSlice = mSlicer->GetSlice();
159 mTSlice = mSlicer->GetTSlice();
160 mSquaresActorList[mTSlice]->VisibilityOn();
163 //------------------------------------------------------------------------------
166 //------------------------------------------------------------------------------
167 void vvImageContour::SetDepth(double d)
168 { //out << __func__ << endl;
170 // Move the actor to be visible
171 double position[3] = {0, 0, 0};
172 int orientation = ComputeCurrentOrientation();
173 position[orientation] = -mDepth;
175 for(unsigned int i=0; i<mSquaresActorList.size(); i++)
176 mSquaresActorList[i]->SetPosition(position);
178 //------------------------------------------------------------------------------
180 //------------------------------------------------------------------------------
181 void vvImageContour::Update(double value)
182 { //out << __func__ << endl;
183 if (!mSlicer) return;
184 if (mPreviousValue == value) {
185 if (mPreviousSlice == mSlicer->GetSlice()) {
186 if (mPreviousTSlice == mSlicer->GetTSlice()) {
187 if (mPreviousOrientation == ComputeCurrentOrientation()) {
188 return; // Nothing to do
194 // Get current threshold value
198 mSlice = mSlicer->GetSlice();
200 if (mDisplayModeIsPreserveMemory) {
201 UpdateWithPreserveMemoryMode();
204 UpdateWithFastCacheMode();
207 //mSlicer->Render(); //DS ---> REMOVE ??
209 mPreviousTSlice = mSlicer->GetTSlice();
210 mPreviousSlice = mSlicer->GetSlice();
211 mPreviousValue = value;
212 mPreviousOrientation = ComputeCurrentOrientation();
214 //------------------------------------------------------------------------------
217 //------------------------------------------------------------------------------
218 void vvImageContour::UpdateWithPreserveMemoryMode()
219 { //out << __func__ << endl;
220 // Only change actor visibility if tslice change
221 mPreviousTslice = mTSlice;
222 mTSlice = mSlicer->GetTSlice();
224 vtkMarchingSquares * mSquares = mSquaresList[mTSlice];
225 vtkPolyDataMapper* mapper = mSquaresMapperList[mTSlice];
226 vtkImageClip * mClipper = mClipperList[mTSlice];
227 vtkActor * mSquaresActor = mSquaresActorList[mTSlice];
228 int orientation = ComputeCurrentOrientation();
230 UpdateActor(mSquaresActor, mapper, mSquares, mClipper, mValue, orientation, mSlice);
232 if (mPreviousTslice != mTSlice) {
233 if (mPreviousTslice != -1) mSquaresActorList[mPreviousTslice]->VisibilityOff();
238 //------------------------------------------------------------------------------
241 //------------------------------------------------------------------------------
242 void vvImageContour::InitializeCacheMode()
243 { //out << __func__ << endl;
244 clitkExceptionMacro("TODO : not implemented yet");
245 mPreviousSlice = mPreviousOrientation = 0;
246 int dim = mSlicer->GetImage()->GetNumberOfDimensions();
248 mListOfCachedContourActors.resize(dim);
249 for(int d=0; d<dim; d++) {
250 int size = mSlicer->GetImage()->GetSize()[d];
251 mListOfCachedContourActors[d].resize(size);
252 for(int j=0; j<size; j++) {
253 mListOfCachedContourActors[d][j] = NULL;
257 //------------------------------------------------------------------------------
260 //------------------------------------------------------------------------------
261 int vvImageContour::ComputeCurrentOrientation()
262 { //out << __func__ << endl;
263 // Get extent of image in the slicer
264 int* extent = mSlicer->GetImageActor()->GetDisplayExtent();
266 // Compute orientation
268 for (orientation = 0; orientation < 6; orientation = orientation+2) {
269 if (extent[orientation] == extent[orientation+1]) {
273 orientation = orientation/2;
276 //------------------------------------------------------------------------------
279 //------------------------------------------------------------------------------
280 void vvImageContour::UpdateWithFastCacheMode()
281 { //out << __func__ << endl;
282 clitkExceptionMacro("TODO : not implemented yet");
284 // Compute orientation
285 int orientation = ComputeCurrentOrientation();
287 if ((mPreviousSlice == mSlice) && (mPreviousOrientation == orientation)) return;
289 vtkActor * actor = mListOfCachedContourActors[orientation][mSlice];
291 mListOfCachedContourActors[orientation][mSlice]->VisibilityOn();
294 //SR: commented out, this code is never reached anyway
295 //UpdateActor(mSquaresActor, mSquares, mClipper, mValue, orientation, mSlice);
296 //mListOfCachedContourActors[orientation][mSlice] = mSquaresActor;
297 //mSquaresActor->VisibilityOn();
300 if (mListOfCachedContourActors[mPreviousOrientation][mPreviousSlice] != NULL)
301 mListOfCachedContourActors[mPreviousOrientation][mPreviousSlice]->VisibilityOff();
302 mPreviousSlice = mSlice;
303 mPreviousOrientation = orientation;
305 //------------------------------------------------------------------------------
308 //------------------------------------------------------------------------------
309 void vvImageContour::CreateNewActor(int numImage)
310 { //out << __func__ << endl;
311 vtkSmartPointer<vtkActor> squaresActor = vtkSmartPointer<vtkActor>::New();
312 vtkSmartPointer<vtkImageClip> clipper = vtkSmartPointer<vtkImageClip>::New();
313 vtkSmartPointer<vtkMarchingSquares> squares = vtkSmartPointer<vtkMarchingSquares>::New();
314 vtkSmartPointer<vtkPolyDataMapper> squaresMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
316 if (mHiddenImageIsUsed) {
317 #if VTK_MAJOR_VERSION <= 5
318 clipper->SetInput(mHiddenImage->GetVTKImages()[0]);
320 clipper->SetInputData(mHiddenImage->GetVTKImages()[0]);
323 #if VTK_MAJOR_VERSION <= 5
324 clipper->SetInput(mSlicer->GetImage()->GetVTKImages()[numImage]);
326 clipper->SetInputData(mSlicer->GetImage()->GetVTKImages()[numImage]);
329 #if VTK_MAJOR_VERSION <= 5
330 squares->SetInput(clipper->GetOutput());
331 squaresMapper->SetInput(squares->GetOutput());
333 squares->SetInputConnection(clipper->GetOutputPort(0));
334 squaresMapper->SetInputConnection(squares->GetOutputPort(0));
336 squaresMapper->ScalarVisibilityOff();
337 squaresActor->SetMapper(squaresMapper);
338 squaresActor->GetProperty()->SetColor(1.0,0,0);
339 squaresActor->SetPickable(0);
340 squaresActor->VisibilityOff();
341 mSlicer->GetRenderer()->AddActor(squaresActor);
343 mSquaresActorList.push_back(squaresActor);
344 mClipperList.push_back(clipper);
345 mSquaresList.push_back(squares);
346 mSquaresMapperList.push_back(squaresMapper);
348 //------------------------------------------------------------------------------
351 //------------------------------------------------------------------------------
352 void vvImageContour::UpdateActor(vtkActor * actor,
353 vtkPolyDataMapper * mapper,
354 vtkMarchingSquares * squares,
355 vtkImageClip * clipper,
356 double threshold, int orientation, int slice)
357 { //out << __func__ << endl;
358 // Set parameter for the MarchigSquare
359 squares->SetValue(0, threshold);
362 int* extent = mSlicer->GetImageActor()->GetDisplayExtent();
364 // Change extent if needed
366 if (mHiddenImageIsUsed) {
367 extent2 = new int[6];
369 extent3 = mHiddenImage->GetFirstVTKImageData()->GetExtent();
371 for(int i=0; i<6; i++) extent2[i] = extent3[i];
373 double s = (double)extent[orientation*2]*(double)mSlicer->GetImage()->GetSpacing()[orientation]; // in mm
374 s = s+mSlicer->GetImage()->GetOrigin()[orientation]; // from origin
375 s = s-mHiddenImage->GetFirstVTKImageData()->GetOrigin()[orientation]; // from corner second image
376 s = s/mHiddenImage->GetFirstVTKImageData()->GetSpacing()[orientation]; // in voxel
378 // Rint to the closest slice
379 extent2[orientation*2+1] = extent2[orientation*2] = (int)lrint(s);
381 // Do not display a contour if there is no contour on this slice
382 // DD(extent2[orientation*2+1]);
383 // DD(extent3[orientation*2+1]);
384 // DD(extent2[orientation*2]);
385 // DD(extent3[orientation*2]);
386 if ((extent2[orientation*2+1] > extent3[orientation*2+1]) ||
387 (extent2[orientation*2] < extent3[orientation*2])) {
388 actor->VisibilityOff();
391 else actor->VisibilityOn();
395 actor->VisibilityOn();
398 clipper->SetOutputWholeExtent(extent2[0],extent2[1],extent2[2],
399 extent2[3],extent2[4],extent2[5]);
401 if (mHiddenImageIsUsed) delete extent2;
403 // Move the actor to be visible
405 // double position[3] = {0, 0, 0};
407 // position[orientation] = -mDepth;
408 // actor->SetPosition(position);
412 //------------------------------------------------------------------------------