fw4spl
SNegatoWindowingInteractor.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/SNegatoWindowingInteractor.hpp"
8 
9 #include <fwCom/Signal.hpp>
10 #include <fwCom/Signal.hxx>
11 #include <fwCom/Signals.hpp>
12 
13 #include <fwData/Image.hpp>
14 #include <fwData/Integer.hpp>
15 #include <fwData/TransferFunction.hpp>
16 
17 #include <fwDataTools/fieldHelper/Image.hpp>
18 #include <fwDataTools/fieldHelper/MedicalImageHelpers.hpp>
19 
20 #include <fwRenderVTK/IAdaptor.hpp>
21 #include <fwRenderVTK/vtk/fwVtkCellPicker.hpp>
22 
23 #include <fwServices/macros.hpp>
24 
25 #include <vtkCommand.h>
26 #include <vtkInteractorStyleImage.h>
27 #include <vtkRenderWindowInteractor.h>
28 
30 
31 #define START_WINDOWING_EVENT vtkCommand::RightButtonPressEvent
32 #define STOP_WINDOWING_EVENT vtkCommand::RightButtonReleaseEvent
33 
34 namespace visuVTKAdaptor
35 {
36 
37 static const ::fwServices::IService::KeyType s_IMAGE_INOUT = "image";
38 static const ::fwServices::IService::KeyType s_TF_INOUT = "tf";
39 
40 //------------------------------------------------------------------------------
41 
42 class NegatoWindowingCallback : public vtkCommand
43 {
44 public:
45  //------------------------------------------------------------------------------
46 
47  static NegatoWindowingCallback* New()
48  {
49  return new NegatoWindowingCallback();
50  }
51 
53  m_picker(nullptr),
54  m_x(0),
55  m_y(0),
56  m_windowStep(1.),
57  m_levelStep(1.),
58  m_mouseMoveObserved(false)
59  {
60  this->PassiveObserverOff();
61  }
62 
64  {
65 
66  }
67 
68  //------------------------------------------------------------------------------
69 
70  virtual void Execute( vtkObject* caller, unsigned long eventId, void*)
71  {
72  if ( m_mouseMoveObserved || !m_adaptor->getInteractor()->GetShiftKey() )
73  {
74  if ( eventId == START_WINDOWING_EVENT)
75  {
76  SLM_ASSERT("m_adaptor not instanced", m_adaptor);
77  SLM_ASSERT("m_picker not instanced", m_picker);
78 
79  double display[3];
80 
81  m_adaptor->getInteractor()->GetEventPosition(m_x, m_y);
82  display[0] = m_x;
83  display[1] = m_y;
84  display[2] = 0;
85 
86  if ( m_picker->Pick( display, m_adaptor->getRenderer() ) )
87  {
88  assert(!m_mouseMoveObserved);
89  m_adaptor->startWindowing();
90  m_adaptor->getInteractor()->AddObserver(vtkCommand::MouseMoveEvent, this, 1.);
91  m_mouseMoveObserved = true;
92  SetAbortFlag(1);
93  m_adaptor->update();
94  }
95 
96  }
97 
98  else if ( eventId == STOP_WINDOWING_EVENT)
99  {
100  SLM_ASSERT("m_adaptor not instanced", m_adaptor);
101  SLM_ASSERT("m_picker not instanced", m_picker);
102 
103  if(m_mouseMoveObserved)
104  {
105  m_adaptor->getInteractor()->RemoveObservers(vtkCommand::MouseMoveEvent, this);
106  m_mouseMoveObserved = false;
107  m_adaptor->stopWindowing();
108  m_adaptor->update();
109  }
110  }
111  else if (eventId == vtkCommand::MouseMoveEvent)
112  {
113  SLM_ASSERT("m_mouseMoveObserved not instanced", m_mouseMoveObserved);
114  int x, y;
115  m_adaptor->getInteractor()->GetEventPosition(x, y);
116 
117  double dx = m_windowStep * ( x - m_x );
118  double dy = m_levelStep * ( m_y - y );
119 
120  m_adaptor->updateWindowing(dx, dy);
121  m_adaptor->update();
122  }
123  }
124  else if (m_adaptor->getInteractor()->GetShiftKey())
125  {
126  vtkRenderWindowInteractor* rwi = vtkRenderWindowInteractor::SafeDownCast(caller);
127  char* keySym = rwi->GetKeySym();
128  if(keySym != nullptr)
129  {
130  if (std::string(keySym) == "R")
131  {
132  m_adaptor->resetWindowing();
133  }
134  }
135  }
136  }
137 
138  //------------------------------------------------------------------------------
139 
140  void setAdaptor( SNegatoWindowingInteractor::sptr adaptor)
141  {
142  m_adaptor = adaptor;
143  }
144 
145  //------------------------------------------------------------------------------
146 
147  void setPicker( vtkAbstractPropPicker* picker)
148  {
149  m_picker = picker;
150  }
151 
152 protected:
153  SNegatoWindowingInteractor::sptr m_adaptor;
154  vtkAbstractPropPicker* m_picker;
155 
156  int m_x;
157  int m_y;
158 
159  double m_windowStep;
160  double m_levelStep;
161 
162  bool m_mouseMoveObserved;
163 
164 };
165 
166 //------------------------------------------------------------------------------
167 
168 SNegatoWindowingInteractor::SNegatoWindowingInteractor() noexcept :
169  m_vtkObserver(nullptr),
170  m_initialWindow(0.),
171  m_initialLevel(0.),
172  m_priority(.6f)
173 {
174 }
175 
176 //------------------------------------------------------------------------------
177 
178 SNegatoWindowingInteractor::~SNegatoWindowingInteractor() noexcept
179 {
180 }
181 
182 //------------------------------------------------------------------------------
183 
185 {
186  this->configureParams();
187 }
188 
189 //------------------------------------------------------------------------------
190 
192 {
193  this->initialize();
194 
195  ::fwData::TransferFunction::sptr tf = this->getInOut< ::fwData::TransferFunction >(s_TF_INOUT);
196  if (tf)
197  {
198  this->setTransferFunction(tf);
199  }
200  else
201  {
202  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
203  SLM_ASSERT("Missing image", image);
204  this->createTransferFunction(image);
205  }
206 
207  NegatoWindowingCallback* observer = NegatoWindowingCallback::New();
208  observer->setAdaptor( SNegatoWindowingInteractor::dynamicCast(this->getSptr()) );
209  observer->setPicker(this->getPicker());
210 
211  m_vtkObserver = observer;
212 
213  this->getInteractor()->AddObserver(START_WINDOWING_EVENT, m_vtkObserver, m_priority);
214  this->getInteractor()->AddObserver(STOP_WINDOWING_EVENT, m_vtkObserver, m_priority);
215  this->getInteractor()->AddObserver(vtkCommand::KeyPressEvent, m_vtkObserver, m_priority);
216 
217  this->updating();
218 }
219 
220 //------------------------------------------------------------------------------
221 
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  this->requestRender();
229 }
230 
231 //------------------------------------------------------------------------------
232 
234 {
235  this->getInteractor()->RemoveObservers(START_WINDOWING_EVENT, m_vtkObserver);
236  this->getInteractor()->RemoveObservers(STOP_WINDOWING_EVENT, m_vtkObserver);
237  this->getInteractor()->RemoveObservers(vtkCommand::KeyPressEvent, m_vtkObserver);
238  m_vtkObserver->Delete();
239  m_vtkObserver = nullptr;
240  this->removeAllPropFromRenderer();
241 }
242 
243 //------------------------------------------------------------------------------
244 
245 void SNegatoWindowingInteractor::swapping(const KeyType& key)
246 {
247  if (key == s_TF_INOUT)
248  {
249  ::fwData::TransferFunction::sptr tf = this->getInOut< ::fwData::TransferFunction >(s_TF_INOUT);
250  if (tf)
251  {
252  this->setTransferFunction(tf);
253  }
254  else
255  {
256  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
257  SLM_ASSERT("Missing image", image);
258  this->createTransferFunction(image);
259  }
260  this->updating();
261  }
262 }
263 
264 //------------------------------------------------------------------------------
265 
266 void SNegatoWindowingInteractor::startWindowing( )
267 {
268  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
269  SLM_ASSERT("Missing image", image);
270 
271  this->updating();
272 
273  ::fwData::TransferFunction::sptr tf = this->getTransferFunction();
274 
275  m_initialLevel = tf->getLevel();
276  m_initialWindow = tf->getWindow();
277 }
278 
279 //------------------------------------------------------------------------------
280 
281 void SNegatoWindowingInteractor::stopWindowing( )
282 {
283 }
284 
285 //------------------------------------------------------------------------------
286 
287 void SNegatoWindowingInteractor::updateWindowing( double dw, double dl )
288 {
289  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
290  SLM_ASSERT("Missing image", image);
291  ::fwData::TransferFunction::sptr tf = this->getTransferFunction();
292 
293  double newWindow = m_initialWindow + dw;
294  double newLevel = m_initialLevel - dl;
295 
296  tf->setWindow( newWindow );
297  tf->setLevel( newLevel );
298 
301  {
302  ::fwCom::Connection::Blocker block(sig->getConnection(m_slotUpdateTFWindowing));
303  sig->asyncEmit( newWindow, newLevel);
304  }
305 
306  this->setVtkPipelineModified();
307 }
308 
309 //------------------------------------------------------------------------------
310 
311 void SNegatoWindowingInteractor::resetWindowing()
312 {
313  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
314  SLM_ASSERT("Missing image", image);
315  ::fwData::TransferFunction::sptr tf = this->getTransferFunction();
316 
317  double newWindow = image->getWindowWidth();
318  double newLevel = image->getWindowCenter();
319 
320  tf->setWindow( newWindow );
321  tf->setLevel( newLevel );
322 
325  {
326  ::fwCom::Connection::Blocker block(sig->getConnection(m_slotUpdateTFWindowing));
327  sig->asyncEmit( newWindow, newLevel);
328  }
329 
330  this->setVtkPipelineModified();
331 }
332 
333 //------------------------------------------------------------------------------
334 
336 {
337  KeyConnectionsMap connections;
338  connections.push(s_IMAGE_INOUT, ::fwData::Image::s_MODIFIED_SIG, s_UPDATE_SLOT);
339  connections.push(s_IMAGE_INOUT, ::fwData::Image::s_BUFFER_MODIFIED_SIG, s_UPDATE_SLOT);
340 
341  return connections;
342 }
343 
344 //------------------------------------------------------------------------------
345 
346 } //namespace visuVTKAdaptor
This class is a helper to define the connections of a service and its data.
Definition: IService.hpp:454
Class allowing to block a Connection.
Definition: Connection.hpp:20
The namespace visuVTKAdaptor contains the list of adaptors available for the generic scene...
Manage windowing interaction for image.
VISUVTKADAPTOR_API void stopping() override
Uninitialize the service activity. The stop() method is always invoked before destroying a service...
VISUVTKADAPTOR_API void updating() override
Perform some computations according to object (this service is attached to) attribute values and its ...
virtual void swapping()
Swap the service from associated object to another object.
Definition: IService.hpp:613
VISUVTKADAPTOR_API void configuring() override
Configure the service before starting. Apply the configuration to service.
VISUVTKADAPTOR_API void starting() override
Initialize the service activity.
#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
virtual VISUVTKADAPTOR_API KeyConnectionsMap getAutoConnections() const override
Returns proposals to connect service slots to associated object signals, this method is used for obj/...
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.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_WINDOWING_MODIFIED_SIG
Type of signal when points are modified.