fw4spl
SLabeledPointList.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/SLabeledPointList.hpp"
8 
9 #include "visuVTKAdaptor/SPointLabel.hpp"
10 #include "visuVTKAdaptor/SPointList.hpp"
11 
12 #include <fwCom/Signal.hxx>
13 
14 #include <fwData/Point.hpp>
15 #include <fwData/PointList.hpp>
16 
17 #include <fwDataTools/fieldHelper/Image.hpp>
18 
19 #include <fwServices/macros.hpp>
20 #include <fwServices/op/Add.hpp>
21 
22 #include <vtkActor.h>
23 #include <vtkAssemblyNode.h>
24 #include <vtkAssemblyPath.h>
25 #include <vtkCellPicker.h>
26 #include <vtkCommand.h>
27 #include <vtkCubeSource.h>
28 #include <vtkPolyDataMapper.h>
29 #include <vtkRenderer.h>
30 #include <vtkRenderWindowInteractor.h>
31 
32 #include <algorithm>
33 
34 fwServicesRegisterMacro(::fwRenderVTK::IAdaptor, ::visuVTKAdaptor::SLabeledPointList);
35 
36 namespace visuVTKAdaptor
37 {
38 
39 static const ::fwServices::IService::KeyType s_POINTLIST_INOUT = "pointList";
40 
41 //------------------------------------------------------------------------------
42 
43 class vtkLabeledPointDeleteCallBack : public vtkCommand
44 {
45 
46 public:
47  //------------------------------------------------------------------------------
48 
50  {
51  return new vtkLabeledPointDeleteCallBack(service);
52  }
53 
55  m_service(service),
56  m_picker( vtkCellPicker::New() ),
57  m_propCollection( vtkPropCollection::New() )
58  {
59  m_lastPos[0] = -1;
60  m_lastPos[1] = -1;
61  m_picker->PickFromListOn();
62  m_picker->SetTolerance(0.001);
63 
64  m_display[2] = 0.0;
65  }
66 
68  {
69  m_picker->Delete();
70  m_picker = NULL;
71 
72  m_propCollection->Delete();
73  m_propCollection = NULL;
74  }
75 
76  //------------------------------------------------------------------------------
77 
78  void fillPickList()
79  {
80  m_picker->InitializePickList();
81  m_propCollection->RemoveAllItems();
82  m_service->getAllSubProps(m_propCollection);
83  m_propCollection->InitTraversal();
84 
85  vtkProp* prop;
86 
87  while ( (prop = m_propCollection->GetNextProp()) )
88  {
89  m_picker->AddPickList(prop);
90  }
91  }
92 
93  //------------------------------------------------------------------------------
94 
95  virtual void Execute( vtkObject* caller, unsigned long eventId, void*)
96  {
97  int pos[2];
98  m_service->getInteractor()->GetLastEventPosition(pos);
99  OSLM_TRACE( "EventId: " << eventId);
100 
101  if ( eventId == vtkCommand::RightButtonPressEvent )
102  {
103  std::copy(pos, pos+1, m_lastPos);
104  m_display[0] = pos[0];
105  m_display[1] = pos[1];
106 
107  this->fillPickList();
108  if (m_picker->Pick( m_display, m_service->getRenderer() ) )
109  {
110  if(this->getSelectedPoint())
111  {
112  this->SetAbortFlag(1);
113  }
114  else
115  {
116  m_pickedPoint.reset();
117  m_pickedPointList.reset();
118  }
119  }
120  }
121  else if ( (eventId == vtkCommand::RightButtonReleaseEvent ) && !m_pickedPoint.expired() &&
122  !m_pickedPointList.expired() && std::equal(pos, pos+1, m_lastPos) )
123  {
124  ::fwData::PointList::PointListContainer& points = m_pickedPointList.lock()->getPoints();
125  ::fwData::PointList::PointListContainer::iterator itr =
126  std::find( points.begin(), points.end(), m_pickedPoint.lock() );
127  if(itr != points.end())
128  {
129  ::fwData::Point::sptr point = *itr;
130  points.erase(itr);
131  auto sig = m_pickedPointList.lock()->signal< ::fwData::PointList::PointRemovedSignalType >(
133  sig->asyncEmit(point);
134  }
135  }
136  }
137  //------------------------------------------------------------------------------
138 
139  bool getSelectedPoint()
140  {
141  bool isFind = false;
142  vtkPropCollection* propc = m_picker->GetActors();
143  vtkProp* prop;
144 
145  propc->InitTraversal();
146  while ( (prop = propc->GetNextProp()) )
147  {
148  ::fwRenderVTK::IAdaptor::sptr pointSrv = m_service->getAssociatedAdaptor(prop, 2);
149 
150  if(pointSrv)
151  {
152 
153  m_pickedPoint = pointSrv->getInOut< ::fwData::Point >(SPoint::s_POINT_INOUT);
154  m_pickedPointList = m_service->getInOut< ::fwData::PointList >(s_POINTLIST_INOUT);
155 
156  if (!m_pickedPoint.expired() && !m_pickedPointList.expired())
157  {
158  ::fwData::PointList::PointListContainer& points = m_pickedPointList.lock()->getPoints();
159  ::fwData::PointList::PointListContainer::iterator itr =
160  std::find(points.begin(), points.end(), m_pickedPoint.lock());
161  if(itr != points.end() )
162  {
163  isFind = true;
164  break;
165  }
166  }
167  }
168  }
169  return isFind;
170  }
171 
172 protected:
173  ::fwRenderVTK::IAdaptor* m_service;
174  vtkPicker* m_picker;
175  vtkPropCollection* m_propCollection;
176  double m_display[3];
177  int m_lastPos[2];
178  ::fwData::Point::wptr m_pickedPoint;
179  ::fwData::PointList::wptr m_pickedPointList;
180 
181 };
182 
183 //------------------------------------------------------------------------------
184 
185 SLabeledPointList::SLabeledPointList() noexcept :
186  m_rightButtonCommand(nullptr),
187  m_radius(7.0),
188  m_interaction(true)
189 {
190 }
191 
192 //------------------------------------------------------------------------------
193 
194 SLabeledPointList::~SLabeledPointList() noexcept
195 {
196 }
197 
198 //------------------------------------------------------------------------------
199 
201 {
202  this->configureParams();
203 
204  const ConfigType config = this->getConfigTree().get_child("config.<xmlattr>");
205 
206  const std::string hexaColor = config.get< std::string >("color", "");
207  m_ptColor = ::fwData::Color::New();
208  if (!hexaColor.empty())
209  {
210  m_ptColor->setRGBA(hexaColor);
211  }
212 
213  const std::string radius = config.get< std::string >("radius", "");
214  if(!radius.empty())
215  {
216  m_radius = std::stod(radius);
217  }
218 
219  const std::string interaction = config.get< std::string >("interaction", "");
220  if(!interaction.empty())
221  {
222  SLM_FATAL_IF("value for 'interaction' must be 'on' or 'off', actual: " + interaction,
223  interaction != "on" && interaction != "off");
224  m_interaction = (interaction == "on");
225  }
226 }
227 
228 //------------------------------------------------------------------------------
229 
231 {
232  this->initialize();
233 
234  if(m_interaction)
235  {
236  m_rightButtonCommand = vtkLabeledPointDeleteCallBack::New(this);
237  this->getInteractor()->AddObserver( "RightButtonPressEvent", m_rightButtonCommand, 1 );
238  this->getInteractor()->AddObserver( "RightButtonReleaseEvent", m_rightButtonCommand, 1 );
239  }
240 
241  this->updating();
242 }
243 
244 //------------------------------------------------------------------------------
245 
247 {
248  // get PointList in image Field then install distance service if required
249  ::fwData::PointList::sptr landmarks = this->getInOut< ::fwData::PointList >(s_POINTLIST_INOUT);
250 
251  this->unregisterServices();
252 
253  if ( !landmarks->getPoints().empty() )
254  {
255  // create the srv configuration for objects auto-connection
256  auto pointListAdaptor = this->registerService< ::visuVTKAdaptor::SPointList>("::visuVTKAdaptor::SPointList");
257  // register the point list
258  pointListAdaptor->registerInput(landmarks, SPointList::s_POINTLIST_INPUT, true);
259 
260  pointListAdaptor->setColor(m_ptColor);
261  pointListAdaptor->setRadius(m_radius);
262  pointListAdaptor->setInteraction(m_interaction);
263 
264  pointListAdaptor->setPickerId( this->getPickerId() );
265  pointListAdaptor->setRenderService( this->getRenderService() );
266  pointListAdaptor->start();
267 
268  for( ::fwData::Point::sptr point : landmarks->getPoints() )
269  {
270  auto serviceLabel = this->registerService< ::fwRenderVTK::IAdaptor>("::visuVTKAdaptor::SPointLabel");
271  // register the point list
272  serviceLabel->registerInput(point, SPointLabel::s_POINT_INPUT, true);
273 
274  serviceLabel->setRenderService( this->getRenderService() );
275  serviceLabel->start();
276  }
277  }
278 
279  this->setVtkPipelineModified();
280  this->requestRender();
281 }
282 
283 //------------------------------------------------------------------------------
284 
286 {
287  if ( m_rightButtonCommand ) // can be not instanciated (use of SLabeledPointList::show() )
288  {
289  this->getInteractor()->RemoveObserver(m_rightButtonCommand);
290  m_rightButtonCommand->Delete();
291  m_rightButtonCommand = 0;
292  }
293 
294  this->unregisterServices();
295  this->requestRender();
296 }
297 
298 //------------------------------------------------------------------------------
299 
301 {
302  KeyConnectionsMap connections;
303  connections.push(s_POINTLIST_INOUT, ::fwData::PointList::s_MODIFIED_SIG, s_UPDATE_SLOT);
304  connections.push(s_POINTLIST_INOUT, ::fwData::PointList::s_POINT_ADDED_SIG, s_UPDATE_SLOT);
305  connections.push(s_POINTLIST_INOUT, ::fwData::PointList::s_POINT_REMOVED_SIG, s_UPDATE_SLOT);
306 
307  return connections;
308 }
309 
310 //------------------------------------------------------------------------------
311 
312 } //namespace visuVTKAdaptor
FWRENDERVTK_API vtkRenderWindowInteractor * getInteractor()
Returns the render interactor.
VISUVTKADAPTOR_API void updating() override
Perform some computations according to object (this service is attached to) attribute values and its ...
This class is a helper to define the connections of a service and its data.
Definition: IService.hpp:454
FWRENDERVTK_API vtkRenderer * getRenderer()
Returns the renderer.
The namespace visuVTKAdaptor contains the list of adaptors available for the generic scene...
This class define a 3D point.
Definition: Point.hpp:22
VISUVTKADAPTOR_API void starting() override
Initialize the service activity.
FWRENDERVTK_API IAdaptor::sptr getAssociatedAdaptor(vtkProp *prop, int depth)
Returns the adaptor associated to the vtkProp.
#define OSLM_TRACE(message)
Definition: spyLog.hpp:230
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_POINT_ADDED_SIG
Signal emitted when a Point is added.
virtual VISUVTKADAPTOR_API KeyConnectionsMap getAutoConnections() const override
Returns proposals to connect service slots to associated object signals, this method is used for obj/...
VISUVTKADAPTOR_API void configuring() override
Configure the service before starting. Apply the configuration to service.
VISUVTKADAPTOR_API void stopping() override
Uninitialize the service activity. The stop() method is always invoked before destroying a service...
Adaptor to display a labeled point list.
FWRENDERVTK_API void getAllSubProps(vtkPropCollection *propc, int depth=-1)
Gets all the vtkProp associated to this adaptor.
#define SLM_FATAL_IF(message, cond)
Definition: spyLog.hpp:287
This class defines a list of points.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_MODIFIED_SIG
Key in m_signals map of signal m_sigModified.
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
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_POINT_REMOVED_SIG
Signal emitted when a Point is added.