3
* $Id: volumepipeline.cpp 3558 2011-03-20 20:02:22Z carlos $
6
* Copyright 2008-10 MetaEmotion S.L. All rights reserved.
7
* http://ginkgo-cadx.com
9
* This file is licensed under LGPL v3 license.
10
* See License.txt for details
17
#include "volumepipeline.h"
18
#include "../volumedataset/volumedataset.h"
21
#include <wx/window.h>
22
#include <api/internacionalizacion.h>
23
#include <main/controllers/controladorlog.h>
29
#include <vtkCommand.h>
30
#include <vtkImageData.h>
31
#include <vtkRenderer.h>
32
#include <vtkImageData.h>
33
#include <vtkRenderer.h>
34
#include <vtkImageResample.h>
35
#include <vtkImageData.h>
36
#include <vtkRenderer.h>
37
#include <vtkImageResample.h>
38
#include <vtkVolume.h>
39
#include <vtkSmartVolumeMapper.h>
40
#include <vtkColorTransferFunction.h>
41
#include <vtkPiecewiseFunction.h>
42
#include <vtkVolumeProperty.h>
43
#include <vtkImageReslice.h>
45
#include <vtkCamera.h>
46
#include <vtkProperty.h>
47
#include <vtkRenderWindow.h>
48
#include <vtkRenderWindowInteractor.h>
50
#include <vtkWindowToImageFilter.h>
51
#include <vtkJPEGWriter.h>
53
#include "../interactors/reconstructioninteractor.h"
54
#include <vtkInteractorStyleTrackballCamera.h>
56
class InteractionCommand : public vtkCommand
60
typedef MedicalViewer::Reconstruction::Pipelines::VolumePipeline TPipeline;
61
typedef GinkgoInteractorStyleReconstruction TStyleReconstruction;
63
InteractionCommand() : Pipeline(NULL), InitialWindow(0), InitialLevel(0), WindowEventStatus(false)
68
static InteractionCommand* New()
70
return new InteractionCommand();
73
void SetPipeline(TPipeline* pipeline)
78
void Execute(vtkObject * caller,
83
if (this->Pipeline == NULL)
88
if (event == vtkCommand::StartWindowLevelEvent) {
89
if (this->Pipeline->IsInitiallized() ) {
93
this->StartWindowing();
97
if (event == vtkCommand::EndWindowLevelEvent) {
103
if (event == vtkCommand::WindowLevelEvent) {
105
this->Windowing( (TStyleReconstruction*) caller);
115
void Windowing(TStyleReconstruction* p_isi)
122
double window = this->InitialWindow;
123
double level = this->InitialLevel;
124
double EPS = std::numeric_limits<double>::epsilon();
127
double dx = p_isi->GetWindowStep();
128
double dy = p_isi->GetLevelStep();
130
// Scale by current values
131
if (fabs(window) > EPS)
137
dx = dx * (window < 0 ? -EPS : EPS);
140
if (fabs(level) > EPS)
146
dy = dy * (level < 0 ? -EPS : EPS);
149
// Abs so that direction does not flip
159
// Compute new window level
160
double newWindow = dx + window;
161
double newLevel = level - dy;
163
// Stay away from zero and really
164
if (fabs(newWindow) < EPS)
166
newWindow = EPS * (newWindow < 0 ? -1 : 1);
169
if (fabs(newLevel) < EPS)
171
newLevel = EPS * (newLevel < 0 ? -1 : 1);
174
this->Pipeline->UpdateBlending(newWindow, newLevel);
177
void StartWindowing()
179
this->InitialWindow = this->Pipeline->Window;
180
this->InitialLevel = this->Pipeline->Level;
191
double InitialWindow;
194
bool WindowEventStatus;
199
//==============================================================================================
201
namespace MedicalViewer {
202
namespace Reconstruction {
203
namespace Pipelines {
205
class VolumeCommandObserver : public vtkCommand
209
static VolumeCommandObserver* New() {
210
return new VolumeCommandObserver();
213
void SetInformation(const std::string& text)
218
void SetNotifier(IReconstructionNotifier* notifier)
223
virtual void Execute(vtkObject* caller, unsigned long, void *callData) {
224
double dProgress = *( (double*)(callData) );
225
vtkAlgorithm* alg = (vtkAlgorithm* ) caller;
227
if (! Notifier->NotifyReconstructionProgress( Text, (float)dProgress) ){
228
alg->AbortExecuteOn();
235
IReconstructionNotifier* Notifier;
241
MedicalViewer::Reconstruction::Pipelines::VolumePipeline::VolumePipeline(wxWindow* win3d) : IPipeline("Reconstruction/Surface", win3d)
244
CurrentBlendType = VBT_MIP;
245
vtkSmartPointer<VolumeCommandObserver> Progress;
247
Renderer->SetBackground(0.0, 0.0, 0.0);
249
Resample = vtkSmartPointer<vtkImageResample>::New();
251
Volume = vtkSmartPointer<vtkVolume>::New();
252
Mapper = vtkSmartPointer<vtkSmartVolumeMapper>::New();
253
Mapper->SetRequestedRenderMode(vtkSmartVolumeMapper::RayCastRenderMode);
254
Mapper->SetInputConnection( Resample->GetOutputPort() );
256
ColorTransferFunction = vtkSmartPointer<vtkColorTransferFunction>::New();
257
OpacityTransferFunction = vtkSmartPointer<vtkPiecewiseFunction>::New();
259
VolumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
261
VolumeProperty->SetColor( ColorTransferFunction );
262
VolumeProperty->SetScalarOpacity( OpacityTransferFunction );
263
VolumeProperty->SetInterpolationTypeToLinear();
265
Volume->SetProperty( VolumeProperty );
266
Volume->SetMapper( Mapper );
267
Volume->VisibilityOff();
269
Renderer->AddVolume(Volume);
271
Interactor = vtkSmartPointer<GinkgoInteractorStyleReconstruction>::New();
275
Progress = vtkSmartPointer<VolumeCommandObserver>::New();
276
Progress->SetInformation("Resampling volume");
277
Resample->AddObserver(vtkCommand::ProgressEvent, Progress);
278
Progresses.push_back(Progress);
280
Progress = vtkSmartPointer<VolumeCommandObserver>::New();
281
Progress->SetInformation("Computing volume");
282
Volume->AddObserver(vtkCommand::ProgressEvent, Progress);
283
Progresses.push_back(Progress);
285
Progress = vtkSmartPointer<VolumeCommandObserver>::New();
286
Progress->SetInformation("Mapping volume");
287
Mapper->AddObserver(vtkCommand::ProgressEvent, Progress);
288
Progresses.push_back(Progress);
293
MedicalViewer::Reconstruction::Pipelines::VolumePipeline::~VolumePipeline()
297
void MedicalViewer::Reconstruction::Pipelines::VolumePipeline::SetupInteractor()
300
vtkSmartPointer<InteractionCommand> cbk = vtkSmartPointer<InteractionCommand>::New();
301
cbk->SetPipeline(this);
302
//Interactor->AddObserver(vtkCommand::KeyPressEvent, cbk);
303
Interactor->AddObserver(vtkCommand::WindowLevelEvent, cbk);
304
Interactor->AddObserver(vtkCommand::StartWindowLevelEvent, cbk);
305
Interactor->AddObserver(vtkCommand::ResetWindowLevelEvent, cbk);
306
Interactor->AddObserver(vtkCommand::EndWindowLevelEvent, cbk);
307
//Interactor->AddObserver(InteractionCommand::ZoomEvent, cbk);
308
SetInteractorStyleToDefault();
312
void MedicalViewer::Reconstruction::Pipelines::VolumePipeline::SetInteractorStyleToDefault()
314
Renderer->GetRenderWindow()->GetInteractor()->SetInteractorStyle(vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New());
317
void MedicalViewer::Reconstruction::Pipelines::VolumePipeline::SetInteractorStyleToWindowLevel()
319
Renderer->GetRenderWindow()->GetInteractor()->SetInteractorStyle(Interactor);
322
void MedicalViewer::Reconstruction::Pipelines::VolumePipeline::SetWindowLevel(double window, double level)
324
SettedWindow = Window = window;
325
SettedLevel = Level = level;
328
void MedicalViewer::Reconstruction::Pipelines::VolumePipeline::ResetWindowLevel()
330
Window = SettedWindow;
332
if (CurrentBlendType < VBT_RGB_Composite) {
333
SetBlendingType(CurrentBlendType);
337
void MedicalViewer::Reconstruction::Pipelines::VolumePipeline::UpdateBlending(double window, double level)
341
if (CurrentBlendType < VBT_RGB_Composite) {
342
SetBlendingType(CurrentBlendType);
348
void MedicalViewer::Reconstruction::Pipelines::VolumePipeline::SetBlendingType(VolumeBlendType blendType) {
350
case VBT_CompositeRamp:
351
SetBlendingToCompositeRamp();
353
case VBT_CompositeShadeRamp:
354
SetBlendingToCompositeShadeRamp();
356
case VBT_RGB_Composite:
357
SetBlendingToRGBComposite();
360
SetBlendingToCTSkin();
363
SetBlendingToCTMuscle();
366
SetBlendingToCTBone();
373
CurrentBlendType = blendType;
376
void MedicalViewer::Reconstruction::Pipelines::VolumePipeline::SetBlendingToMIP()
378
ColorTransferFunction->RemoveAllPoints();
379
OpacityTransferFunction->RemoveAllPoints();
380
OpacityTransferFunction->Modified();
381
ColorTransferFunction->Modified();
383
ColorTransferFunction->AddRGBSegment(0.0, 1.0, 1.0, 1.0, 255.0, 1.0, 1.0, 1.0 );
384
OpacityTransferFunction->AddSegment( Level - 0.5 * Window, 0.0,
385
Level + 0.5 * Window, 1.0 );
386
Mapper->SetBlendModeToMaximumIntensity();
389
void MedicalViewer::Reconstruction::Pipelines::VolumePipeline::SetBlendingToCompositeRamp()
391
ColorTransferFunction->RemoveAllPoints();
392
OpacityTransferFunction->RemoveAllPoints();
393
OpacityTransferFunction->Modified();
394
ColorTransferFunction->Modified();
396
ColorTransferFunction->AddRGBSegment(Level - 0.5 * Window, 0.0, 0.0, 0.0, Level + 0.5*Window, 1.0, 1.0, 1.0 );
397
OpacityTransferFunction->AddSegment( Level - 0.5 * Window, 0.0, Level + 0.5 * Window, 1.0 );
398
Mapper->SetBlendModeToComposite();
399
VolumeProperty->ShadeOff();
402
void MedicalViewer::Reconstruction::Pipelines::VolumePipeline::SetBlendingToCompositeShadeRamp()
404
ColorTransferFunction->RemoveAllPoints();
405
OpacityTransferFunction->RemoveAllPoints();
406
OpacityTransferFunction->Modified();
407
ColorTransferFunction->Modified();
409
ColorTransferFunction->AddRGBSegment(0.0, 1.0, 1.0, 1.0, 255.0, 1.0, 1.0, 1.0 );
410
OpacityTransferFunction->AddSegment( Level - 0.5 * Window, 0.0, Level + 0.5 * Window, 1.0 );
411
Mapper->SetBlendModeToComposite();
412
VolumeProperty->ShadeOn();
415
void MedicalViewer::Reconstruction::Pipelines::VolumePipeline::SetBlendingToRGBComposite()
417
ColorTransferFunction->RemoveAllPoints();
418
OpacityTransferFunction->RemoveAllPoints();
419
OpacityTransferFunction->Modified();
420
ColorTransferFunction->Modified();
422
OpacityTransferFunction->AddPoint(0, 0.0);
423
OpacityTransferFunction->AddPoint(5.0, 0.0);
424
OpacityTransferFunction->AddPoint(30.0, 0.05);
425
OpacityTransferFunction->AddPoint(31.0, 0.0);
426
OpacityTransferFunction->AddPoint(90.0, 0.0);
427
OpacityTransferFunction->AddPoint(100.0, 0.3);
428
OpacityTransferFunction->AddPoint(110.0, 0.0);
429
OpacityTransferFunction->AddPoint(190.0, 0.0);
430
OpacityTransferFunction->AddPoint(200.0, 0.4);
431
OpacityTransferFunction->AddPoint(210.0, 0.0);
432
OpacityTransferFunction->AddPoint(245.0, 0.0);
433
OpacityTransferFunction->AddPoint(255.0, 0.5);
435
Mapper->SetBlendModeToComposite();
436
VolumeProperty->ShadeOff();
437
VolumeProperty->SetScalarOpacityUnitDistance(1.0);
440
void MedicalViewer::Reconstruction::Pipelines::VolumePipeline::SetBlendingToCTSkin()
442
ColorTransferFunction->RemoveAllPoints();
443
OpacityTransferFunction->RemoveAllPoints();
444
OpacityTransferFunction->Modified();
445
ColorTransferFunction->Modified();
447
ColorTransferFunction->AddRGBPoint( -3024, 0, 0, 0, 0.5, 0.0 );
448
ColorTransferFunction->AddRGBPoint( -1000, .62, .36, .18, 0.5, 0.0 );
449
ColorTransferFunction->AddRGBPoint( 100, .88, .60, .29, 0.33, 0.45 );
450
ColorTransferFunction->AddRGBPoint( 3071, .83, .66, 1, 0.5, 0.0 );
452
OpacityTransferFunction->AddPoint(-3024, 0, 0.5, 0.0 );
453
OpacityTransferFunction->AddPoint(-1000, 0, 0.5, 0.0 );
454
OpacityTransferFunction->AddPoint(100, 1.0, 0.33, 0.45 );
455
OpacityTransferFunction->AddPoint(3071, 1.0, 0.5, 0.0);
457
Mapper->SetBlendModeToComposite();
458
VolumeProperty->ShadeOn();
459
VolumeProperty->SetAmbient(0.1);
460
VolumeProperty->SetDiffuse(0.9);
461
VolumeProperty->SetSpecular(0.2);
462
VolumeProperty->SetSpecularPower(10.0);
463
VolumeProperty->SetScalarOpacityUnitDistance(0.8919);
466
void MedicalViewer::Reconstruction::Pipelines::VolumePipeline::SetBlendingToCTMuscle()
468
ColorTransferFunction->RemoveAllPoints();
469
OpacityTransferFunction->RemoveAllPoints();
470
OpacityTransferFunction->Modified();
471
ColorTransferFunction->Modified();
473
ColorTransferFunction->AddRGBPoint( -3024, 0, 0, 0, 0.5, 0.0 );
474
ColorTransferFunction->AddRGBPoint( -155, .55, .25, .15, 0.5, .92 );
475
ColorTransferFunction->AddRGBPoint( 217, .88, .60, .29, 0.33, 0.45 );
476
ColorTransferFunction->AddRGBPoint( 420, 1, .94, .95, 0.5, 0.0 );
477
ColorTransferFunction->AddRGBPoint( 3071, .83, .66, 1, 0.5, 0.0 );
479
OpacityTransferFunction->AddPoint(-3024, 0, 0.5, 0.0 );
480
OpacityTransferFunction->AddPoint(-155, 0, 0.5, 0.92 );
481
OpacityTransferFunction->AddPoint(217, .68, 0.33, 0.45 );
482
OpacityTransferFunction->AddPoint(420,.83, 0.5, 0.0);
483
OpacityTransferFunction->AddPoint(3071, .80, 0.5, 0.0);
485
Mapper->SetBlendModeToComposite();
486
VolumeProperty->ShadeOn();
487
VolumeProperty->SetAmbient(0.1);
488
VolumeProperty->SetDiffuse(0.9);
489
VolumeProperty->SetSpecular(0.2);
490
VolumeProperty->SetSpecularPower(10.0);
491
VolumeProperty->SetScalarOpacityUnitDistance(0.8919);
494
void MedicalViewer::Reconstruction::Pipelines::VolumePipeline::SetBlendingToCTBone()
496
ColorTransferFunction->RemoveAllPoints();
497
OpacityTransferFunction->RemoveAllPoints();
498
OpacityTransferFunction->Modified();
499
ColorTransferFunction->Modified();
501
ColorTransferFunction->AddRGBPoint( -3024, 0, 0, 0, 0.5, 0.0 );
502
ColorTransferFunction->AddRGBPoint( -16, 0.73, 0.25, 0.30, 0.49, .61 );
503
ColorTransferFunction->AddRGBPoint( 641, .90, .82, .56, .5, 0.0 );
504
ColorTransferFunction->AddRGBPoint( 3071, 1, 1, 1, .5, 0.0 );
506
OpacityTransferFunction->AddPoint(-3024, 0, 0.5, 0.0 );
507
OpacityTransferFunction->AddPoint(-16, 0, .49, .61 );
508
OpacityTransferFunction->AddPoint(641, .72, .5, 0.0 );
509
OpacityTransferFunction->AddPoint(3071, .71, 0.5, 0.0);
511
Mapper->SetBlendModeToComposite();
512
VolumeProperty->ShadeOn();
513
VolumeProperty->SetAmbient(0.1);
514
VolumeProperty->SetDiffuse(0.9);
515
VolumeProperty->SetSpecular(0.2);
516
VolumeProperty->SetSpecularPower(10.0);
517
VolumeProperty->SetScalarOpacityUnitDistance(0.8919);
520
void MedicalViewer::Reconstruction::Pipelines::VolumePipeline::SetDataSet(unsigned int volNum, double reductionFactor)
523
GnkPtr<TDataSet> vol = FindDataSet(volNum);
526
LOG_ERROR("Reconstruction/Volume", "Unable to set DataSet " << volNum << ": DataSet not found");
530
LOG_DEBUG("Reconstruction/Volume", "Setting DataSet " << volNum << ". Range = [ " << vol->MinValue << ", " << vol->MaxValue << " ]");
532
CurrentImage = vol->Img;
533
Window = (double)vol->MaxValue - (double)vol->MinValue;
534
Level = 0.5 * Window;
536
Resample->RemoveAllInputs();
537
Resample->SetInput(CurrentImage);
538
Resample->SetAxisMagnificationFactor(0, reductionFactor);
539
Resample->SetAxisMagnificationFactor(1, reductionFactor);
540
Resample->SetAxisMagnificationFactor(2, reductionFactor);
543
void MedicalViewer::Reconstruction::Pipelines::VolumePipeline::Enable(bool enable)
545
Volume->SetVisibility(enable? 1: 0);
548
void MedicalViewer::Reconstruction::Pipelines::VolumePipeline::Update()
551
LOG_DEBUG("VolumePipeline", _Std("Updating..."));
553
Resample->AbortExecuteOff();
554
Mapper->AbortExecuteOff();
563
LOG_DEBUG("VolumePipeline", _Std("Update done"));
566
void MedicalViewer::Reconstruction::Pipelines::VolumePipeline::SetProgressNotifier(IReconstructionNotifier* notifier)
568
for (TProgressList::iterator it = Progresses.begin(); it != Progresses.end(); it++) {
569
(*it)->SetNotifier(notifier);