fw4spl
SNegatoMPR.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-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/SNegatoMPR.hpp"
8 
9 #include "visuVTKAdaptor/SNegatoOneSlice.hpp"
10 #include "visuVTKAdaptor/SNegatoSlicingInteractor.hpp"
11 #include "visuVTKAdaptor/SNegatoWindowingInteractor.hpp"
12 #include "visuVTKAdaptor/SSlicesCursor.hpp"
13 
14 #include <fwCom/Slot.hpp>
15 #include <fwCom/Slot.hxx>
16 #include <fwCom/Slots.hpp>
17 #include <fwCom/Slots.hxx>
18 
19 #include <fwData/Boolean.hpp>
20 #include <fwData/Image.hpp>
21 #include <fwData/Integer.hpp>
22 #include <fwData/String.hpp>
23 
24 #include <fwDataTools/fieldHelper/Image.hpp>
25 #include <fwDataTools/fieldHelper/MedicalImageHelpers.hpp>
26 
27 #include <fwServices/macros.hpp>
28 #include <fwServices/op/Add.hpp>
29 #include <fwServices/registry/Proxy.hpp>
30 
31 #include <fwTools/fwID.hpp>
32 
33 #include <string>
34 
35 fwServicesRegisterMacro( ::fwRenderVTK::IAdaptor, ::visuVTKAdaptor::SNegatoMPR);
36 
37 namespace visuVTKAdaptor
38 {
39 static const ::fwCom::Slots::SlotKeyType s_UPDATE_SLICE_TYPE_SLOT = "updateSliceType";
40 static const ::fwCom::Slots::SlotKeyType s_UPDATE_SLICE_MODE_SLOT = "updateSliceMode";
41 static const ::fwCom::Slots::SlotKeyType s_SHOW_SLICE_SLOT = "showSlice";
42 static const ::fwCom::Slots::SlotKeyType s_SET_CROSS_SCALE_SLOT = "setCrossScale";
43 static const ::fwCom::Slots::SlotKeyType S_CHANGE_IMAGE_SOURCE_SLOT = "changeImageSource";
44 
45 static const std::string s_slicingStartingProxy = "slicingStartingProxy";
46 static const std::string s_slicingStoppingProxy = "slicingStoppingProxy";
47 
48 const ::fwServices::IService::KeyType SNegatoMPR::s_IMAGE_INOUT = "image";
49 const ::fwServices::IService::KeyType SNegatoMPR::s_TF_INOUT = "tf";
50 
51 //------------------------------------------------------------------------------
52 
53 SNegatoMPR::SNegatoMPR() noexcept :
54  m_allowAlphaInTF(false),
55  m_interpolation(false),
56  m_actorOpacity(1.0),
57  m_3dModeEnabled( ::boost::logic::indeterminate ),
58  m_sliceMode(THREE_SLICES),
59  m_backupedSliceMode(THREE_SLICES)
60 {
61  newSlot(s_UPDATE_SLICE_TYPE_SLOT, &SNegatoMPR::updateSliceType, this);
62  newSlot(s_UPDATE_SLICE_MODE_SLOT, &SNegatoMPR::updateSliceMode, this);
63  newSlot(s_SHOW_SLICE_SLOT, &SNegatoMPR::showSlice, this);
64  newSlot(s_SET_CROSS_SCALE_SLOT, &SNegatoMPR::setCrossScale, this);
65  newSlot(S_CHANGE_IMAGE_SOURCE_SLOT, &SNegatoMPR::changeImageSource, this);
66 }
67 
68 //------------------------------------------------------------------------------
69 
70 SNegatoMPR::~SNegatoMPR() noexcept
71 {
72 }
73 
74 //------------------------------------------------------------------------------
75 
77 {
78  this->initialize();
79  this->updating();
80 }
81 
82 //------------------------------------------------------------------------------
83 
85 {
86  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
87  SLM_ASSERT("Missing image", image);
88 
89  //disconnect proxy
90  ::fwServices::registry::Proxy::sptr proxy = ::fwServices::registry::Proxy::getDefault();
91 
92  for (auto srv : this->getRegisteredServices())
93  {
94  SNegatoSlicingInteractor::sptr negatoSlicingInteractor = SNegatoSlicingInteractor::dynamicCast(srv.lock());
95  SSlicesCursor::sptr sliceCursor = SSlicesCursor::dynamicCast(srv.lock());
96  if (negatoSlicingInteractor)
97  {
98  proxy->disconnect(m_slicingStartingProxy, negatoSlicingInteractor->signal(
100  proxy->disconnect(m_slicingStoppingProxy, negatoSlicingInteractor->signal(
102  }
103 
104  if (sliceCursor)
105  {
106  proxy->disconnect(m_slicingStartingProxy, sliceCursor->slot(
108 
109  proxy->disconnect(m_slicingStoppingProxy, sliceCursor->slot(
111  }
112  }
113 
114  this->unregisterServices();
115  this->requestRender();
116 }
117 
118 //------------------------------------------------------------------------------
119 
121 {
122  this->stopping();
123 
124  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
125  SLM_ASSERT("Missing image", image);
126 
128 
129  if ( imageIsValid)
130  {
131  if(this->getSliceMode() != NO_SLICE)
132  {
133  if(this->getSliceMode() == ONE_SLICE)
134  {
135  this->addAdaptor("::visuVTKAdaptor::SNegatoOneSlice", m_orientation);
136  }
137  else if(this->getSliceMode() == THREE_SLICES)
138  {
139  this->addAdaptor("::visuVTKAdaptor::SNegatoOneSlice", X_AXIS);
140  this->addAdaptor("::visuVTKAdaptor::SNegatoOneSlice", Y_AXIS);
141  this->addAdaptor("::visuVTKAdaptor::SNegatoOneSlice", Z_AXIS);
142  }
143 
144  ::fwRenderVTK::IAdaptor::sptr sliceCursor;
145  ::fwRenderVTK::IAdaptor::sptr negatoSlicingInteractor;
146  this->addAdaptor("::visuVTKAdaptor::SNegatoWindowingInteractor");
147  negatoSlicingInteractor = this->addAdaptor("::visuVTKAdaptor::SNegatoSlicingInteractor", m_orientation);
148  sliceCursor = this->addAdaptor("::visuVTKAdaptor::SSlicesCursor", m_orientation);
149  this->addAdaptor("::visuVTKAdaptor::SProbeCursor", m_orientation);
150 
151  // Connect slicing signals/slots from NegatoSlicingInteractor to SlicesCursor using the image slicing proxy
152  ::fwServices::registry::Proxy::sptr proxy = ::fwServices::registry::Proxy::getDefault();
153  m_slicingStartingProxy = image->getID() + s_slicingStartingProxy;
154  m_slicingStoppingProxy = image->getID() + s_slicingStoppingProxy;
155  proxy->connect(m_slicingStartingProxy, negatoSlicingInteractor->signal(
157  proxy->connect(m_slicingStartingProxy, sliceCursor->slot(
159 
160  proxy->connect(m_slicingStoppingProxy, negatoSlicingInteractor->signal(
162  proxy->connect(m_slicingStoppingProxy, sliceCursor->slot(
164  m_sliceCursor = sliceCursor;
165  }
166  if(this->is3dModeEnabled())
167  {
168  this->addAdaptor("::visuVTKAdaptor::SMedical3DCamera", m_orientation);
169  }
170  else if(!this->is3dModeEnabled())
171  {
172  this->addAdaptor("::visuVTKAdaptor::SSliceFollowerCamera", m_orientation);
173  }
174  else
175  {
176  SLM_TRACE("No 2D/3D mode specified.");
177  }
178  this->setVtkPipelineModified();
179  this->requestRender();
180  }
181 }
182 
183 //------------------------------------------------------------------------------
184 
185 void SNegatoMPR::swapping(const KeyType& key)
186 {
187  if (key == s_TF_INOUT)
188  {
189  ::fwData::TransferFunction::sptr tf = this->getInOut< ::fwData::TransferFunction >(s_TF_INOUT);
190  this->setTransferFunction(tf);
191 
192  for (const auto& srv: this->getRegisteredServices())
193  {
194  ::fwServices::IService::sptr service = srv.lock();
195  if (tf)
196  {
197  service->registerInOut(tf, s_TF_INOUT, false, true);
198  service->swapKey(s_TF_INOUT, nullptr);
199  }
200  else if(::fwServices::OSR::isRegistered(s_TF_INOUT, AccessType::INOUT, service))
201  {
202  ::fwServices::OSR::unregisterService(s_TF_INOUT, AccessType::INOUT, service);
203  service->swapKey(s_TF_INOUT, nullptr);
204  }
205  }
206  }
207 }
208 
209 //-----------------------------------------------------------------------------
210 
211 void SNegatoMPR::updateSliceType(int from, int to)
212 {
213  if( to == static_cast<int>(m_orientation) )
214  {
215  setOrientation( static_cast< Orientation >( from ));
216  }
217  else if(from == static_cast<int>(m_orientation))
218  {
219  setOrientation( static_cast< Orientation >( to ));
220  }
221 }
222 
223 //-----------------------------------------------------------------------------
224 
225 void SNegatoMPR::updateSliceMode(int mode)
226 {
227  switch(mode)
228  {
229  case 0:
230  {
231  this->setSliceMode(NO_SLICE);
232  break;
233  }
234  case 1:
235  {
236  this->setSliceMode(ONE_SLICE);
237  break;
238  }
239  case 3:
240  {
241  this->setSliceMode(THREE_SLICES);
242  break;
243  }
244  default:
245  {
246  FW_RAISE("Slice mode " << mode << " is not implemented.");
247  }
248  }
249  m_backupedSliceMode = this->getSliceMode();
250  this->updating();
251 }
252 //-----------------------------------------------------------------------------
253 
254 void SNegatoMPR::showSlice(bool isShown)
255 {
256  if(isShown)
257  {
258  this->setSliceMode(m_backupedSliceMode);
259  }
260  else
261  {
262  m_backupedSliceMode = this->getSliceMode();
263  this->setSliceMode(NO_SLICE);
264  }
265  this->updating();
266 }
267 
268 //-----------------------------------------------------------------------------
269 
270 void SNegatoMPR::setCrossScale(double scale)
271 {
272  if (!m_sliceCursor.expired())
273  {
274  ::fwCom::SlotBase::sptr slot = m_sliceCursor.lock()->slot(s_SET_CROSS_SCALE_SLOT);
275  slot->asyncRun(scale);
276  }
277 }
278 
279 //-----------------------------------------------------------------------------
280 
281 void SNegatoMPR::changeImageSource(std::string _value, std::string _key)
282 {
283  if( _key == "ImageSource" )
284  {
285  // Select the right algorithm
286  m_imageSourceId = _value;
287 
288  this->updating();
289  }
290 }
291 
292 //------------------------------------------------------------------------------
293 
295 {
296  this->configureParams();
297 
298  const ConfigType config = this->getConfigTree().get_child("config.<xmlattr>");
299 
300  if (config.count("mode"))
301  {
302  std::string value = config.get<std::string>("mode");
303  std::transform(value.begin(), value.end(), value.begin(), tolower);
304  SLM_ASSERT("Bad value '" + value + "' for attribute mode, it should either be '2d' or '3d'.",
305  value == "3d" || value == "2d");
306  this->set3dMode(value == "3d");
307  }
308  if (config.count("slices"))
309  {
310  const std::string value = config.get<std::string>("slices");
311 
312  if(value == "0")
313  {
314  this->setSliceMode(NO_SLICE);
315  }
316  else if(value == "1")
317  {
318  this->setSliceMode(ONE_SLICE);
319  }
320  else if(value == "3")
321  {
322  this->setSliceMode(THREE_SLICES);
323  }
324  else
325  {
326  SLM_FATAL("'slice' value must be '0', '1' or '3', actual: " + value);
327  }
328  m_backupedSliceMode = this->getSliceMode();
329  }
330 
331  const std::string orientation = config.get<std::string>("sliceIndex", "axial");
332  if(orientation == "axial" )
333  {
334  m_orientation = Z_AXIS;
335  }
336  else if(orientation == "frontal" )
337  {
338  m_orientation = Y_AXIS;
339  }
340  else if(orientation == "sagittal" )
341  {
342  m_orientation = X_AXIS;
343  }
344 
345  const std::string tfalpha = config.get<std::string>("tfalpha", "no");
346  SLM_ASSERT("'tfalpha' value must be 'yes' or 'no', actual: " + tfalpha, tfalpha == "yes" || tfalpha == "no");
347  this->setAllowAlphaInTF(tfalpha == "yes");
348 
349  const std::string interpolation = config.get<std::string>("interpolation", "off");
350  SLM_ASSERT("'interpolation' value must be 'on' or 'off', actual: " + interpolation,
351  interpolation == "on" || interpolation == "off");
352  this->setInterpolation(interpolation == "yes");
353 
354  this->setVtkImageSourceId( config.get<std::string>("vtkimagesource", ""));
355 
356  m_actorOpacity = config.get<double>("actorOpacity", 1.);
357 }
358 
359 //------------------------------------------------------------------------------
360 
361 void SNegatoMPR::setSliceMode(SliceMode sliceMode)
362 {
363  if(m_sliceMode != sliceMode)
364  {
365  m_sliceMode = sliceMode;
366  }
367 }
368 
369 //------------------------------------------------------------------------------
370 
371 SNegatoMPR::SliceMode SNegatoMPR::getSliceMode() const
372 {
373  return m_sliceMode;
374 }
375 
376 //------------------------------------------------------------------------------
377 
378 ::boost::logic::tribool SNegatoMPR::is3dModeEnabled() const
379 {
380  return m_3dModeEnabled;
381 }
382 
383 //------------------------------------------------------------------------------
384 
385 void SNegatoMPR::set3dMode( bool enabled )
386 {
387  m_3dModeEnabled = enabled;
388 }
389 
390 //------------------------------------------------------------------------------
391 
392 ::fwRenderVTK::IAdaptor::sptr SNegatoMPR::addAdaptor(const std::string& adaptorType, int axis)
393 {
394  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
395  SLM_ASSERT("Missing image", image);
396 
397  // create the srv configuration for objects auto-connection
398  auto service = this->registerService< ::fwRenderVTK::IAdaptor>(adaptorType);
399  // register image
400  service->registerInOut(image, s_IMAGE_INOUT, true);
401 
402  if(axis >= 0)
403  {
404  auto adaptorSrv = ::fwDataTools::helper::MedicalImageAdaptor::dynamicCast(service);
405  SLM_ASSERT("adaptorSrv not instanced", adaptorSrv);
406  adaptorSrv->setOrientation((Orientation) axis);
407  }
408 
409  auto negatoAdaptor = ::visuVTKAdaptor::SNegatoOneSlice::dynamicCast(service);
410 
411  if (negatoAdaptor)
412  {
413  negatoAdaptor->setAllowAlphaInTF(m_allowAlphaInTF);
414  negatoAdaptor->setInterpolation(m_interpolation);
415  if (!m_imageSourceId.empty())
416  {
417  negatoAdaptor->setVtkImageSourceId(m_imageSourceId);
418  }
419  negatoAdaptor->setActorOpacity(m_actorOpacity);
420  }
421 
422  ::fwData::TransferFunction::sptr tf = this->getInOut< ::fwData::TransferFunction >(s_TF_INOUT);
423  if (tf)
424  {
425  // register the TF as optional
426  service->registerInOut(tf, s_TF_INOUT, false, true);
427  }
428 
429  service->setRenderService(this->getRenderService());
430  service->setRendererId( this->getRendererId() );
431  service->setPickerId( this->getPickerId() );
432  service->setTransformId( this->getTransformId() );
433 
434  service->start();
435  service->update();
436 
437  return service;
438 }
439 
440 //------------------------------------------------------------------------------
441 
443 {
444  KeyConnectionsMap connections;
445  connections.push(s_IMAGE_INOUT, ::fwData::Image::s_MODIFIED_SIG, s_UPDATE_SLOT);
446  connections.push(s_IMAGE_INOUT, ::fwData::Image::s_SLICE_TYPE_MODIFIED_SIG, s_UPDATE_SLICE_TYPE_SLOT);
447 
448  return connections;
449 }
450 
451 //------------------------------------------------------------------------------
452 
453 } //namespace visuVTKAdaptor
This class is a helper to define the connections of a service and its data.
Definition: IService.hpp:454
FWDATATOOLS_API void setTransferFunction(const ::fwData::TransferFunction::sptr &tf)
Set the current TransferFunction.
VISUVTKADAPTOR_API void starting() override
Initialize the service activity.
Definition: SNegatoMPR.cpp:76
VISUVTKADAPTOR_API void configuring() override
Configure the service before starting. Apply the configuration to service.
Definition: SNegatoMPR.cpp:294
static FWSERVICES_API Proxy::sptr getDefault()
Returns an instance of Proxy.
Definition: Proxy.cpp:33
The namespace visuVTKAdaptor contains the list of adaptors available for the generic scene...
static VISUVTKADAPTOR_APIconst::fwCom::Signals::SignalKeyType s_SLICING_STARTED_SIG
Type of signal when slicing is updated.
static const ::fwCom::Slots::SlotKeyType s_SHOW_FULL_CROSS_SLOT
Slot: update image slice index.
FWRENDERVTK_API void configureParams()
Parse the xml configuration for renderer, picker and transform.
virtual FWDATATOOLS_API void setOrientation(Orientation orientation)
Set the image orientation.
static VISUVTKADAPTOR_APIconst::fwCom::Signals::SignalKeyType s_SLICING_STOPPED_SIG
Type of signal when slicing is updated.
const ServiceVector & getRegisteredServices() const
Get all subservices linked to this service.
FWRENDERVTK_API void requestRender()
notify a render request iff vtkPipeline is modified
virtual void swapping()
Swap the service from associated object to another object.
Definition: IService.hpp:613
FWRENDERVTK_API void setVtkPipelineModified()
End-user have to call this method when a vtk structure has been modified, thus a render request will ...
FWRENDERVTK_API SRender::sptr getRenderService() const
Returd the associated render service.
FWRENDERVTK_API SRender::PickerIdType getPickerId() const
Gets the identifier of the picker used by this adaptor.
VISUVTKADAPTOR_API void updating() override
Perform some computations according to object (this service is attached to) attribute values and its ...
Definition: SNegatoMPR.cpp:120
VISUVTKADAPTOR_API void stopping() override
Uninitialize the service activity. The stop() method is always invoked before destroying a service...
Definition: SNegatoMPR.cpp:84
#define SLM_FATAL(message)
Definition: spyLog.hpp:283
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...
#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/...
Definition: SNegatoMPR.cpp:442
FWRENDERVTK_API SRender::VtkObjectIdType getTransformId() const
Returns the identifier of the transform used by this adaptor.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_MODIFIED_SIG
Key in m_signals map of signal m_sigModified.
FWRENDERVTK_API SRender::RendererIdType getRendererId() const
Returns the renderer identifier.
static FWDATATOOLS_API bool checkImageValidity(::fwData::Image::csptr _pImg)
Check if the image is valid.
#define SLM_TRACE(message)
Definition: spyLog.hpp:228
FWRENDERVTK_API void initialize()
Initialize the adaptor with the associated render service. (must be call in starting).
static const ::fwCom::Slots::SlotKeyType s_SHOW_NORMAL_CROSS_SLOT
Slot: update image slice index.
FWSERVICES_API bool isRegistered(const ::fwServices::IService::KeyType &objKey,::fwServices::IService::AccessType access,::fwServices::IService::sptr service)
Return true if a key is registered for a given service.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_SLICE_TYPE_MODIFIED_SIG
Type of signal when image&#39;s buffer is added.
Display a negato image.
Definition: SNegatoMPR.hpp:64
static FWSERVICES_APIconst::fwCom::Slots::SlotKeyType s_UPDATE_SLOT
Slot to call start method.
Definition: IService.hpp:177
FWSERVICES_API ConfigType getConfigTree() const
Return the configuration, in an boost property tree.
Definition: IService.cpp:247