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 <vtkImageActor.h>
22 #include <vtkCamera.h>
23 #include <vtkRenderer.h>
24 #include <vtkMarchingSquares.h>
25 #include <vtkImageClip.h>
26 #include <vtkImageData.h>
27 #include <vtkPolyDataMapper.h>
28 #include <vtkProperty.h>
30 //------------------------------------------------------------------------------
31 vvImageContour::vvImageContour()
35 mHiddenImageIsUsed = false;
36 mDisplayModeIsPreserveMemory = true;
37 SetPreserveMemoryModeEnabled(true);
38 mPreviousOrientation = -1;
42 //------------------------------------------------------------------------------
45 //------------------------------------------------------------------------------
46 vvImageContour::~vvImageContour()
48 mSquaresActorList.clear();
50 //------------------------------------------------------------------------------
53 //------------------------------------------------------------------------------
54 void vvImageContour::RemoveActors()
56 for (unsigned int i = 0; i < mSquaresActorList.size(); i++) {
59 if (mSlicer->GetRenderer() != NULL) {
60 if (mSquaresActorList[i] != NULL) {
61 mSlicer->GetRenderer()->RemoveActor(mSquaresActorList[i]);
68 //------------------------------------------------------------------------------
71 //------------------------------------------------------------------------------
72 void vvImageContour::SetSlicer(vvSlicer * slicer) {
74 // Create an actor for each time slice
75 for (unsigned int numImage = 0; numImage < mSlicer->GetImage()->GetVTKImages().size(); numImage++) {
76 CreateNewActor(numImage);
79 //------------------------------------------------------------------------------
82 //------------------------------------------------------------------------------
83 void vvImageContour::SetImage(vvImage::Pointer image) {
84 for (unsigned int numImage = 0; numImage < image->GetVTKImages().size(); numImage++) {
85 mClipperList[numImage]->SetInput(image->GetVTKImages()[numImage]);
87 mHiddenImageIsUsed = true;
90 //------------------------------------------------------------------------------
93 //------------------------------------------------------------------------------
94 void vvImageContour::SetPreserveMemoryModeEnabled(bool b) {
95 // FastCache mode work only if threshold is always the same
96 if (mDisplayModeIsPreserveMemory == b) return;
97 mDisplayModeIsPreserveMemory = b;
99 clitkExceptionMacro("TODO : not implemented yet");
101 InitializeCacheMode();
104 for(unsigned int d=0; d<mListOfCachedContourActors.size(); d++)
105 mListOfCachedContourActors[d].clear();
106 mListOfCachedContourActors.clear();
110 //------------------------------------------------------------------------------
113 //------------------------------------------------------------------------------
114 void vvImageContour::SetColor(double r, double g, double b) {
115 for(unsigned int i=0; i<mSquaresActorList.size(); i++) {
116 mSquaresActorList[i]->GetProperty()->SetColor(r,g,b);
119 //------------------------------------------------------------------------------
122 //------------------------------------------------------------------------------
123 void vvImageContour::SetLineWidth(double w)
125 for(unsigned int i=0; i<mSquaresActorList.size(); i++) {
126 mSquaresActorList[i]->GetProperty()->SetLineWidth(w);
129 //------------------------------------------------------------------------------
132 //------------------------------------------------------------------------------
133 void vvImageContour::HideActors() {
134 if (!mSlicer) return;
135 mSlice = mSlicer->GetSlice();
136 for(unsigned int i=0; i<mSquaresActorList.size(); i++) {
137 mSquaresActorList[i]->VisibilityOff();
140 //------------------------------------------------------------------------------
143 //------------------------------------------------------------------------------
144 void vvImageContour::ShowActors() {
145 if (!mSlicer) return;
146 mSlice = mSlicer->GetSlice();
147 mTSlice = mSlicer->GetTSlice();
148 mSquaresActorList[mTSlice]->VisibilityOn();
151 //------------------------------------------------------------------------------
154 //------------------------------------------------------------------------------
155 void vvImageContour::SetDepth(double d)
158 // Move the actor to be visible
159 double position[3] = {0, 0, 0};
160 int orientation = ComputeCurrentOrientation();
161 position[orientation] = -mDepth;
163 for(unsigned int i=0; i<mSquaresActorList.size(); i++)
164 mSquaresActorList[i]->SetPosition(position);
166 //------------------------------------------------------------------------------
168 //------------------------------------------------------------------------------
169 void vvImageContour::Update(double value) {
170 if (!mSlicer) return;
171 if (mPreviousValue == value) {
172 if (mPreviousSlice == mSlicer->GetSlice()) {
173 if (mPreviousTSlice == mSlicer->GetTSlice()) {
174 if (mPreviousOrientation == ComputeCurrentOrientation()) {
175 return; // Nothing to do
181 // Get current threshold value
185 mSlice = mSlicer->GetSlice();
187 if (mDisplayModeIsPreserveMemory) {
188 UpdateWithPreserveMemoryMode();
191 UpdateWithFastCacheMode();
194 //mSlicer->Render(); //DS ---> REMOVE ??
196 mPreviousTSlice = mSlicer->GetTSlice();
197 mPreviousSlice = mSlicer->GetSlice();
198 mPreviousValue = value;
199 mPreviousOrientation = ComputeCurrentOrientation();
201 //------------------------------------------------------------------------------
204 //------------------------------------------------------------------------------
205 void vvImageContour::UpdateWithPreserveMemoryMode() {
206 // Only change actor visibility if tslice change
207 mPreviousTslice = mTSlice;
208 mTSlice = mSlicer->GetTSlice();
210 vtkMarchingSquares * mSquares = mSquaresList[mTSlice];
211 vtkPolyDataMapper* mapper = mSquaresMapperList[mTSlice];
212 vtkImageClip * mClipper = mClipperList[mTSlice];
213 vtkActor * mSquaresActor = mSquaresActorList[mTSlice];
214 int orientation = ComputeCurrentOrientation();
216 UpdateActor(mSquaresActor, mapper, mSquares, mClipper, mValue, orientation, mSlice);
218 if (mPreviousTslice != mTSlice) {
219 if (mPreviousTslice != -1) mSquaresActorList[mPreviousTslice]->VisibilityOff();
224 //------------------------------------------------------------------------------
227 //------------------------------------------------------------------------------
228 void vvImageContour::InitializeCacheMode() {
229 clitkExceptionMacro("TODO : not implemented yet");
230 mPreviousSlice = mPreviousOrientation = 0;
231 int dim = mSlicer->GetImage()->GetNumberOfDimensions();
233 mListOfCachedContourActors.resize(dim);
234 for(int d=0; d<dim; d++) {
235 int size = mSlicer->GetImage()->GetSize()[d];
236 mListOfCachedContourActors[d].resize(size);
237 for(int j=0; j<size; j++) {
238 mListOfCachedContourActors[d][j] = NULL;
242 //------------------------------------------------------------------------------
245 //------------------------------------------------------------------------------
246 int vvImageContour::ComputeCurrentOrientation() {
247 // Get extent of image in the slicer
248 int* extent = mSlicer->GetImageActor()->GetDisplayExtent();
250 // Compute orientation
252 for (orientation = 0; orientation < 6; orientation = orientation+2) {
253 if (extent[orientation] == extent[orientation+1]) {
257 orientation = orientation/2;
260 //------------------------------------------------------------------------------
263 //------------------------------------------------------------------------------
264 void vvImageContour::UpdateWithFastCacheMode() {
265 clitkExceptionMacro("TODO : not implemented yet");
267 // Compute orientation
268 int orientation = ComputeCurrentOrientation();
270 if ((mPreviousSlice == mSlice) && (mPreviousOrientation == orientation)) return;
272 vtkActor * actor = mListOfCachedContourActors[orientation][mSlice];
274 mListOfCachedContourActors[orientation][mSlice]->VisibilityOn();
277 //SR: commented out, this code is never reached anyway
278 //UpdateActor(mSquaresActor, mSquares, mClipper, mValue, orientation, mSlice);
279 //mListOfCachedContourActors[orientation][mSlice] = mSquaresActor;
280 //mSquaresActor->VisibilityOn();
283 if (mListOfCachedContourActors[mPreviousOrientation][mPreviousSlice] != NULL)
284 mListOfCachedContourActors[mPreviousOrientation][mPreviousSlice]->VisibilityOff();
285 mPreviousSlice = mSlice;
286 mPreviousOrientation = orientation;
288 //------------------------------------------------------------------------------
291 //------------------------------------------------------------------------------
292 void vvImageContour::CreateNewActor(int numImage) {
293 vtkSmartPointer<vtkActor> squaresActor = vtkSmartPointer<vtkActor>::New();
294 vtkSmartPointer<vtkImageClip> clipper = vtkSmartPointer<vtkImageClip>::New();
295 vtkSmartPointer<vtkMarchingSquares> squares = vtkSmartPointer<vtkMarchingSquares>::New();
296 vtkSmartPointer<vtkPolyDataMapper> squaresMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
298 if (mHiddenImageIsUsed)
299 clipper->SetInput(mHiddenImage->GetVTKImages()[0]);
301 clipper->SetInput(mSlicer->GetImage()->GetVTKImages()[numImage]);
303 squares->SetInput(clipper->GetOutput());
304 squaresMapper->SetInput(squares->GetOutput());
305 squaresMapper->ScalarVisibilityOff();
306 squaresActor->SetMapper(squaresMapper);
307 squaresActor->GetProperty()->SetColor(1.0,0,0);
308 squaresActor->SetPickable(0);
309 squaresActor->VisibilityOff();
310 mSlicer->GetRenderer()->AddActor(squaresActor);
312 mSquaresActorList.push_back(squaresActor);
313 mClipperList.push_back(clipper);
314 mSquaresList.push_back(squares);
315 mSquaresMapperList.push_back(squaresMapper);
317 //------------------------------------------------------------------------------
320 //------------------------------------------------------------------------------
321 void vvImageContour::UpdateActor(vtkActor * actor,
322 vtkPolyDataMapper * mapper,
323 vtkMarchingSquares * squares,
324 vtkImageClip * clipper,
325 double threshold, int orientation, int slice) {
326 // Set parameter for the MarchigSquare
327 squares->SetValue(0, threshold);
330 int* extent = mSlicer->GetImageActor()->GetDisplayExtent();
332 // Change extent if needed
334 if (mHiddenImageIsUsed) {
335 extent2 = new int[6];
337 extent3 = mHiddenImage->GetFirstVTKImageData()->GetExtent();
339 for(int i=0; i<6; i++) extent2[i] = extent3[i];
341 double s = (double)extent[orientation*2]*(double)mSlicer->GetImage()->GetSpacing()[orientation]; // in mm
342 s = s+mSlicer->GetImage()->GetOrigin()[orientation]; // from origin
343 s = s-mHiddenImage->GetFirstVTKImageData()->GetOrigin()[orientation]; // from corner second image
344 s = s/mHiddenImage->GetFirstVTKImageData()->GetSpacing()[orientation]; // in voxel
346 // Rint to the closest slice
347 extent2[orientation*2+1] = extent2[orientation*2] = (int)lrint(s);
349 // Do not display a contour if there is no contour on this slice
350 // DD(extent2[orientation*2+1]);
351 // DD(extent3[orientation*2+1]);
352 // DD(extent2[orientation*2]);
353 // DD(extent3[orientation*2]);
354 if ((extent2[orientation*2+1] > extent3[orientation*2+1]) ||
355 (extent2[orientation*2] < extent3[orientation*2])) {
356 actor->VisibilityOff();
359 else actor->VisibilityOn();
363 actor->VisibilityOn();
366 clipper->SetOutputWholeExtent(extent2[0],extent2[1],extent2[2],
367 extent2[3],extent2[4],extent2[5]);
369 if (mHiddenImageIsUsed) delete extent2;
371 // Move the actor to be visible
373 // double position[3] = {0, 0, 0};
375 // position[orientation] = -mDepth;
376 // actor->SetPosition(position);
380 //------------------------------------------------------------------------------