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>
31 //------------------------------------------------------------------------------
32 vvImageContour::vvImageContour()
33 { //out << __func__ << endl;
36 mHiddenImageIsUsed = false;
37 mDisplayModeIsPreserveMemory = true;
38 SetPreserveMemoryModeEnabled(true);
39 mPreviousOrientation = -1;
43 //------------------------------------------------------------------------------
46 //------------------------------------------------------------------------------
47 vvImageContour::~vvImageContour()
48 { //out << __func__ << endl;
49 mSquaresActorList.clear();
51 //------------------------------------------------------------------------------
54 //------------------------------------------------------------------------------
55 void vvImageContour::RemoveActors()
56 { //out << __func__ << endl;
57 for (unsigned int i = 0; i < mSquaresActorList.size(); i++) {
60 if (mSlicer->GetRenderer() != NULL) {
61 if (mSquaresActorList[i] != NULL) {
62 mSlicer->GetRenderer()->RemoveActor(mSquaresActorList[i]);
69 //------------------------------------------------------------------------------
72 //------------------------------------------------------------------------------
73 void vvImageContour::SetSlicer(vvSlicer * slicer)
74 { //out << __func__ << endl;
76 // Create an actor for each time slice
77 for (unsigned int numImage = 0; numImage < mSlicer->GetImage()->GetVTKImages().size(); numImage++) {
78 CreateNewActor(numImage);
81 //------------------------------------------------------------------------------
84 //------------------------------------------------------------------------------
85 void vvImageContour::SetImage(vvImage::Pointer image)
86 { //out << __func__ << endl;
87 for (unsigned int numImage = 0; numImage < image->GetVTKImages().size(); numImage++) {
88 #if VTK_MAJOR_VERSION <= 5
89 mClipperList[numImage]->SetInput(image->GetVTKImages()[numImage]);
91 mClipperList[numImage]->SetInputData(image->GetVTKImages()[numImage]);
94 mHiddenImageIsUsed = true;
97 //------------------------------------------------------------------------------
100 //------------------------------------------------------------------------------
101 void vvImageContour::SetPreserveMemoryModeEnabled(bool b)
102 { //out << __func__ << endl;
103 // FastCache mode work only if threshold is always the same
104 if (mDisplayModeIsPreserveMemory == b) return;
105 mDisplayModeIsPreserveMemory = b;
107 clitkExceptionMacro("TODO : not implemented yet");
109 InitializeCacheMode();
112 for(unsigned int d=0; d<mListOfCachedContourActors.size(); d++)
113 mListOfCachedContourActors[d].clear();
114 mListOfCachedContourActors.clear();
118 //------------------------------------------------------------------------------
121 //------------------------------------------------------------------------------
122 void vvImageContour::SetColor(double r, double g, double b)
123 { //out << __func__ << endl;
124 for(unsigned int i=0; i<mSquaresActorList.size(); i++) {
125 mSquaresActorList[i]->GetProperty()->SetColor(r,g,b);
128 //------------------------------------------------------------------------------
131 //------------------------------------------------------------------------------
132 void vvImageContour::SetLineWidth(double w)
133 { //out << __func__ << endl;
134 for(unsigned int i=0; i<mSquaresActorList.size(); i++) {
135 mSquaresActorList[i]->GetProperty()->SetLineWidth(w);
138 //------------------------------------------------------------------------------
141 //------------------------------------------------------------------------------
142 void vvImageContour::HideActors()
143 { //out << __func__ << endl;
144 if (!mSlicer) return;
145 mSlice = mSlicer->GetSlice();
146 for(unsigned int i=0; i<mSquaresActorList.size(); i++) {
147 mSquaresActorList[i]->VisibilityOff();
150 //------------------------------------------------------------------------------
153 //------------------------------------------------------------------------------
154 void vvImageContour::ShowActors()
155 { //out << __func__ << endl;
156 if (!mSlicer) return;
157 mSlice = mSlicer->GetSlice();
158 mTSlice = mSlicer->GetTSlice();
159 mSquaresActorList[mTSlice]->VisibilityOn();
162 //------------------------------------------------------------------------------
165 //------------------------------------------------------------------------------
166 void vvImageContour::SetDepth(double d)
167 { //out << __func__ << endl;
169 // Move the actor to be visible
170 double position[3] = {0, 0, 0};
171 int orientation = ComputeCurrentOrientation();
172 position[orientation] = -mDepth;
174 for(unsigned int i=0; i<mSquaresActorList.size(); i++)
175 mSquaresActorList[i]->SetPosition(position);
177 //------------------------------------------------------------------------------
179 //------------------------------------------------------------------------------
180 void vvImageContour::Update(double value)
181 { //out << __func__ << endl;
182 if (!mSlicer) return;
183 if (mPreviousValue == value) {
184 if (mPreviousSlice == mSlicer->GetSlice()) {
185 if (mPreviousTSlice == mSlicer->GetTSlice()) {
186 if (mPreviousOrientation == ComputeCurrentOrientation()) {
187 return; // Nothing to do
193 // Get current threshold value
197 mSlice = mSlicer->GetSlice();
199 if (mDisplayModeIsPreserveMemory) {
200 UpdateWithPreserveMemoryMode();
203 UpdateWithFastCacheMode();
206 //mSlicer->Render(); //DS ---> REMOVE ??
208 mPreviousTSlice = mSlicer->GetTSlice();
209 mPreviousSlice = mSlicer->GetSlice();
210 mPreviousValue = value;
211 mPreviousOrientation = ComputeCurrentOrientation();
213 //------------------------------------------------------------------------------
216 //------------------------------------------------------------------------------
217 void vvImageContour::UpdateWithPreserveMemoryMode()
218 { //out << __func__ << endl;
219 // Only change actor visibility if tslice change
220 mPreviousTslice = mTSlice;
221 mTSlice = mSlicer->GetTSlice();
223 vtkMarchingSquares * mSquares = mSquaresList[mTSlice];
224 vtkPolyDataMapper* mapper = mSquaresMapperList[mTSlice];
225 vtkImageClip * mClipper = mClipperList[mTSlice];
226 vtkActor * mSquaresActor = mSquaresActorList[mTSlice];
227 int orientation = ComputeCurrentOrientation();
229 //UpdateActor(mSquaresActor, mapper, mSquares, mClipper, mValue, orientation, mSlice);
231 if (mPreviousTslice != mTSlice) {
232 if (mPreviousTslice != -1) mSquaresActorList[mPreviousTslice]->VisibilityOff();
237 //------------------------------------------------------------------------------
240 //------------------------------------------------------------------------------
241 void vvImageContour::InitializeCacheMode()
242 { //out << __func__ << endl;
243 clitkExceptionMacro("TODO : not implemented yet");
244 mPreviousSlice = mPreviousOrientation = 0;
245 int dim = mSlicer->GetImage()->GetNumberOfDimensions();
247 mListOfCachedContourActors.resize(dim);
248 for(int d=0; d<dim; d++) {
249 int size = mSlicer->GetImage()->GetSize()[d];
250 mListOfCachedContourActors[d].resize(size);
251 for(int j=0; j<size; j++) {
252 mListOfCachedContourActors[d][j] = NULL;
256 //------------------------------------------------------------------------------
259 //------------------------------------------------------------------------------
260 int vvImageContour::ComputeCurrentOrientation()
261 { //out << __func__ << endl;
262 // Get extent of image in the slicer
263 int* extent = mSlicer->GetImageActor()->GetDisplayExtent();
265 // Compute orientation
267 for (orientation = 0; orientation < 6; orientation = orientation+2) {
268 if (extent[orientation] == extent[orientation+1]) {
272 orientation = orientation/2;
275 //------------------------------------------------------------------------------
278 //------------------------------------------------------------------------------
279 void vvImageContour::UpdateWithFastCacheMode()
280 { //out << __func__ << endl;
281 clitkExceptionMacro("TODO : not implemented yet");
283 // Compute orientation
284 int orientation = ComputeCurrentOrientation();
286 if ((mPreviousSlice == mSlice) && (mPreviousOrientation == orientation)) return;
288 vtkActor * actor = mListOfCachedContourActors[orientation][mSlice];
290 mListOfCachedContourActors[orientation][mSlice]->VisibilityOn();
293 //SR: commented out, this code is never reached anyway
294 //UpdateActor(mSquaresActor, mSquares, mClipper, mValue, orientation, mSlice);
295 //mListOfCachedContourActors[orientation][mSlice] = mSquaresActor;
296 //mSquaresActor->VisibilityOn();
299 if (mListOfCachedContourActors[mPreviousOrientation][mPreviousSlice] != NULL)
300 mListOfCachedContourActors[mPreviousOrientation][mPreviousSlice]->VisibilityOff();
301 mPreviousSlice = mSlice;
302 mPreviousOrientation = orientation;
304 //------------------------------------------------------------------------------
307 //------------------------------------------------------------------------------
308 void vvImageContour::CreateNewActor(int numImage)
309 { //out << __func__ << endl;
310 vtkSmartPointer<vtkActor> squaresActor = vtkSmartPointer<vtkActor>::New();
311 vtkSmartPointer<vtkImageClip> clipper = vtkSmartPointer<vtkImageClip>::New();
312 vtkSmartPointer<vtkMarchingSquares> squares = vtkSmartPointer<vtkMarchingSquares>::New();
313 vtkSmartPointer<vtkPolyDataMapper> squaresMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
315 if (mHiddenImageIsUsed) {
316 #if VTK_MAJOR_VERSION <= 5
317 clipper->SetInput(mHiddenImage->GetVTKImages()[0]);
319 clipper->SetInputData(mHiddenImage->GetVTKImages()[0]);
322 #if VTK_MAJOR_VERSION <= 5
323 clipper->SetInput(mSlicer->GetImage()->GetVTKImages()[numImage]);
325 clipper->SetInputData(mSlicer->GetImage()->GetVTKImages()[numImage]);
329 #if VTK_MAJOR_VERSION <= 5
330 squares->SetInput(clipper->GetOutput());
331 squaresMapper->SetInput(squares->GetOutput());
333 squares->SetInputData(clipper->GetOutput());
334 squaresMapper->SetInputData(squares->GetOutput());
337 squaresMapper->Update();
338 squaresMapper->ScalarVisibilityOff();
339 squaresActor->SetMapper(squaresMapper);
340 squaresActor->GetProperty()->SetColor(1.0,0,0);
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)
359 { //out << __func__ << endl;
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 clipper->Print(cout);
405 if (mHiddenImageIsUsed) delete extent2;
407 // Move the actor to be visible
409 // double position[3] = {0, 0, 0};
411 // position[orientation] = -mDepth;
412 // actor->SetPosition(position);
416 //------------------------------------------------------------------------------