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)
157 // Move the actor to be visible
158 double position[3] = {0, 0, 0};
159 int orientation = ComputeCurrentOrientation();
160 position[orientation] = -mDepth;
162 for(unsigned int i=0; i<mSquaresActorList.size(); i++)
163 mSquaresActorList[i]->SetPosition(position);
165 //------------------------------------------------------------------------------
167 //------------------------------------------------------------------------------
168 void vvImageContour::Update(double value) {
169 if (!mSlicer) return;
170 if (mPreviousValue == value) {
171 if (mPreviousSlice == mSlicer->GetSlice()) {
172 if (mPreviousTSlice == mSlicer->GetTSlice()) {
173 if (mPreviousOrientation == ComputeCurrentOrientation()) {
174 return; // Nothing to do
180 // Get current threshold value
184 mSlice = mSlicer->GetSlice();
186 if (mDisplayModeIsPreserveMemory) {
187 UpdateWithPreserveMemoryMode();
190 UpdateWithFastCacheMode();
193 //mSlicer->Render(); //DS ---> REMOVE ??
195 mPreviousTSlice = mSlicer->GetTSlice();
196 mPreviousSlice = mSlicer->GetSlice();
197 mPreviousValue = value;
198 mPreviousOrientation = ComputeCurrentOrientation();
200 //------------------------------------------------------------------------------
203 //------------------------------------------------------------------------------
204 void vvImageContour::UpdateWithPreserveMemoryMode() {
205 // Only change actor visibility if tslice change
206 mPreviousTslice = mTSlice;
207 mTSlice = mSlicer->GetTSlice();
209 vtkMarchingSquares * mSquares = mSquaresList[mTSlice];
210 vtkPolyDataMapper* mapper = mSquaresMapperList[mTSlice];
211 vtkImageClip * mClipper = mClipperList[mTSlice];
212 vtkActor * mSquaresActor = mSquaresActorList[mTSlice];
213 int orientation = ComputeCurrentOrientation();
215 UpdateActor(mSquaresActor, mapper, mSquares, mClipper, mValue, orientation, mSlice);
217 if (mPreviousTslice != mTSlice) {
218 if (mPreviousTslice != -1) mSquaresActorList[mPreviousTslice]->VisibilityOff();
223 //------------------------------------------------------------------------------
226 //------------------------------------------------------------------------------
227 void vvImageContour::InitializeCacheMode() {
228 clitkExceptionMacro("TODO : not implemented yet");
229 mPreviousSlice = mPreviousOrientation = 0;
230 int dim = mSlicer->GetImage()->GetNumberOfDimensions();
232 mListOfCachedContourActors.resize(dim);
233 for(int d=0; d<dim; d++) {
234 int size = mSlicer->GetImage()->GetSize()[d];
235 mListOfCachedContourActors[d].resize(size);
236 for(int j=0; j<size; j++) {
237 mListOfCachedContourActors[d][j] = NULL;
241 //------------------------------------------------------------------------------
244 //------------------------------------------------------------------------------
245 int vvImageContour::ComputeCurrentOrientation() {
246 // Get extent of image in the slicer
247 int* extent = mSlicer->GetImageActor()->GetDisplayExtent();
249 // Compute orientation
251 for (orientation = 0; orientation < 6; orientation = orientation+2) {
252 if (extent[orientation] == extent[orientation+1]) {
256 orientation = orientation/2;
259 //------------------------------------------------------------------------------
262 //------------------------------------------------------------------------------
263 void vvImageContour::UpdateWithFastCacheMode() {
264 clitkExceptionMacro("TODO : not implemented yet");
266 // Compute orientation
267 int orientation = ComputeCurrentOrientation();
269 if ((mPreviousSlice == mSlice) && (mPreviousOrientation == orientation)) return;
271 vtkActor * actor = mListOfCachedContourActors[orientation][mSlice];
273 mListOfCachedContourActors[orientation][mSlice]->VisibilityOn();
276 //SR: commented out, this code is never reached anyway
277 //UpdateActor(mSquaresActor, mSquares, mClipper, mValue, orientation, mSlice);
278 //mListOfCachedContourActors[orientation][mSlice] = mSquaresActor;
279 //mSquaresActor->VisibilityOn();
282 if (mListOfCachedContourActors[mPreviousOrientation][mPreviousSlice] != NULL)
283 mListOfCachedContourActors[mPreviousOrientation][mPreviousSlice]->VisibilityOff();
284 mPreviousSlice = mSlice;
285 mPreviousOrientation = orientation;
287 //------------------------------------------------------------------------------
290 //------------------------------------------------------------------------------
291 void vvImageContour::CreateNewActor(int numImage) {
292 vtkSmartPointer<vtkActor> squaresActor = vtkSmartPointer<vtkActor>::New();
293 vtkSmartPointer<vtkImageClip> clipper = vtkSmartPointer<vtkImageClip>::New();
294 vtkSmartPointer<vtkMarchingSquares> squares = vtkSmartPointer<vtkMarchingSquares>::New();
295 vtkSmartPointer<vtkPolyDataMapper> squaresMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
297 if (mHiddenImageIsUsed)
298 clipper->SetInput(mHiddenImage->GetVTKImages()[0]);
300 clipper->SetInput(mSlicer->GetImage()->GetVTKImages()[numImage]);
302 squares->SetInput(clipper->GetOutput());
303 squaresMapper->SetInput(squares->GetOutput());
304 squaresMapper->ScalarVisibilityOff();
305 squaresActor->SetMapper(squaresMapper);
306 squaresActor->GetProperty()->SetColor(1.0,0,0);
307 squaresActor->SetPickable(0);
308 squaresActor->VisibilityOff();
309 mSlicer->GetRenderer()->AddActor(squaresActor);
311 mSquaresActorList.push_back(squaresActor);
312 mClipperList.push_back(clipper);
313 mSquaresList.push_back(squares);
314 mSquaresMapperList.push_back(squaresMapper);
316 //------------------------------------------------------------------------------
319 //------------------------------------------------------------------------------
320 void vvImageContour::UpdateActor(vtkActor * actor,
321 vtkPolyDataMapper * mapper,
322 vtkMarchingSquares * squares,
323 vtkImageClip * clipper,
324 double threshold, int orientation, int slice) {
325 // Set parameter for the MarchigSquare
326 squares->SetValue(0, threshold);
329 int* extent = mSlicer->GetImageActor()->GetDisplayExtent();
331 // Change extent if needed
333 if (mHiddenImageIsUsed) {
334 extent2 = new int[6];
336 extent3 = mHiddenImage->GetFirstVTKImageData()->GetExtent();
338 for(int i=0; i<6; i++) extent2[i] = extent3[i];
340 double s = (double)extent[orientation*2]*(double)mSlicer->GetImage()->GetSpacing()[orientation]; // in mm
341 s = s+mSlicer->GetImage()->GetOrigin()[orientation]; // from origin
342 s = s-mHiddenImage->GetFirstVTKImageData()->GetOrigin()[orientation]; // from corner second image
343 s = s/mHiddenImage->GetFirstVTKImageData()->GetSpacing()[orientation]; // in voxel
345 // Rint to the closest slice
346 extent2[orientation*2+1] = extent2[orientation*2] = (int)lrint(s);
348 // Do not display a contour if there is no contour on this slice
349 // DD(extent2[orientation*2+1]);
350 // DD(extent3[orientation*2+1]);
351 // DD(extent2[orientation*2]);
352 // DD(extent3[orientation*2]);
353 if ((extent2[orientation*2+1] > extent3[orientation*2+1]) ||
354 (extent2[orientation*2] < extent3[orientation*2])) {
355 actor->VisibilityOff();
358 else actor->VisibilityOn();
362 actor->VisibilityOn();
365 clipper->SetOutputWholeExtent(extent2[0],extent2[1],extent2[2],
366 extent2[3],extent2[4],extent2[5]);
368 if (mHiddenImageIsUsed) delete extent2;
370 // Move the actor to be visible
372 // double position[3] = {0, 0, 0};
374 // position[orientation] = -mDepth;
375 // actor->SetPosition(position);
379 //------------------------------------------------------------------------------