fw4spl
STransformFromWheel.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2017-2018.
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/STransformFromWheel.hpp"
8 
9 #include <fwCom/Slot.hxx>
10 #include <fwCom/Slots.hxx>
11 
12 #include <fwDataTools/TransformationMatrix3D.hpp>
13 
14 #include <fwRenderVTK/vtk/Helpers.hpp>
15 
16 #include <fwServices/macros.hpp>
17 
18 #include <glm/gtc/matrix_transform.hpp>
19 #include <glm/vec3.hpp>
20 
21 #include <vtkAbstractPropPicker.h>
22 
23 namespace visuVTKAdaptor
24 {
25 
26 fwServicesRegisterMacro( ::fwRenderVTK::IAdaptor, ::visuVTKAdaptor::STransformFromWheel);
27 
28 static const ::fwCom::Slots::SlotKeyType s_ROTATE_TRANSFORM_SLOT = "rotateTransform";
29 static const ::fwCom::Slots::SlotKeyType s_TRANSLATE_TRANSFORM = "translateTransform";
30 static const ::fwCom::Slots::SlotKeyType s_UPDATE_SLICE_TYPE_SLOT = "updateSliceType";
31 
32 static const ::fwServices::IService::KeyType s_TRANSFORM_INOUT = "transform";
33 
34 //------------------------------------------------------------------------------
35 
36 STransformFromWheel::STransformFromWheel() :
37  m_orientation(::fwDataTools::helper::MedicalImageAdaptor::Orientation::Z_AXIS),
38  m_interactionMode(2),
39  m_initAngle(0.),
40  m_translate(false)
41 {
42  newSlot(s_ROTATE_TRANSFORM_SLOT, &STransformFromWheel::rotateTransform, this);
43  newSlot(s_TRANSLATE_TRANSFORM, &STransformFromWheel::translateTransform, this);
44  newSlot(s_UPDATE_SLICE_TYPE_SLOT, &STransformFromWheel::updateSliceOrientation, this);
45 }
46 
47 //------------------------------------------------------------------------------
48 
49 STransformFromWheel::~STransformFromWheel()
50 {
51 
52 }
53 
54 //------------------------------------------------------------------------------
55 
56 void STransformFromWheel::configuring()
57 {
58  this->configureParams();
59 
60  const ConfigType config = this->getConfigTree().get_child("config.<xmlattr>");
61  const std::string interactionMode = config.get<std::string>("mode", "2D");
62 
63  if(interactionMode == "2d" || interactionMode == "2D")
64  {
65  m_interactionMode = 2;
66  }
67  else if(interactionMode == "3d" || interactionMode == "3D")
68  {
69  m_interactionMode = 3;
70  }
71  else
72  {
73  SLM_WARN("Wrong interaction mode specified. Set to 2D.");
74  }
75 
76  const std::string orientation = config.get<std::string>("orientation", "");
77 
78  if(orientation == "axial")
79  {
80  m_orientation = ::fwDataTools::helper::MedicalImageAdaptor::Orientation::Z_AXIS;
81  }
82  else if(orientation == "sagittal")
83  {
84  m_orientation = ::fwDataTools::helper::MedicalImageAdaptor::Orientation::X_AXIS;
85  }
86  else if(orientation == "frontal")
87  {
88  m_orientation = ::fwDataTools::helper::MedicalImageAdaptor::Orientation::Y_AXIS;
89  }
90  else
91  {
92  SLM_FATAL("Unknown orientation: '" + orientation + "'.");
93  }
94 }
95 
96 //------------------------------------------------------------------------------
97 
98 void STransformFromWheel::starting()
99 {
100  this->initialize();
101 }
102 
103 //------------------------------------------------------------------------------
104 
105 void STransformFromWheel::updating()
106 {
107 
108 }
109 
110 //------------------------------------------------------------------------------
111 
112 void STransformFromWheel::stopping()
113 {
114 
115 }
116 
117 //------------------------------------------------------------------------------
118 
119 void STransformFromWheel::applyTransformToOutput(const glm::dmat4& transform) const
120 {
121  ::fwData::TransformationMatrix3D::sptr outTrans =
122  this->getInOut< ::fwData::TransformationMatrix3D >(s_TRANSFORM_INOUT);
123 
124  SLM_ASSERT("No 'transform' found.", outTrans);
125 
126  ::glm::dmat4 finalTransform = ::fwDataTools::TransformationMatrix3D::getMatrixFromTF3D(outTrans);
127  finalTransform = finalTransform * transform;
128 
130 
131  auto sig = outTrans->signal< ::fwData::TransformationMatrix3D::ModifiedSignalType >
133 
134  sig->asyncEmit();
135 }
136 
137 //------------------------------------------------------------------------------
138 
139 void STransformFromWheel::updateSliceOrientation(int from, int to)
140 {
141  if( to == static_cast< int > ( m_orientation ) )
142  {
143  m_orientation = static_cast< ::fwDataTools::helper::MedicalImageAdaptor::Orientation > ( from );
144  }
145  else if(from == static_cast<int>(m_orientation))
146  {
147  m_orientation = static_cast< ::fwDataTools::helper::MedicalImageAdaptor::Orientation >( to );
148  }
149 }
150 
151 //------------------------------------------------------------------------------
152 
153 void STransformFromWheel::rotateTransform(double cx, double cy, double wheelAngle)
154 {
155  const double angle = wheelAngle - m_initAngle;
156  m_initAngle = wheelAngle;
157 
158  // Get wheel position in image space.
159  vtkAbstractPropPicker* picker = this->getRenderService()->getPicker(m_pickerId);
160 
161  SLM_ASSERT("No picker named '" + m_pickerId + "'.", picker);
162 
163  double displayPosition[3] = { cx, cy, 0. };
164  picker->Pick( displayPosition, this->getRenderer());
165 
166  double worldPos[3];
167  ::fwRenderVTK::vtk::getNearestPickedPosition(picker, this->getRenderer(), worldPos);
168 
169  ::glm::dvec3 rotAxis;
170  ::glm::dvec3 pos(worldPos[0], worldPos[1], worldPos[2]);
171 
172  rotAxis[m_orientation] = 1.;
173 
174  if(m_interactionMode == 2)
175  {
176  switch (m_orientation)
177  {
178  case ::fwDataTools::helper::MedicalImageAdaptor::Orientation::Z_AXIS: break;
179  case ::fwDataTools::helper::MedicalImageAdaptor::Orientation::Y_AXIS:
180  rotAxis = -rotAxis;
181  pos = ::glm::dvec3(pos.x, pos.z, pos.y);
182  break;
183  case ::fwDataTools::helper::MedicalImageAdaptor::Orientation::X_AXIS:
184  pos = ::glm::dvec3(pos.z, pos.x, pos.y);
185  break;
186  }
187  }
188 
189  const ::glm::dmat4 invTransMat = ::glm::translate(::glm::dmat4(1.), pos);
190  const ::glm::dmat4 rotMat = ::glm::rotate(invTransMat, angle, rotAxis);
191  const ::glm::dmat4 centeredRot = ::glm::translate(rotMat, -pos);
192 
193  this->applyTransformToOutput(centeredRot);
194 }
195 
196 //------------------------------------------------------------------------------
197 
198 void STransformFromWheel::translateTransform(fwDataTools::PickingInfo info)
199 {
200  if(info.m_eventId == ::fwDataTools::PickingInfo::Event::MOUSE_LEFT_DOWN)
201  {
202  std::copy(info.m_worldPos, info.m_worldPos + 3, m_lastPickedPos);
203 
204  m_translate = true;
205  }
206  else if(m_translate && info.m_eventId == ::fwDataTools::PickingInfo::Event::MOUSE_MOVE)
207  {
208  ::glm::dvec3 transVec(m_lastPickedPos[0] - info.m_worldPos[0],
209  m_lastPickedPos[1] - info.m_worldPos[1],
210  m_lastPickedPos[2] - info.m_worldPos[2]);
211 
212  if(m_interactionMode == 2)
213  {
214  switch (m_orientation)
215  {
216  case ::fwDataTools::helper::MedicalImageAdaptor::Orientation::Z_AXIS: break;
217  case ::fwDataTools::helper::MedicalImageAdaptor::Orientation::Y_AXIS:
218  transVec = ::glm::dvec3(transVec.x, transVec.z, transVec.y);
219  break;
220  case ::fwDataTools::helper::MedicalImageAdaptor::Orientation::X_AXIS:
221  transVec = ::glm::dvec3(transVec.z, transVec.x, transVec.y);
222  break;
223  }
224  }
225 
226  const ::glm::dmat4 transMat = ::glm::translate(::glm::dmat4(1.), transVec);
227 
228  this->applyTransformToOutput(transMat);
229 
230  std::copy(info.m_worldPos, info.m_worldPos + 3, m_lastPickedPos);
231  }
232  else if(info.m_eventId == ::fwDataTools::PickingInfo::Event::MOUSE_LEFT_UP)
233  {
234  m_translate = false;
235  }
236 
237  this->requestRender();
238 }
239 
240 //------------------------------------------------------------------------------
241 
242 } // namespace visuVTKAdaptor
double m_worldPos[3]
Position clicked in world coordinates.
Definition: PickingInfo.hpp:44
static FWDATATOOLS_API void setTF3DFromMatrix(::fwData::TransformationMatrix3D::sptr &_trf, const ::glm::dmat4x4 &_input)
Convert a GLM matrix into a fwData::TransformationMatrix3D.
The namespace visuVTKAdaptor contains the list of adaptors available for the generic scene...
The namespace fwDataTools contains classes which provide helpers to manipulate fwData::Object. *.
#define SLM_WARN(message)
Definition: spyLog.hpp:261
#define SLM_FATAL(message)
Definition: spyLog.hpp:283
#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
Structure to store picking information.
Definition: PickingInfo.hpp:20
static FWDATATOOLS_API::glm::dmat4x4 getMatrixFromTF3D(const ::fwData::TransformationMatrix3D::csptr &_trf)
Convert a fwData::TransformationMatrix3D into a GLM matrix.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_MODIFIED_SIG
Key in m_signals map of signal m_sigModified.
FWGUI_API void initialize()
Initialize managers.
virtual FWSERVICES_API void info(std::ostream &_sstream)
Write information in a stream.
Definition: IService.cpp:74
Event m_eventId
Mouse event.
Definition: PickingInfo.hpp:50
FWSERVICES_API ConfigType getConfigTree() const
Return the configuration, in an boost property tree.
Definition: IService.cpp:247