fw4spl
SPlaneList.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 #ifndef ANDROID
8 
9 #include "visuVTKAdaptor/SPlaneList.hpp"
10 
11 #include "visuVTKAdaptor/SPlane.hpp"
12 
13 #include <fwCom/Signal.hpp>
14 #include <fwCom/Signal.hxx>
15 #include <fwCom/Slot.hpp>
16 #include <fwCom/Slot.hxx>
17 #include <fwCom/Slots.hpp>
18 #include <fwCom/Slots.hxx>
19 
20 #include <fwData/Boolean.hpp>
21 #include <fwData/Plane.hpp>
22 #include <fwData/PlaneList.hpp>
23 
24 #include <fwServices/macros.hpp>
25 
26 #include <vtkActor.h>
27 #include <vtkAssemblyNode.h>
28 #include <vtkAssemblyPath.h>
29 #include <vtkCellPicker.h>
30 #include <vtkCommand.h>
31 #include <vtkPolyDataMapper.h>
32 #include <vtkRenderer.h>
33 #include <vtkRenderWindowInteractor.h>
34 
35 fwServicesRegisterMacro( ::fwRenderVTK::IAdaptor, ::visuVTKAdaptor::SPlaneList);
36 
37 namespace visuVTKAdaptor
38 {
39 
40 static const ::fwCom::Signals::SignalKeyType s_SELECTED_SIG = "selected";
41 
42 static const ::fwCom::Slots::SlotKeyType s_UPDATE_SELECTION_SLOT = "updateSelection";
43 static const ::fwCom::Slots::SlotKeyType s_UPDATE_PLANES_SLOT = "updatePlanes";
44 static const ::fwCom::Slots::SlotKeyType s_SHOW_PLANES_SLOT = "showPlanes";
45 
46 static const ::fwServices::IService::KeyType s_PLANES_INOUT = "planes";
47 
48 //------------------------------------------------------------------------------
49 
50 void notifyDeletePlane( ::fwData::PlaneList::sptr planeList, ::fwData::Plane::sptr plane )
51 {
52  auto sig = planeList->signal< ::fwData::PlaneList::PlaneRemovedSignalType >(
54  sig->asyncEmit(plane);
55 }
56 
57 class vtkPlaneDeleteCallBack : public vtkCommand
58 {
59 
60 public:
61  //------------------------------------------------------------------------------
62 
63  static vtkPlaneDeleteCallBack* New( ::fwRenderVTK::IAdaptor* service)
64  {
65  return new vtkPlaneDeleteCallBack(service);
66  }
67 
69  m_service(service),
70  m_picker( vtkCellPicker::New() ),
71  m_propCollection( vtkPropCollection::New() )
72  {
73  m_lastPos[0] = -1;
74  m_lastPos[1] = -1;
75  m_picker->PickFromListOn();
76  m_picker->SetTolerance(0.001);
77 
78  m_display[2] = 0.0;
79  }
80 
82  {
83  m_picker->Delete();
84  m_picker = NULL;
85 
86  m_propCollection->Delete();
87  m_propCollection = NULL;
88  }
89 
90  //------------------------------------------------------------------------------
91 
92  void fillPickList()
93  {
94  m_picker->InitializePickList();
95  m_propCollection->RemoveAllItems();
96  m_service->getAllSubProps(m_propCollection);
97  m_propCollection->InitTraversal();
98 
99  vtkProp* prop;
100 
101  while ( (prop = m_propCollection->GetNextProp()) )
102  {
103  m_picker->AddPickList(prop);
104  }
105  }
106 
107  //------------------------------------------------------------------------------
108 
109  virtual void Execute( vtkObject* caller, unsigned long eventId, void*)
110  {
111  int pos[2];
112  m_service->getInteractor()->GetLastEventPosition(pos);
113 
114  if ( eventId == vtkCommand::RightButtonPressEvent )
115  {
116  std::copy(pos, pos+1, m_lastPos);
117  m_display[0] = pos[0];
118  m_display[1] = pos[1];
119 
120  this->fillPickList();
121  if (m_picker->Pick( m_display, m_service->getRenderer() ) )
122  {
123  if(getSelectedPlane())
124  {
125  SetAbortFlag(1);
126  }
127  else
128  {
129  m_pickedPlane.reset();
130  }
131  }
132  }
133  else if ( eventId == vtkCommand::RightButtonReleaseEvent &&
134  std::equal(pos, pos+1, m_lastPos) && !m_pickedPlane.expired() )
135  {
136  // backup of plane
137  ::fwData::Plane::sptr planeBackup(m_pickedPlane);
138 
139  ::fwData::PlaneList::sptr planeList = m_service->getInOut< ::fwData::PlaneList >(s_PLANES_INOUT);
140  SLM_ASSERT("PlaneList '" + s_PLANES_INOUT + "' is missing", planeList);
141 
142  planeList->getPlanes().erase
143  (
144  std::find( planeList->getPlanes().begin(), planeList->getPlanes().end(), m_pickedPlane.lock())
145  );
146  notifyDeletePlane(planeList, planeBackup);
147  }
148  }
149  //------------------------------------------------------------------------------
150 
151  bool getSelectedPlane()
152  {
153  bool isFind = false;
154  vtkPropCollection* propc = m_picker->GetActors();
155  vtkProp* prop;
156 
157  propc->InitTraversal();
158  while ( (prop = propc->GetNextProp()) )
159  {
160  ::fwRenderVTK::IAdaptor::sptr planeAdaptor = m_service->getAssociatedAdaptor(prop, 1);
161  if (planeAdaptor)
162  {
163  m_pickedPlane = planeAdaptor->getInOut< ::fwData::Plane >(SPlane::s_PLANE_INOUT);
164 
165  ::fwData::PlaneList::sptr planeList = m_service->getInOut< ::fwData::PlaneList >(s_PLANES_INOUT);
166  SLM_ASSERT("PlaneList '" + s_PLANES_INOUT + "' is missing", planeList);
167 
168  if(!planeList->getPlanes().empty())
169  {
170  ::fwData::PlaneList::PlaneListContainer::iterator itr = std::find(
171  planeList->getPlanes().begin(), planeList->getPlanes().end(), m_pickedPlane.lock());
172  if(itr != planeList->getPlanes().end() )
173  {
174  isFind = true;
175  break;
176  }
177  }
178  }
179  }
180  return isFind;
181  }
182 
183 protected:
184  ::fwRenderVTK::IAdaptor* m_service;
185  vtkPicker* m_picker;
186  vtkPropCollection* m_propCollection;
187  double m_display[3];
188  int m_lastPos[2];
189  ::fwData::Plane::wptr m_pickedPlane;
190 
191 };
192 
193 //------------------------------------------------------------------------------
194 
195 SPlaneList::SPlaneList() noexcept :
196  m_rightButtonCommand(nullptr),
197  m_planeCollectionId("")
198 {
199  newSlot(s_UPDATE_SELECTION_SLOT, &SPlaneList::updateSelection, this);
200  newSlot(s_UPDATE_PLANES_SLOT, &SPlaneList::updatePlanes, this);
201  newSlot(s_SHOW_PLANES_SLOT, &SPlaneList::showPlanes, this);
202 
203  newSignal< SelectedignalType >(s_SELECTED_SIG);
204 }
205 
206 //------------------------------------------------------------------------------
207 
208 SPlaneList::~SPlaneList() noexcept
209 {
210 }
211 
212 //------------------------------------------------------------------------------
213 
215 {
216  this->configureParams();
217 
218  const ConfigType config = this->getConfigTree().get_child("config.<xmlattr>");
219 
220  this->setPlaneCollectionId( config.get("planecollection", "") );
221 }
222 
223 //------------------------------------------------------------------------------
224 
226 {
227  this->initialize();
228 
229  m_rightButtonCommand = vtkPlaneDeleteCallBack::New(this);
230  this->getInteractor()->AddObserver( "RightButtonPressEvent", m_rightButtonCommand, 1 );
231  this->getInteractor()->AddObserver( "RightButtonReleaseEvent", m_rightButtonCommand, 1 );
232 
233  this->updating();
234 }
235 
236 //------------------------------------------------------------------------------
237 
239 {
240  ::fwData::PlaneList::sptr planeList = this->getInOut< ::fwData::PlaneList >(s_PLANES_INOUT);
241  SLM_ASSERT("PlaneList '" + s_PLANES_INOUT + "' is missing", planeList);
242 
243  bool showPlanes = planeList->getField("ShowPlanes", ::fwData::Boolean::New(true))->value();
244  if(showPlanes)
245  {
246  for(const ::fwData::Plane::sptr& plane : planeList->getPlanes())
247  {
248  // create the srv configuration for objects auto-connection
249  auto servicePlane = this->registerService< ::fwRenderVTK::IAdaptor>("::visuVTKAdaptor::SPlane");
250  servicePlane->registerInOut(plane, SPlane::s_PLANE_INOUT, true);
251 
252  servicePlane->setRenderService(this->getRenderService());
253  servicePlane->setRendererId(this->getRendererId());
254  servicePlane->setPickerId(this->getPickerId());
255 
256  if (!m_planeCollectionId.empty())
257  {
258  SPlane::dynamicCast(servicePlane)->setVtkPlaneCollection( this->getVtkObject(m_planeCollectionId) );
259  }
260  servicePlane->start();
261 
262  m_planeConnections.connect(servicePlane, SPlane::s_INTERACTION_STARTED_SIG, this->getSptr(),
263  s_UPDATE_SELECTION_SLOT);
264  }
265  }
266 }
267 
268 //------------------------------------------------------------------------------
269 
270 void SPlaneList::updatePlanes()
271 {
272  this->stopping();
273  this->starting();
274  this->setVtkPipelineModified();
275  this->requestRender();
276 }
277 
278 //------------------------------------------------------------------------------
279 
280 void SPlaneList::showPlanes(bool visible)
281 {
282  this->stopping();
283  if(visible)
284  {
285  this->starting();
286  }
287  this->setVtkPipelineModified();
288  this->requestRender();
289 }
290 
291 //------------------------------------------------------------------------------
292 
293 void SPlaneList::updateSelection(::fwData::Plane::sptr plane)
294 {
295  auto subServices = this->getRegisteredServices();
296  for (const ::fwServices::IService::wptr& adaptor: subServices)
297  {
298  SPlane::sptr planeAdaptor = SPlane::dynamicCast(adaptor.lock());
299 
300  if (planeAdaptor->getInOut< ::fwData::Plane >(SPlane::s_PLANE_INOUT) == plane)
301  {
302  planeAdaptor->selectPlane(true);
303  }
304  else
305  {
306  planeAdaptor->selectPlane(false);
307  }
308  }
309 
310  auto sig = this->signal< SelectedignalType >(s_SELECTED_SIG);
311  sig->asyncEmit(plane);
312 }
313 
314 //------------------------------------------------------------------------------
315 
317 {
318  if ( m_rightButtonCommand ) // can be not instanciated
319  {
320  this->getInteractor()->RemoveObserver(m_rightButtonCommand);
321  m_rightButtonCommand->Delete();
322  m_rightButtonCommand = 0;
323  }
324  m_planeConnections.disconnect();
325 
326  this->unregisterServices();
327 }
328 
329 //------------------------------------------------------------------------------
330 
332 {
333  KeyConnectionsMap connections;
334 
335  connections.push(s_PLANES_INOUT, ::fwData::PlaneList::s_MODIFIED_SIG, s_UPDATE_PLANES_SLOT);
336 
337  return connections;
338 }
339 
340 } //namespace visuVTKAdaptor
341 
342 #endif // ANDROID
FWRENDERVTK_API vtkRenderWindowInteractor * getInteractor()
Returns the render interactor.
This class is a helper to define the connections of a service and its data.
Definition: IService.hpp:454
void updateSelection(::fwData::Plane::sptr plane)
Slot: Update plane selection.
Definition: SPlaneList.cpp:293
This class defines a plane defined by tree points.
Definition: Plane.hpp:25
FWRENDERVTK_API vtkRenderer * getRenderer()
Returns the renderer.
The namespace visuVTKAdaptor contains the list of adaptors available for the generic scene...
FWRENDERVTK_API IAdaptor::sptr getAssociatedAdaptor(vtkProp *prop, int depth)
Returns the adaptor associated to the vtkProp.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_PLANE_REMOVED_SIG
Signal emitted when a plane is added.
Definition: PlaneList.hpp:69
static VISUVTKADAPTOR_APIconst::fwCom::Signals::SignalKeyType s_INTERACTION_STARTED_SIG
Type of signal when plane interaction is started (store current plane)
Definition: SPlane.hpp:84
virtual VISUVTKADAPTOR_API KeyConnectionsMap getAutoConnections() const override
Returns proposals to connect service slots to associated object signals, this method is used for obj/...
Definition: SPlaneList.cpp:331
VISUVTKADAPTOR_API void stopping() override
Uninitialize the service activity. The stop() method is always invoked before destroying a service...
Definition: SPlaneList.cpp:316
#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
FWRENDERVTK_API void getAllSubProps(vtkPropCollection *propc, int depth=-1)
Gets all the vtkProp associated to this adaptor.
VISUVTKADAPTOR_API void configuring() override
Configure the service before starting. Apply the configuration to service.
Definition: SPlaneList.cpp:214
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_MODIFIED_SIG
Key in m_signals map of signal m_sigModified.
This class defines a list of planes.
Definition: PlaneList.hpp:26
std::shared_ptr< DATATYPE > getInOut(const KeyType &key) const
Return the inout object at the given key. Asserts if the data is not of the right type...
Definition: IService.hxx:47
Represents a list of Plane that can be interacted with 3 points.
Definition: SPlaneList.hpp:55
VISUVTKADAPTOR_API void updating() override
Perform some computations according to object (this service is attached to) attribute values and its ...
Definition: SPlaneList.cpp:238
VISUVTKADAPTOR_API void starting() override
Initialize the service activity.
Definition: SPlaneList.cpp:225