fw4spl
SImagePickerInteractor.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/SImagePickerInteractor.hpp"
8 
9 #include <fwCom/Signal.hpp>
10 #include <fwCom/Signal.hxx>
11 #include <fwCom/Slot.hpp>
12 #include <fwCom/Slot.hxx>
13 #include <fwCom/Slots.hpp>
14 #include <fwCom/Slots.hxx>
15 
16 #include <fwData/Composite.hpp>
17 #include <fwData/Material.hpp>
18 #include <fwData/Reconstruction.hpp>
19 
20 #include <fwRenderVTK/vtk/Helpers.hpp>
21 
22 #include <fwServices/macros.hpp>
23 
24 #include <boost/tokenizer.hpp>
25 
26 #include <vtkAbstractPropPicker.h>
27 #include <vtkActor.h>
28 #include <vtkCommand.h>
29 #include <vtkCubeSource.h>
30 #include <vtkPolyDataMapper.h>
31 #include <vtkRenderWindowInteractor.h>
32 
33 #define START_INTERACTION_EVENT vtkCommand::LeftButtonPressEvent
34 #define STOP_INTERACTION_EVENT vtkCommand::LeftButtonReleaseEvent
35 
37 
38 namespace visuVTKAdaptor
39 {
40 
41 static const ::fwServices::IService::KeyType s_IMAGE_INOUT = "image";
42 
43 static const ::fwCom::Slots::SlotKeyType s_UPDATE_SLICE_INDEX_SLOT = "updateSliceIndex";
44 
45 //------------------------------------------------------------------------------
46 
47 class ImagePickerInteractorCallback : public vtkCommand
48 {
49 public:
50  //------------------------------------------------------------------------------
51 
52  static ImagePickerInteractorCallback* New()
53  {
54  return new ImagePickerInteractorCallback();
55  }
56 
57  //------------------------------------------------------------------------------
58 
60  m_picker(nullptr),
61  m_eventId(nullptr)
62  {
63  m_picker = NULL;
64  this->PassiveObserverOn();
65  }
66 
67  //------------------------------------------------------------------------------
68 
70  {
71  }
72 
73  //------------------------------------------------------------------------------
74 
75  virtual void Execute( vtkObject* caller, unsigned long eventId, void*)
76  {
77  SLM_ASSERT("m_adaptor not instanced", m_adaptor);
78  SLM_ASSERT("m_picker not instanced", m_picker);
79 
80  this->process(vtkRenderWindowInteractor::SafeDownCast(caller), eventId);
81  }
82 
83  //------------------------------------------------------------------------------
84 
85  bool pickSomething()
86  {
87  int x, y;
88  double display[3];
89 
90  m_adaptor->getInteractor()->GetEventPosition(x, y);
91  display[0] = x;
92  display[1] = y;
93  display[2] = 0;
94 
95  return (m_picker->Pick( display, m_adaptor->getRenderer() ) != 0);
96  }
97 
98  //------------------------------------------------------------------------------
99 
100  void process(vtkRenderWindowInteractor* caller, unsigned long eventId) // from
101  {
102  if( m_eventId->find( static_cast< SImagePickerInteractor::EventID>(eventId) ) != m_eventId->end() )
103  {
104 #ifdef __linux
105  if(eventId == SImagePickerInteractor::MOUSE_MOVE)
108  {
109  m_skipMove++;
110  if( m_skipMove % 10 )
111  {
112  return;
113  }
114  }
115 #endif
116  SLM_ASSERT("bad vtk caller", caller);
117 
118  if ( this->pickSomething() )
119  {
120  double world[3] = {-1, 0, 0};
121  ::fwRenderVTK::vtk::getNearestPickedPosition(m_picker, m_adaptor->getRenderer(), world);
122  OSLM_TRACE("PICK" << world[0] << " ," << world[1] << " ," << world[2] );
123 
125 
126  m_adaptor->worldToImageSliceIndex(world, info.m_worldPos);
127 
128  const auto iter = SPickerInteractor::s_vtkEventIDConversion.find(eventId);
129  SLM_ASSERT("Unknown eventId", iter != SPickerInteractor::s_vtkEventIDConversion.end());
130  info.m_eventId = iter->second;
131 
132  info.m_keyPressed = caller->GetKeyCode();
133 
134  info.m_modifierMask =
135  caller->GetControlKey() ? ::fwDataTools::PickingInfo::CTRL : ::fwDataTools::PickingInfo::NONE;
136  info.m_modifierMask |=
137  caller->GetShiftKey() ? ::fwDataTools::PickingInfo::SHIFT : ::fwDataTools::PickingInfo::NONE;
138 
139  auto sig = m_adaptor->signal<SPickerInteractor::PickedSignalType>(
140  SPickerInteractor::s_PICKED_SIGNAL);
141  sig->asyncEmit(info);
142  }
143  }
144 
145  }
146 
147  //------------------------------------------------------------------------------
148 
149  void setAdaptor( SImagePickerInteractor::sptr adaptor)
150  {
151  m_adaptor = adaptor;
152  }
153 
154  //------------------------------------------------------------------------------
155 
156  void setPicker( vtkAbstractPropPicker* picker)
157  {
158  m_picker = picker;
159  }
160 
161  //------------------------------------------------------------------------------
162 
163  void setEventId(SImagePickerInteractor::SetEventIdType* eventId)
164  {
165  m_eventId = eventId;
166  }
167 
168 protected:
169  SImagePickerInteractor::sptr m_adaptor;
170  vtkAbstractPropPicker* m_picker;
171  SImagePickerInteractor::SetEventIdType* m_eventId;
172  SImagePickerInteractor::PickedSignalType::sptr m_sigPickedCell;
173 #ifdef __linux
174  unsigned int m_skipMove = 0u;
175 #endif // __linux
176 };
177 
178 //------------------------------------------------------------------------------
179 
180 SImagePickerInteractor::SImagePickerInteractor() noexcept
181 {
182  newSlot(s_UPDATE_SLICE_INDEX_SLOT, &SImagePickerInteractor::updateSliceIndex, this);
183 }
184 
185 //------------------------------------------------------------------------------
186 
187 SImagePickerInteractor::~SImagePickerInteractor() noexcept
188 {
189 }
190 
191 //------------------------------------------------------------------------------
192 
194 {
196 }
197 
198 //------------------------------------------------------------------------------
199 
201 {
202  this->initialize();
203 
204  ImagePickerInteractorCallback* observer = ImagePickerInteractorCallback::New();
205  observer->setAdaptor( SImagePickerInteractor::dynamicCast(this->getSptr()) );
206  observer->setPicker(this->getPicker());
207  observer->setEventId(&m_eventId);
208 
209  m_interactionCommand = observer;
210 
211  vtkRenderWindowInteractor* interactor = this->getInteractor();
212  const float priority = 0.999f;
213  interactor->AddObserver(vtkCommand::LeftButtonPressEvent, m_interactionCommand, priority);
214  interactor->AddObserver(vtkCommand::LeftButtonReleaseEvent, m_interactionCommand, priority);
215  interactor->AddObserver(vtkCommand::MiddleButtonPressEvent, m_interactionCommand, priority);
216  interactor->AddObserver(vtkCommand::MiddleButtonReleaseEvent, m_interactionCommand, priority);
217  interactor->AddObserver(vtkCommand::RightButtonPressEvent, m_interactionCommand, priority);
218  interactor->AddObserver(vtkCommand::RightButtonReleaseEvent, m_interactionCommand, priority);
219  interactor->AddObserver(vtkCommand::MouseMoveEvent, m_interactionCommand, priority);
220  interactor->AddObserver(vtkCommand::MouseWheelForwardEvent, m_interactionCommand, priority);
221  interactor->AddObserver(vtkCommand::MouseWheelBackwardEvent, m_interactionCommand, priority);
222  interactor->AddObserver(vtkCommand::KeyPressEvent, m_interactionCommand, priority);
223 
224  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
225  SLM_ASSERT("Missing image", image);
226 
227  this->updateImageInfos(image);
228 }
229 
230 //------------------------------------------------------------------------------
231 
233 {
234  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
235  SLM_ASSERT("Missing image", image);
236 
237  this->updateImageInfos(image);
238 }
239 
240 //-----------------------------------------------------------------------------
241 
242 void SImagePickerInteractor::updateSliceIndex(int axial, int frontal, int sagittal)
243 {
244  m_axialIndex->value() = axial;
245  m_frontalIndex->value() = frontal;
246  m_sagittalIndex->value() = sagittal;
247 }
248 
249 //------------------------------------------------------------------------------
250 
252 {
253  vtkRenderWindowInteractor* interactor = this->getInteractor();
254  interactor->RemoveObservers(vtkCommand::LeftButtonPressEvent, m_interactionCommand);
255  interactor->RemoveObservers(vtkCommand::LeftButtonReleaseEvent, m_interactionCommand);
256  interactor->RemoveObservers(vtkCommand::MiddleButtonPressEvent, m_interactionCommand);
257  interactor->RemoveObservers(vtkCommand::MiddleButtonReleaseEvent, m_interactionCommand);
258  interactor->RemoveObservers(vtkCommand::RightButtonPressEvent, m_interactionCommand);
259  interactor->RemoveObservers(vtkCommand::RightButtonReleaseEvent, m_interactionCommand);
260  interactor->RemoveObservers(vtkCommand::MouseMoveEvent, m_interactionCommand);
261  interactor->RemoveObservers(vtkCommand::MouseWheelForwardEvent, m_interactionCommand);
262  interactor->RemoveObservers(vtkCommand::MouseWheelBackwardEvent, m_interactionCommand);
263  interactor->RemoveObservers(vtkCommand::KeyPressEvent, m_interactionCommand);
264 
265  m_interactionCommand->Delete();
266  m_interactionCommand = NULL;
267 }
268 
269 //------------------------------------------------------------------------------
270 
272 {
273  KeyConnectionsMap connections;
274  connections.push( s_IMAGE_INOUT, ::fwData::Image::s_MODIFIED_SIG, s_UPDATE_SLOT);
275  connections.push( s_IMAGE_INOUT, ::fwData::Image::s_SLICE_INDEX_MODIFIED_SIG, s_UPDATE_SLICE_INDEX_SLOT);
276  connections.push( s_IMAGE_INOUT, ::fwData::Image::s_BUFFER_MODIFIED_SIG, s_UPDATE_SLOT);
277 
278  return connections;
279 }
280 
281 //------------------------------------------------------------------------------
282 
283 } //namespace visuVTKAdaptor
VISUVTKADAPTOR_API void updating() override
Perform some computations according to object (this service is attached to) attribute values and its ...
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
double m_worldPos[3]
Position clicked in world coordinates.
Definition: PickingInfo.hpp:44
VISUVTKADAPTOR_API void starting() override
Initialize the service activity.
The namespace visuVTKAdaptor contains the list of adaptors available for the generic scene...
VISUVTKADAPTOR_API void stopping() override
Uninitialize the service activity. The stop() method is always invoked before destroying a service...
#define OSLM_TRACE(message)
Definition: spyLog.hpp:230
SImagePickerInteractor::PickedSignalType::sptr m_sigPickedCell
signal to emit
std::int8_t m_modifierMask
Modifier mask.
Definition: PickingInfo.hpp:52
#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.
Structure to store picking information.
Definition: PickingInfo.hpp:20
char m_keyPressed
Key event.
Definition: PickingInfo.hpp:54
VISUVTKADAPTOR_API void configuring() override
Configure the service before starting. Apply the configuration to service.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_BUFFER_MODIFIED_SIG
Type of signal when image&#39;s buffer is added.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_MODIFIED_SIG
Key in m_signals map of signal m_sigModified.
virtual VISUVTKADAPTOR_API KeyConnectionsMap getAutoConnections() const override
Returns proposals to connect service slots to associated object signals, this method is used for obj/...
This service emits a signal when the user click on the associated image in the scene.
Event m_eventId
Mouse event.
Definition: PickingInfo.hpp:50