fw4spl
visu/visuVTKAdaptor/src/visuVTKAdaptor/SLandmarks.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/SLandmarks.hpp"
8 
9 #include <fwCom/Signal.hpp>
10 #include <fwCom/Signal.hxx>
11 #include <fwCom/Signals.hpp>
12 #include <fwCom/Slot.hpp>
13 #include <fwCom/Slot.hxx>
14 #include <fwCom/Slots.hpp>
15 #include <fwCom/Slots.hxx>
16 
17 #include <fwData/Boolean.hpp>
18 #include <fwData/Image.hpp>
19 #include <fwData/Landmarks.hpp>
20 #include <fwData/Material.hpp>
21 #include <fwData/Point.hpp>
22 #include <fwData/PointList.hpp>
23 
24 #include <fwDataTools/fieldHelper/Image.hpp>
25 
26 #include <fwRenderVTK/vtk/fwHandleRepresentation3D.hpp>
27 #include <fwRenderVTK/vtk/Helpers.hpp>
28 #include <fwRenderVTK/vtk/MarkedSphereHandleRepresentation.hpp>
29 
30 #include <fwServices/macros.hpp>
31 #include <fwServices/op/Add.hpp>
32 
33 #include <vtkActor.h>
34 #include <vtkAssemblyNode.h>
35 #include <vtkAssemblyPath.h>
36 #include <vtkCellPicker.h>
37 #include <vtkCommand.h>
38 #include <vtkCubeSource.h>
39 #include <vtkPolyDataMapper.h>
40 #include <vtkProperty.h>
41 #include <vtkRenderer.h>
42 #include <vtkRenderWindowInteractor.h>
43 #include <vtkTextActor.h>
44 #include <vtkTextMapper.h>
45 #include <vtkTextProperty.h>
46 
47 #include <algorithm>
48 
49 fwServicesRegisterMacro( ::fwRenderVTK::IAdaptor, ::visuVTKAdaptor::SLandmarks, ::fwData::Landmarks );
50 
51 namespace visuVTKAdaptor
52 {
53 
54 static const ::fwCom::Slots::SlotKeyType s_ADD_POINT_SLOT = "addPoint";
55 static const ::fwCom::Slots::SlotKeyType s_INSERT_POINT_SLOT = "insertPoint";
56 static const ::fwCom::Slots::SlotKeyType s_REMOVE_POINT_SLOT = "removePoint";
57 static const ::fwCom::Slots::SlotKeyType s_ADD_GROUP_SLOT = "addGroup";
58 static const ::fwCom::Slots::SlotKeyType s_REMOVE_GROUP_SLOT = "removeGroup";
59 static const ::fwCom::Slots::SlotKeyType s_MODIFY_GROUP_SLOT = "modifyGroup";
60 static const ::fwCom::Slots::SlotKeyType s_MODIFY_POINT_SLOT = "modifyPoint";
61 static const ::fwCom::Slots::SlotKeyType s_RENAME_GROUP_SLOT = "renameGroup";
62 static const ::fwCom::Slots::SlotKeyType s_SELECT_POINT_SLOT = "selectPoint";
63 static const ::fwCom::Slots::SlotKeyType s_DESELECT_POINT_SLOT = "deselectPoint";
64 static const ::fwCom::Slots::SlotKeyType s_SHOW_SLOT = "show";
65 
66 const ::fwServices::IService::KeyType s_LANDMARKS_INOUT = "landmarks";
67 
68 //------------------------------------------------------------------------------
69 
70 class vtkLandmarkUpdateCallBack : public vtkCommand
71 {
72 
73 public:
74 
75 //------------------------------------------------------------------------------
76 
77  static vtkLandmarkUpdateCallBack* New( ::fwData::Landmarks::sptr landmarks,
78  const ::fwCom::SlotBase::sptr& pointModifiedSlot,
79  const std::string& groupName,
80  size_t pointIndex,
81  vtkAbstractPropPicker* picker,
82  vtkRenderer* renderer,
83  vtkActor2D* labelActor)
84  {
85  return new vtkLandmarkUpdateCallBack(landmarks, pointModifiedSlot, groupName, pointIndex, picker, renderer,
86  labelActor);
87  }
88 
89 //------------------------------------------------------------------------------
90 
91  vtkLandmarkUpdateCallBack( ::fwData::Landmarks::sptr landmarks,
92  const ::fwCom::SlotBase::sptr& pointModifiedSlot,
93  const std::string& groupName,
94  size_t pointIndex,
95  vtkAbstractPropPicker* picker,
96  vtkRenderer* renderer,
97  vtkActor2D* labelActor) :
98  m_landmarks(landmarks),
99  m_pointModifiedSlot(pointModifiedSlot),
100  m_groupName(groupName),
101  m_pointIndex(pointIndex),
102  m_picker(picker),
103  m_renderer(renderer),
104  m_labelActor(labelActor)
105  {
106  }
107 
108 //------------------------------------------------------------------------------
109 
110  void updateInfo(const std::string& groupName, size_t pointIndex)
111  {
112  m_groupName = groupName;
113  m_pointIndex = pointIndex;
114  }
115 
116 //------------------------------------------------------------------------------
117 
118  virtual void Execute( vtkObject* caller, unsigned long eventId, void*)
119  {
120  vtkHandleWidget* handler = vtkHandleWidget::SafeDownCast(caller);
121  if (!handler)
122  {
123  return;
124  }
125 
126  if ( eventId == vtkCommand::StartInteractionEvent)
127  {
128  handler->AddObserver(vtkCommand::EndInteractionEvent, this );
129  handler->AddObserver(vtkCommand::InteractionEvent, this );
130 
131  }
132  else if ( eventId == vtkCommand::EndInteractionEvent )
133  {
134  handler->RemoveObservers(vtkCommand::EndInteractionEvent, this );
135  handler->RemoveObservers(vtkCommand::InteractionEvent, this );
136  }
137 
138  vtkHandleRepresentation* representation = handler->GetHandleRepresentation();
139  SLM_ASSERT("handler not instanced", handler);
140  double* world = representation->GetWorldPosition();
141 
142  if ( eventId == vtkCommand::InteractionEvent)
143  {
144  double display[3];
145  int x, y;
146  handler->GetInteractor()->GetLastEventPosition(x, y);
147  display[0] = x;
148  display[1] = y;
149  display[2] = 0;
150 
151  if ( m_picker && m_picker->Pick( display, m_renderer ) )
152  {
153  ::fwRenderVTK::vtk::getNearestPickedPosition(m_picker, m_renderer, world);
154  }
155 
156  auto& point = m_landmarks->getPoint(m_groupName, m_pointIndex);
157  std::copy( world, world+3, point.begin() );
158 
159  representation->SetWorldPosition(world);
160  m_labelActor->GetPositionCoordinate()->SetValue(world);
161 
162  auto sig = m_landmarks->signal< ::fwData::Landmarks::PointModifiedSigType >
164  {
165  ::fwCom::Connection::Blocker block(sig->getConnection(m_pointModifiedSlot));
166  sig->asyncEmit(m_groupName, m_pointIndex);
167  }
168  }
169  else if (eventId == vtkCommand::StartInteractionEvent)
170  {
171  auto sig = m_landmarks->signal< ::fwData::Landmarks::PointSelectedSignalType >
173  sig->asyncEmit(m_groupName, m_pointIndex);
174  }
175  }
176 
177 protected:
178 
179  ::fwData::Landmarks::sptr m_landmarks;
180 
181  const ::fwCom::SlotBase::sptr m_pointModifiedSlot;
182 
183  std::string m_groupName;
184 
185  size_t m_pointIndex;
186 
187  vtkAbstractPropPicker* m_picker;
188 
189  vtkRenderer* m_renderer;
190 
191  vtkActor2D* m_labelActor;
192 };
193 
194 //------------------------------------------------------------------------------
195 
196 class vtkDeselectLandmarksCallBack : public vtkCommand
197 {
198 
199 public:
200 
201 //------------------------------------------------------------------------------
202 
203  static vtkDeselectLandmarksCallBack* New()
204  {
205  return new vtkDeselectLandmarksCallBack();
206  }
207 
208 //------------------------------------------------------------------------------
209 
211  {
212  }
213 
214  //------------------------------------------------------------------------------
215 
216  void setAdaptor(const SLandmarks::sptr& adaptor)
217  {
218  m_adaptor = adaptor;
219  }
220 
221 //------------------------------------------------------------------------------
222 
223  virtual void Execute( vtkObject* /*caller*/, unsigned long /*eventId*/, void*)
224  {
225  m_adaptor->deselect();
226  }
227 
228 protected:
229 
230  SLandmarks::sptr m_adaptor;
231 };
232 
233 //------------------------------------------------------------------------------
234 
235 SLandmarks::SLandmarks() noexcept :
236  m_noSelectionCommand(nullptr),
237  m_count(0),
238  m_interaction(true)
239 {
240  this->newSlot(s_ADD_POINT_SLOT, &SLandmarks::addPoint, this);
241  this->newSlot(s_INSERT_POINT_SLOT, &SLandmarks::insertPoint, this);
242  this->newSlot(s_REMOVE_POINT_SLOT, &SLandmarks::removePoint, this);
243  this->newSlot(s_MODIFY_POINT_SLOT, &SLandmarks::modifyPoint, this);
244  this->newSlot(s_ADD_GROUP_SLOT, &SLandmarks::addGroup, this);
245  this->newSlot(s_REMOVE_GROUP_SLOT, &SLandmarks::removeGroup, this);
246  this->newSlot(s_MODIFY_GROUP_SLOT, &SLandmarks::modifyGroup, this);
247  this->newSlot(s_RENAME_GROUP_SLOT, &SLandmarks::renameGroup, this);
248  this->newSlot(s_SELECT_POINT_SLOT, &SLandmarks::selectPoint, this);
249  this->newSlot(s_DESELECT_POINT_SLOT, &SLandmarks::deselectPoint, this);
250  this->newSlot(s_SHOW_SLOT, &SLandmarks::show, this);
251 }
252 
253 //------------------------------------------------------------------------------
254 
255 SLandmarks::~SLandmarks() noexcept
256 {
257 }
258 
259 //------------------------------------------------------------------------------
260 
262 {
263  this->configureParams();
264 
265  const ConfigType config = this->getConfigTree().get_child("config.<xmlattr>");
266 
267  const std::string interaction = config.get<std::string>("interaction", "on");
268 
269  SLM_FATAL_IF("value for 'interaction' must be 'on' or 'off', actual: " + interaction,
270  interaction != "on" && interaction != "off");
271 
272  m_interaction = (interaction == "on");
273 }
274 
275 //------------------------------------------------------------------------------
276 
278 {
279  this->initialize();
280 
281  vtkDeselectLandmarksCallBack* callback = vtkDeselectLandmarksCallBack::New();
282  callback->setAdaptor(this->getSptr());
283  m_noSelectionCommand = callback;
284  this->getInteractor()->AddObserver(vtkCommand::RightButtonPressEvent, m_noSelectionCommand);
285  this->getInteractor()->AddObserver(vtkCommand::RightButtonReleaseEvent, m_noSelectionCommand);
286 
287  this->updating();
288 }
289 
290 //------------------------------------------------------------------------------
291 
293 {
294  this->clearLandmarks();
295 
296  ::fwData::Landmarks::csptr landmarks = this->getInOut< ::fwData::Landmarks >(s_LANDMARKS_INOUT);
297  SLM_ASSERT("'landmarks' inout is not defined", landmarks);
298 
299  ::fwData::Landmarks::GroupNameContainer groupNames = landmarks->getGroupNames();
300 
301  for(auto& name : groupNames)
302  {
303  this->addGroup(name);
304  }
305 
306  this->getRenderer()->ResetCameraClippingRange();
307  this->setVtkPipelineModified();
308  this->requestRender();
309 }
310 
311 //------------------------------------------------------------------------------
312 
314 {
315  this->clearLandmarks();
316  if (m_noSelectionCommand)
317  {
318  this->getInteractor()->RemoveObserver(m_noSelectionCommand);
319  m_noSelectionCommand->Delete();
320  m_noSelectionCommand = nullptr;
321  }
322  this->requestRender();
323 }
324 
325 //------------------------------------------------------------------------------
326 
327 void SLandmarks::addPoint(std::string groupName)
328 {
329  ::fwData::Landmarks::sptr landmarks = this->getInOut< ::fwData::Landmarks >(s_LANDMARKS_INOUT);
330  SLM_ASSERT("'landmarks' inout is not defined", landmarks);
331 
332  for(size_t i = m_handles[groupName].size(); i < landmarks->getNumberOfPoints(groupName); ++i)
333  {
334  auto handle = this->newHandle(landmarks, groupName, i);
335  m_handles[groupName].push_back(handle);
336  }
337 
338  this->getRenderer()->ResetCameraClippingRange();
339  this->setVtkPipelineModified();
340  this->requestRender();
341 }
342 
343 //------------------------------------------------------------------------------
344 
345 void SLandmarks::insertPoint(std::string groupName, size_t index)
346 {
347  ::fwData::Landmarks::sptr landmarks = this->getInOut< ::fwData::Landmarks >(s_LANDMARKS_INOUT);
348  SLM_ASSERT("'landmarks' inout is not defined", landmarks);
349 
350  auto handle = this->newHandle(landmarks, groupName, index);
351 
352  LandmarksWidgetContainerType& landmarkHandleGroup = m_handles[groupName];
353  landmarkHandleGroup.insert(
354  landmarkHandleGroup.begin() + static_cast<GroupWidgetsMapType::difference_type>(index), handle);
355 
356  this->getRenderer()->ResetCameraClippingRange();
357  this->setVtkPipelineModified();
358  this->requestRender();
359 }
360 
361 //------------------------------------------------------------------------------
362 
363 void SLandmarks::removePoint(std::string groupName, size_t index)
364 {
365  if (m_timer && m_selectedPoint.first == groupName && m_selectedPoint.second == index)
366  {
367  m_timer->stop();
368  m_timer.reset();
369  }
370  LandmarksWidgetContainerType& landmarkHandleGroup = m_handles[groupName];
371 
372  auto& handleToRemove = landmarkHandleGroup[index];
373 
374  vtkActor2D* label = m_labels[handleToRemove];
375  this->getRenderer()->RemoveViewProp(label);
376  label->Delete();
377 
378  vtkCommand* command = m_commands[handleToRemove];
379  handleToRemove->RemoveObserver(command);
380  command->Delete();
381 
382  handleToRemove->Off();
383  handleToRemove->SetInteractor(nullptr);
384 
385  this->m_propCollection->RemoveItem(handleToRemove->GetRepresentation());
386 
387  m_commands.erase(handleToRemove);
388  m_labels.erase(handleToRemove);
389  landmarkHandleGroup.erase(landmarkHandleGroup.begin() + static_cast<GroupWidgetsMapType::difference_type>(index));
390 
391  for(size_t i = index; i < landmarkHandleGroup.size(); ++i)
392  {
393  auto& handle = landmarkHandleGroup.at(i);
394  vtkLandmarkUpdateCallBack* commandToUpdate = dynamic_cast<vtkLandmarkUpdateCallBack* >(m_commands[handle]);
395  commandToUpdate->updateInfo(groupName, i);
396 
397  vtkActor2D* labelToUpdate = m_labels[handle];
398  vtkSmartPointer<vtkTextMapper> textMapper = vtkTextMapper::SafeDownCast(labelToUpdate->GetMapper());
399  const std::string label = groupName + "_" + std::to_string(i);
400  textMapper->SetInput(label.c_str());
401  }
402 
403  this->setVtkPipelineModified();
404  this->requestRender();
405 }
406 
407 //------------------------------------------------------------------------------
408 
409 void SLandmarks::modifyGroup(std::string groupName)
410 {
411  ::fwData::Landmarks::csptr landmarks = this->getInOut< ::fwData::Landmarks >(s_LANDMARKS_INOUT);
412  SLM_ASSERT("'landmarks' inout is not defined", landmarks);
413 
414  const ::fwData::Landmarks::LandmarksGroup& group = landmarks->getGroup(groupName);
415 
416  LandmarksWidgetContainerType& landmarkHandleGroup = m_handles[groupName];
417 
418  for(auto& handle : landmarkHandleGroup)
419  {
420  const ::fwData::Landmarks::ColorType& color = group.m_color;
421 
422  vtkSmartPointer< ::fwRenderVTK::vtk::fwHandleRepresentation3D> rep =
423  ::fwRenderVTK::vtk::fwHandleRepresentation3D::SafeDownCast(handle->GetHandleRepresentation());
424 
425  if (group.m_shape == ::fwData::Landmarks::Shape::CUBE)
426  {
427  rep->SetShapeRepresentation(::fwRenderVTK::vtk::fwHandleRepresentation3D::CUBE);
428  }
429  else
430  {
431  rep->SetShapeRepresentation(::fwRenderVTK::vtk::fwHandleRepresentation3D::SPHERE);
432  }
433 
434  rep->GetSelectedProperty()->SetOpacity(color[3]);
435  rep->GetMarkerProperty()->SetOpacity(color[3]);
436  rep->GetProperty()->SetColor(color[0], color[1], color[2]);
437  rep->GetProperty()->SetOpacity(color[3]);
438  rep->SetHandleSize(group.m_size);
439  rep->SetVisibility(group.m_visibility);
440 
441  vtkActor2D* textActor = m_labels[handle];
442  vtkSmartPointer<vtkTextMapper> textMapper = vtkTextMapper::SafeDownCast(textActor->GetMapper());
443  textMapper->GetTextProperty()->SetColor(color[0], color[1], color[2]);
444  textActor->SetVisibility(group.m_visibility);
445  }
446 
447  this->getRenderer()->ResetCameraClippingRange();
448  this->setVtkPipelineModified();
449  this->requestRender();
450 }
451 
452 //------------------------------------------------------------------------------
453 
454 void SLandmarks::removeGroup(std::string groupName)
455 {
456  const size_t nbPoints = m_handles[groupName].size();
457 
458  // It is more efficient to walk through our vector backwards.
459  // That way we avoid useless label renaming.
460  for(size_t i = nbPoints; i > 0; --i)
461  {
462  this->removePoint(groupName, i - 1);
463  }
464 
465  m_handles.erase(groupName);
466 
467  this->setVtkPipelineModified();
468  this->requestRender();
469 }
470 
471 //------------------------------------------------------------------------------
472 
473 void SLandmarks::addGroup(std::string groupName)
474 {
475  ::fwData::Landmarks::sptr landmarks = this->getInOut< ::fwData::Landmarks >(s_LANDMARKS_INOUT);
476  SLM_ASSERT("'landmarks' inout is not defined", landmarks);
477 
478  const size_t ptNumber = landmarks->getNumberOfPoints(groupName);
479 
480  for(size_t index = 0; index < ptNumber; ++index)
481  {
482  auto handle = this->newHandle(landmarks, groupName, index);
483  m_handles[groupName].push_back(handle);
484  }
485 
486  this->getRenderer()->ResetCameraClippingRange();
487  this->setVtkPipelineModified();
488  this->requestRender();
489 }
490 
491 //------------------------------------------------------------------------------
492 
493 void SLandmarks::modifyPoint(std::string groupName, size_t index)
494 {
495  ::fwData::Landmarks::sptr landmarks = this->getInOut< ::fwData::Landmarks >(s_LANDMARKS_INOUT);
496  SLM_ASSERT("'landmarks' inout is not defined", landmarks);
497 
498  ::fwData::Landmarks::PointType& point = landmarks->getPoint(groupName, index);
499  LandmarkWidgetType& widget = m_handles.at(groupName).at(index);
500 
501  vtkHandleRepresentation* handleRep = vtkHandleRepresentation::SafeDownCast(widget->GetRepresentation());
502  handleRep->SetWorldPosition(point.data());
503 
504  vtkActor2D* textActor = m_labels[widget];
505  textActor->GetPositionCoordinate()->SetValue(point.data());
506 
507  this->getRenderer()->ResetCameraClippingRange();
508  this->setVtkPipelineModified();
509  this->requestRender();
510 }
511 
512 //------------------------------------------------------------------------------
513 
514 void SLandmarks::renameGroup(std::string oldName, std::string newName)
515 {
516  LandmarksWidgetContainerType& landmarkHandleGroup = m_handles[oldName];
517  m_handles.insert(std::make_pair(newName, landmarkHandleGroup));
518 
519  size_t count = 0;
520  for(auto& handle : landmarkHandleGroup)
521  {
522  vtkActor2D* textActor = m_labels[handle];
523 
524  vtkCommand* command = m_commands[handle];
525  vtkLandmarkUpdateCallBack* updateCallback = dynamic_cast<vtkLandmarkUpdateCallBack* >(command);
526  SLM_ASSERT("Missing landmark command", updateCallback);
527  updateCallback->updateInfo(newName, count);
528 
529  vtkSmartPointer<vtkTextMapper> textMapper = vtkTextMapper::SafeDownCast(textActor->GetMapper());
530  const std::string label = newName + "_" + std::to_string(count);
531  textMapper->SetInput(label.c_str());
532  ++count;
533  }
534 
535  m_handles.erase(oldName);
536 
537  this->setVtkPipelineModified();
538  this->requestRender();
539 }
540 
541 //------------------------------------------------------------------------------
542 
543 void SLandmarks::selectPoint(std::string groupName, size_t index)
544 {
545  // deselect the current selected point
546  if (m_timer)
547  {
548  this->deselectPoint(m_selectedPoint.first, m_selectedPoint.second);
549  }
550 
551  m_selectedPoint.first = groupName;
552  m_selectedPoint.second = index;
553 
554  LandmarkWidgetType& widget =
555  m_handles.at(groupName).at(index);
556 
557  vtkSmartPointer< ::fwRenderVTK::vtk::fwHandleRepresentation3D> rep =
558  ::fwRenderVTK::vtk::fwHandleRepresentation3D::SafeDownCast(widget->GetHandleRepresentation());
559 
560  const double* color = rep->GetProperty()->GetColor();
561 
562  m_timer = m_associatedWorker->createTimer();
563 
564  ::fwThread::Timer::TimeDurationType duration = std::chrono::milliseconds(500);
565 
566  const std::array<double, 3> color1 = {{color[0], color[1], color[2]}};
567  const std::array<double, 3> color2 = {{0., 1., 0.}};
568 
569  m_count = 0;
570  m_timer->setFunction(std::bind(&SLandmarks::changeColor, this, rep, color1, color2));
571  m_timer->setDuration(duration);
572  m_timer->start();
573 
574  this->setVtkPipelineModified();
575  this->requestRender();
576 }
577 
578 //------------------------------------------------------------------------------
579 
580 void SLandmarks::deselectPoint(std::string groupName, size_t index)
581 {
582  if(m_timer)
583  {
584  m_timer->stop();
585  m_timer.reset();
586  }
587 
588  ::fwData::Landmarks::sptr landmarks = this->getInOut< ::fwData::Landmarks >(s_LANDMARKS_INOUT);
589  SLM_ASSERT("'landmarks' inout is not defined", landmarks);
590 
591  LandmarkWidgetType& widget = m_handles.at(groupName).at(index);
592 
593  vtkSmartPointer< ::fwRenderVTK::vtk::fwHandleRepresentation3D> rep =
594  ::fwRenderVTK::vtk::fwHandleRepresentation3D::SafeDownCast(widget->GetHandleRepresentation());
595 
596  ::fwData::Landmarks::ColorType& color = landmarks->getGroup(groupName).m_color;
597 
598  double castedColour[3] = { static_cast< double >(color[0]),
599  static_cast< double >(color[1]),
600  static_cast< double >(color[2]) };
601 
602  rep->GetProperty()->SetColor(castedColour);
603  this->setVtkPipelineModified();
604  this->requestRender();
605 }
606 
607 //------------------------------------------------------------------------------
608 
610 {
611  if (m_timer)
612  {
613  ::fwData::Landmarks::sptr landmarks = this->getInOut< ::fwData::Landmarks >(s_LANDMARKS_INOUT);
614  SLM_ASSERT("'landmarks' inout is not defined", landmarks);
615 
616  this->deselectPoint(m_selectedPoint.first, m_selectedPoint.second);
617  auto sig = landmarks->signal< ::fwData::Landmarks::PointDeselectedSignalType >(
619  ::fwCom::Connection::Blocker block(sig->getConnection(this->slot(s_DESELECT_POINT_SLOT)));
620  sig->asyncEmit(m_selectedPoint.first, m_selectedPoint.second);
621  }
622 }
623 
624 //------------------------------------------------------------------------------
625 
626 void SLandmarks::changeColor(const vtkSmartPointer< ::fwRenderVTK::vtk::fwHandleRepresentation3D >& rep,
627  const std::array<double, 3>& color1, const std::array<double, 3>& color2)
628 {
629  std::array<double, 3> color;
630  if (m_count%2 == 0)
631  {
632  color = color2;
633  }
634  else
635  {
636  color = color1;
637  }
638 
639  rep->GetProperty()->SetColor(color.data());
640 
641  ++m_count;
642  this->setVtkPipelineModified();
643  this->requestRender();
644 }
645 
646 //------------------------------------------------------------------------------
647 
648 void SLandmarks::clearLandmarks()
649 {
650  while (!m_handles.empty())
651  {
652  const std::string name = m_handles.begin()->first;
653  this->removeGroup(name);
654  }
655 }
656 
657 //------------------------------------------------------------------------------
658 
659 vtkSmartPointer< vtkHandleWidget > SLandmarks::newHandle(const ::fwData::Landmarks::sptr& landmarks,
660  const std::string& groupName,
661  size_t pointIndex)
662 {
663  const ::fwData::Landmarks::LandmarksGroup& group = landmarks->getGroup(groupName);
664  ::fwData::Landmarks::PointType& point = landmarks->getPoint(groupName, pointIndex);
665 
666  vtkSmartPointer< vtkHandleWidget > handle = vtkSmartPointer<vtkHandleWidget>::New();
667 
668  const ::fwData::Landmarks::ColorType& color = group.m_color;
669 
670  // TODO add option for cube representation
672  ::fwRenderVTK::vtk::fwHandleRepresentation3D::New();
673 
674  if (group.m_shape == ::fwData::Landmarks::Shape::SPHERE)
675  {
676 
677  pointRep->SetShapeRepresentation(::fwRenderVTK::vtk::fwHandleRepresentation3D::SPHERE);
678  }
679  else
680  {
681  pointRep->SetShapeRepresentation(::fwRenderVTK::vtk::fwHandleRepresentation3D::CUBE);
682  }
683  pointRep->GetSelectedProperty()->SetOpacity(color[3]);
684  pointRep->GetMarkerProperty()->SetOpacity(color[3]);
685  pointRep->GetProperty()->SetColor(color[0], color[1], color[2]);
686  pointRep->GetProperty()->SetOpacity(color[3]);
687  pointRep->SetHandleSize(group.m_size);
688  pointRep->SetVisibility(group.m_visibility);
689 
690  pointRep->SetWorldPosition(point.data());
691 
692  handle->SetRepresentation(pointRep);
693  handle->SetPriority(0.8f);
694 
695  handle->SetInteractor( this->getInteractor() );
696  handle->KeyPressActivationOff();
697 
698  if (!m_interaction)
699  {
700  handle->ProcessEventsOff();
701  handle->ManagesCursorOff();
702  }
703 
704  handle->On();
705 
706  // We don't want to add pointRep to the renderer, handle is already managing that.
707  this->registerProp(pointRep);
708 
709  // create label
710  const std::string label = groupName + "_" + std::to_string(pointIndex);
711 
712  vtkActor2D* textActor = vtkActor2D::New();
713  vtkSmartPointer<vtkTextMapper> textMapper = vtkSmartPointer< vtkTextMapper>::New();
714  textMapper->GetTextProperty()->SetFontFamilyToCourier(); // Fixed-width font
715  textMapper->GetTextProperty()->ShadowOn(); // better contrast
716  textMapper->GetTextProperty()->BoldOn();
717  textMapper->GetTextProperty()->SetFontSize(15);
718  textMapper->GetTextProperty()->SetColor(color[0], color[1], color[2]);
719  textMapper->SetInput(label.c_str());
720 
721  textActor->SetMapper(textMapper);
722  textActor->GetPositionCoordinate()->SetCoordinateSystemToWorld();
723  textActor->GetPosition2Coordinate()->SetCoordinateSystemToWorld();
724  textActor->GetPositionCoordinate()->SetValue(point.data());
725 
726  m_labels.insert(std::make_pair(handle, textActor));
727 
728  this->addToRenderer(textActor);
729 
730  const auto& slot = this->slot(s_MODIFY_POINT_SLOT);
731 
732  vtkLandmarkUpdateCallBack* updateCallback;
733  updateCallback = vtkLandmarkUpdateCallBack::New(landmarks, slot, groupName, pointIndex, this->getPicker(),
734  this->getRenderer(), textActor);
735 
736  m_commands.insert(std::make_pair(handle, updateCallback));
737 
738  handle->AddObserver(vtkCommand::StartInteractionEvent, updateCallback);
739 
740  return handle;
741 }
742 
743 //------------------------------------------------------------------------------
744 
745 void SLandmarks::show(bool b)
746 {
747  if (b)
748  {
749  this->starting();
750  }
751  else
752  {
753  this->stopping();
754  }
755 }
756 
757 //------------------------------------------------------------------------------
758 
760 {
761  KeyConnectionsMap connections;
762 
763  connections.push(s_LANDMARKS_INOUT, ::fwData::Landmarks::s_POINT_ADDED_SIG, s_ADD_POINT_SLOT);
764  connections.push(s_LANDMARKS_INOUT, ::fwData::Landmarks::s_POINT_INSERTED_SIG, s_INSERT_POINT_SLOT);
765  connections.push(s_LANDMARKS_INOUT, ::fwData::Landmarks::s_POINT_REMOVED_SIG, s_REMOVE_POINT_SLOT);
766  connections.push(s_LANDMARKS_INOUT, ::fwData::Landmarks::s_GROUP_ADDED_SIG, s_ADD_GROUP_SLOT);
767  connections.push(s_LANDMARKS_INOUT, ::fwData::Landmarks::s_GROUP_REMOVED_SIG, s_REMOVE_GROUP_SLOT);
768  connections.push(s_LANDMARKS_INOUT, ::fwData::Landmarks::s_GROUP_MODIFIED_SIG, s_MODIFY_GROUP_SLOT);
769  connections.push(s_LANDMARKS_INOUT, ::fwData::Landmarks::s_POINT_MODIFIED_SIG, s_MODIFY_POINT_SLOT);
770  connections.push(s_LANDMARKS_INOUT, ::fwData::Landmarks::s_MODIFIED_SIG, s_UPDATE_SLOT);
771  connections.push(s_LANDMARKS_INOUT, ::fwData::Landmarks::s_GROUP_RENAMED_SIG, s_RENAME_GROUP_SLOT);
772  connections.push(s_LANDMARKS_INOUT, ::fwData::Landmarks::s_POINT_SELECTED_SIG, s_SELECT_POINT_SLOT);
773  connections.push(s_LANDMARKS_INOUT, ::fwData::Landmarks::s_POINT_DESELECTED_SIG, s_DESELECT_POINT_SLOT);
774 
775  return connections;
776 }
777 
778 //------------------------------------------------------------------------------
779 
780 } //namespace visuVTKAdaptor
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_POINT_INSERTED_SIG
Type of signal when a group is added.
This class is a helper to define the connections of a service and its data.
Definition: IService.hpp:454
This class defines a list of 3D points inside groups.
VISUVTKADAPTOR_API void starting() override
Initialize the service activity.
Class allowing to block a Connection.
Definition: Connection.hpp:20
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_POINT_DESELECTED_SIG
Type of signal when a group is added.
The namespace visuVTKAdaptor contains the list of adaptors available for the generic scene...
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_GROUP_ADDED_SIG
Type of signal when a group is added.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_GROUP_REMOVED_SIG
Type of signal when a group is added.
VISUVTKADAPTOR_API void stopping() override
Uninitialize the service activity. The stop() method is always invoked before destroying a service...
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_POINT_SELECTED_SIG
Type of signal when a group is added.
3D Representation to be used with vtkHandleWidget (represents a cube or a sphere).
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_POINT_ADDED_SIG
Type of signal when a group is added.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_GROUP_RENAMED_SIG
Type of signal when a group is added.
#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
#define SLM_FATAL_IF(message, cond)
Definition: spyLog.hpp:287
void deselect()
Deselect the current point and emit the corresponding Landmarks signal.
VISUVTKADAPTOR_API void configuring() override
Configure the service before starting. Apply the configuration to service.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_MODIFIED_SIG
Key in m_signals map of signal m_sigModified.
vtkSmartPointer< vtkHandleWidget > LandmarkWidgetType
Widget used to display and interact with landmarks.
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_POINT_MODIFIED_SIG
Type of signal when a group is added.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_GROUP_MODIFIED_SIG
Type of signal when a group is added.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_POINT_REMOVED_SIG
Type of signal when a group is added.
Adaptor for landmarks in the field of an image.