fw4spl
SSliceFollowerCamera.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2017.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "visuVTKAdaptor/SSliceFollowerCamera.hpp"
8 
9 #include <fwCom/Slot.hpp>
10 #include <fwCom/Slot.hxx>
11 #include <fwCom/Slots.hpp>
12 #include <fwCom/Slots.hxx>
13 
14 #include <fwDataTools/fieldHelper/MedicalImageHelpers.hpp>
15 
16 #include <fwServices/macros.hpp>
17 
18 #include <vtkActor.h>
19 #include <vtkCamera.h>
20 #include <vtkInteractorStyleImage.h>
21 #include <vtkMath.h>
22 #include <vtkMatrix4x4.h>
23 #include <vtkRenderer.h>
24 #include <vtkRenderWindowInteractor.h>
25 #include <vtkTransform.h>
26 
28 
29 namespace visuVTKAdaptor
30 {
31 
32 static const ::fwCom::Slots::SlotKeyType s_UPDATE_SLICE_INDEX_SLOT = "updateSliceIndex";
33 static const ::fwCom::Slots::SlotKeyType s_UPDATE_SLICE_TYPE_SLOT = "updateSliceType";
34 
35 static const ::fwServices::IService::KeyType s_IMAGE_INOUT = "image";
36 
37 //------------------------------------------------------------------------------
38 
39 SSliceFollowerCamera::SSliceFollowerCamera() noexcept :
40  m_camera(nullptr)
41 {
42  newSlot(s_UPDATE_SLICE_INDEX_SLOT, &SSliceFollowerCamera::updateSliceIndex, this);
43  newSlot(s_UPDATE_SLICE_TYPE_SLOT, &SSliceFollowerCamera::updateSliceType, this);
44 }
45 
46 //------------------------------------------------------------------------------
47 
48 SSliceFollowerCamera::~SSliceFollowerCamera() noexcept
49 {
50 }
51 
52 //------------------------------------------------------------------------------
53 
55 {
56  this->configureParams();
57 
58  const ConfigType config = this->getConfigTree().get_child("config.<xmlattr>");
59 
60  const std::string orientation = config.get<std::string>("sliceIndex", "axial");
61  if(orientation == "axial" )
62  {
63  m_orientation = Z_AXIS;
64  }
65  else if(orientation == "frontal" )
66  {
67  m_orientation = Y_AXIS;
68  }
69  else if(orientation == "sagittal" )
70  {
71  m_orientation = X_AXIS;
72  }
73 }
74 
75 //------------------------------------------------------------------------------
76 
78 {
79  this->initialize();
80 
81  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
82  SLM_ASSERT("Missing image", image);
83 
84  this->updateImageInfos(image);
85 
86  m_camera = this->getRenderer()->GetActiveCamera();
87  this->initializeCamera();
88  this->updating();
89 }
90 
91 //------------------------------------------------------------------------------
92 
94 {
95  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
96  SLM_ASSERT("Missing image", image);
97 
98  this->updateImageInfos(image);
99  this->initializeCamera();
100 }
101 
102 //------------------------------------------------------------------------------
103 
105 {
106  this->unregisterServices();
107 }
108 
109 //-----------------------------------------------------------------------------
110 
111 void SSliceFollowerCamera::updateSliceIndex(int /*axial*/, int /*frontal*/, int /*sagittal*/)
112 {
113  this->updateCamera();
114 }
115 
116 //-----------------------------------------------------------------------------
117 
118 void SSliceFollowerCamera::updateSliceType(int from, int to)
119 {
120  if( to == static_cast<int>(m_orientation) )
121  {
122  setOrientation( static_cast< Orientation >( from ));
123  }
124  else if(from == static_cast<int>(m_orientation))
125  {
126  setOrientation( static_cast< Orientation >( to ));
127  }
128  this->initializeCamera();
129  this->requestRender();
130 }
131 
132 //------------------------------------------------------------------------------
133 
134 void SSliceFollowerCamera::initializeCamera()
135 {
136  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
137  SLM_ASSERT("Missing image", image);
138 
140 
141  if (imageIsValid)
142  {
143  const int orientationToAxe[3] = { 2, 2, 1 };
144  double imageSize[3];
145  this->getImageSize(imageSize);
146  int orientation = orientationToAxe [m_orientation];
147  double size = imageSize[ orientation ];
148 
149  double distance = (1.1 * size)
150  / ( std::tan( m_camera->GetViewAngle() * (vtkMath::Pi() / 180.0) ) );
151 
152  m_camera->ParallelProjectionOn();
154 
155  this->updateCamera(distance, size);
156  }
157 }
158 
159 //------------------------------------------------------------------------------
160 
161 void SSliceFollowerCamera::updateCamera(double distance, double size)
162 {
163  SLM_ASSERT("No Camera", m_camera );
164 
165  if (distance > 0)
166  {
167  // Update position according to orientation
168  double center[ 3 ];
169  double focalPoint[ 3 ];
170  double position[ 3 ];
171  getCurrentSliceCenter( center );
172  std::copy(center, center+3, focalPoint);
173 
174  double origin[ 3 ];
175  getImageOrigin( origin );
176  focalPoint[m_orientation] = origin[m_orientation];
177 
178  distance = m_camera->GetDistance();
179 
180  std::copy(focalPoint, focalPoint+3, position);
181 
182  position[ m_orientation ] -= distance;
183 
184  m_camera->SetParallelScale(.51*size);
185  m_camera->SetFocalPoint( focalPoint );
186  m_camera->SetPosition( position );
187  }
188 
189  // m_orientation = 0 : 0, 0,1
190  // m_orientation = 1 : 0, 0,1
191  // m_orientation = 2 : 0,-1,0
192  m_camera->SetViewUp(
193  0,
194  (m_orientation == 2 ? -1 : 0),
195  (m_orientation <= 1 ? 1 : 0)
196  );
197  m_camera->OrthogonalizeViewUp();
198 
199  this->getRenderer()->ResetCameraClippingRange();
200  this->setVtkPipelineModified();
201 }
202 
203 //------------------------------------------------------------------------------
204 
206 {
207  KeyConnectionsMap connections;
208  connections.push(s_IMAGE_INOUT, ::fwData::Image::s_MODIFIED_SIG, s_UPDATE_SLOT);
209  connections.push(s_IMAGE_INOUT, ::fwData::Image::s_SLICE_INDEX_MODIFIED_SIG, s_UPDATE_SLICE_INDEX_SLOT);
210  connections.push(s_IMAGE_INOUT, ::fwData::Image::s_SLICE_TYPE_MODIFIED_SIG, s_UPDATE_SLICE_TYPE_SLOT);
211 
212  return connections;
213 }
214 
215 //------------------------------------------------------------------------------
216 
217 } //namespace visuVTKAdaptor
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_SLICE_INDEX_MODIFIED_SIG
Type of signal when image&#39;s buffer is added.
This class is a helper to define the connections of a service and its data.
Definition: IService.hpp:454
virtual VISUVTKADAPTOR_API KeyConnectionsMap getAutoConnections() const override
Returns proposals to connect service slots to associated object signals, this method is used for obj/...
VISUVTKADAPTOR_API void updating() override
Perform some computations according to object (this service is attached to) attribute values and its ...
FWRENDERVTK_API vtkRenderer * getRenderer()
Returns the renderer.
The namespace visuVTKAdaptor contains the list of adaptors available for the generic scene...
FWRENDERVTK_API void configureParams()
Parse the xml configuration for renderer, picker and transform.
virtual FWDATATOOLS_API void setOrientation(Orientation orientation)
Set the image orientation.
FWDATATOOLS_API void getImageSize(double size[3]) const
Get the image size ( = dataSize * spacing ).
FWRENDERVTK_API void requestRender()
notify a render request iff vtkPipeline is modified
FWRENDERVTK_API void setVtkPipelineModified()
End-user have to call this method when a vtk structure has been modified, thus a render request will ...
VISUVTKADAPTOR_API void starting() override
Initialize the service activity.
Update the camera according to slice move.
FWDATATOOLS_API void getCurrentSliceCenter(double center[3])
Get the slice center.
Orientation m_orientation
Image orientation.
FWSERVICES_API void unregisterServices(const std::string &_implType="")
Unregister all services linked to this service, optionally matches only a given type of services...
FWDATATOOLS_API void updateImageInfos(::fwData::Image::sptr image)
Update the image information (slice index, min/max,...)
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308
VISUVTKADAPTOR_API void configuring() override
Configure the service before starting. Apply the configuration to service.
FWDATATOOLS_API void getImageOrigin(double origin[3]) const
Get the image origin.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_MODIFIED_SIG
Key in m_signals map of signal m_sigModified.
static FWDATATOOLS_API bool checkImageValidity(::fwData::Image::csptr _pImg)
Check if the image is valid.
FWRENDERVTK_API void initialize()
Initialize the adaptor with the associated render service. (must be call in starting).
This class defines an image.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_SLICE_TYPE_MODIFIED_SIG
Type of signal when image&#39;s buffer is added.
static FWSERVICES_APIconst::fwCom::Slots::SlotKeyType s_UPDATE_SLOT
Slot to call start method.
Definition: IService.hpp:177
VISUVTKADAPTOR_API void stopping() override
Uninitialize the service activity. The stop() method is always invoked before destroying a service...
FWSERVICES_API ConfigType getConfigTree() const
Return the configuration, in an boost property tree.
Definition: IService.cpp:247