fw4spl
SSimpleMeshDeformation.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 "vtkSimpleMesh/SSimpleMeshDeformation.hpp"
8 
9 #include <fwCom/Signal.hxx>
10 #include <fwCom/Slots.hxx>
11 
12 #include <fwData/Mesh.hpp>
13 #include <fwData/mt/ObjectReadLock.hpp>
14 #include <fwData/mt/ObjectReadToWriteLock.hpp>
15 
16 #include <fwDataTools/Mesh.hpp>
17 
18 #include <fwServices/macros.hpp>
19 #include <fwServices/registry/ActiveWorkers.hpp>
20 
21 #include <functional>
22 
24 
25 namespace vtkSimpleMesh
26 {
27 
28 //-----------------------------------------------------------------------------
29 
30 const ::fwCom::Slots::SlotKeyType SSimpleMeshDeformation::s_START_DEFORMATION_SLOT = "startDeformation";
31 const ::fwCom::Slots::SlotKeyType SSimpleMeshDeformation::s_STOP_DEFORMATION_SLOT = "stopDeformation";
32 
33 static const std::string s_MESH_KEY = "mesh";
34 
35 //-----------------------------------------------------------------------------
36 
38 {
39  newSlot(s_START_DEFORMATION_SLOT, &SSimpleMeshDeformation::startDeformation, this);
40  newSlot(s_STOP_DEFORMATION_SLOT, &SSimpleMeshDeformation::stopDeformation, this);
41 }
42 
43 //-----------------------------------------------------------------------------
44 
46 {
47 }
48 
49 //-----------------------------------------------------------------------------
50 
52 {
53  SLM_ASSERT("No valid worker for mesh deformation", m_associatedWorker);
54  m_timer = m_associatedWorker->createTimer();
55 
56  ::fwThread::Timer::TimeDurationType duration = std::chrono::milliseconds(200);
57 
58  m_timer->setFunction( std::bind( &SSimpleMeshDeformation::updating, this) );
59  m_timer->setDuration(duration);
60 }
61 
62 //-----------------------------------------------------------------------------
63 
65 {
66 }
67 
68 //-----------------------------------------------------------------------------
69 
71 {
72  this->stopDeformation();
73 }
74 
75 //-----------------------------------------------------------------------------
76 
78 {
80 
81  auto mesh = this->getInOut< ::fwData::Mesh >(s_MESH_KEY);
82 
84  if ( mesh->getNumberOfPoints() > 0 )
85  {
86  m_hiRestimer.reset();
87  m_hiRestimer.start();
88  this->computeDeformation(m_mesh, m_transformMesh);
89  m_hiRestimer.stop();
90  OSLM_INFO("Deformation time (milli sec) = " << m_hiRestimer.getElapsedTimeInMilliSec());
91 
92  lock.upgrade();
93  m_hiRestimer.reset();
94  m_hiRestimer.start();
95  copyMesh(m_transformMesh, mesh);
96  m_hiRestimer.stop();
97  OSLM_INFO("Copy time (milli sec) = " << m_hiRestimer.getElapsedTimeInMilliSec());
98  lock.downgrade();
99 
100  ::fwData::Mesh::VertexModifiedSignalType::sptr sig;
102  sig->asyncEmit();
103  }
104 }
105 
106 //-----------------------------------------------------------------------------
107 
109 {
110  bool meshIsLoaded;
111  {
112  auto mesh = this->getInOut< ::fwData::Mesh >(s_MESH_KEY);
113  ::fwData::mt::ObjectReadLock lock(mesh);
114  meshIsLoaded = mesh->getNumberOfPoints() > 0;
115  }
116 
117  if ( meshIsLoaded )
118  {
119  this->initMeshBackup();
120 
121  if (!m_timer->isRunning())
122  {
123  m_timer->start();
124  }
125  }
126 }
127 
128 //-----------------------------------------------------------------------------
129 
131 {
132  if (m_timer->isRunning())
133  {
134  m_timer->stop();
135  m_transformMesh.reset();
136  m_mesh.reset();
137  }
138 }
139 
140 //-----------------------------------------------------------------------------
141 
142 void SSimpleMeshDeformation::copyMesh( const ::fwData::Mesh::sptr& src, const ::fwData::Mesh::sptr& dest ) const
143 {
144  dest->setPointsArray(::fwData::Object::copy( src->getPointsArray() ));
145  dest->setPointNormalsArray(::fwData::Object::copy( src->getPointNormalsArray() ));
146  dest->setPointColorsArray(::fwData::Object::copy( src->getPointColorsArray() ));
147 }
148 
149 //-----------------------------------------------------------------------------
150 
151 void SSimpleMeshDeformation::computeDeformation (
152  const ::fwData::Mesh::sptr& refMesh,
153  const ::fwData::Mesh::sptr& transformMesh,
154  float deformationPercent )
155 {
156  SLM_ASSERT("Deformation range must be equal to [0,1]", 0 <= deformationPercent && deformationPercent <= 1 );
157 
158  const float maxDeformation = 15/100.0f;
159  const float center = 2/3.0f;
160 
161  ::fwDataTools::helper::Mesh meshHelper(refMesh);
162  ::fwDataTools::helper::Mesh transformMeshHelper(transformMesh);
163 
164  ::fwData::Mesh::PointsMultiArrayType points = meshHelper.getPoints();
165  ::fwData::Mesh::PointsMultiArrayType pointsTransform = transformMeshHelper.getPoints();
166  ::fwData::Mesh::PointColorsMultiArrayType colorTransform = transformMeshHelper.getPointColors();
167 
168  size_t nbPts = refMesh->getNumberOfPoints();
169 
170  // Compute limits
171  float ymin = points[0][1];
172  float ymax = points[0][1];
173  for(size_t i = 0; i != nbPts; ++i)
174  {
175  const float val = points[i][1];
176  if ( val < ymin )
177  {
178  ymin = val;
179  }
180  else if ( val > ymax )
181  {
182  ymax = val;
183  }
184  }
185 
186  // Compute deformation
187  float sizeRef = ymax-ymin;
188  float yref = sizeRef * center + ymin;
189  float strafe = maxDeformation * sizeRef;
190  float currentStrafe = deformationPercent * strafe;
191 
192  for(size_t i = 0; i < nbPts; ++i )
193  {
194  float y = points[i][1];
195  if( y < yref )
196  {
197  float val = ( yref - y ) / ( yref - ymin ) * currentStrafe;
198  pointsTransform[i][1] = y - val;
199  colorTransform[i][0] = 255;
200  colorTransform[i][1] = static_cast<fwData::Mesh::ColorValueType>(255 - 255 * ( val / strafe ));
201  colorTransform[i][2] = static_cast<fwData::Mesh::ColorValueType>(255 - 255 * ( val / strafe ));
202  }
203  else
204  {
205  colorTransform[i][0] = 255;
206  colorTransform[i][1] = 255;
207  colorTransform[i][2] = 255;
208  }
209  }
210 
212 }
213 
214 //-----------------------------------------------------------------------------
215 
216 void SSimpleMeshDeformation::computeDeformation(
217  const ::fwData::Mesh::sptr& refMesh,
218  const ::fwData::Mesh::sptr& transformMesh )
219 {
220  const int step = 5;
221 
222  m_currentDeformation += m_currentIncrement;
223  if ( m_currentDeformation == 100 )
224  {
225  m_currentIncrement = -step;
226  }
227  else if ( m_currentDeformation == 0 )
228  {
229  m_currentIncrement = step;
230  }
231  this->computeDeformation( refMesh, transformMesh, m_currentDeformation/100.0f );
232 }
233 
234 //-----------------------------------------------------------------------------
235 
236 void SSimpleMeshDeformation::initMeshBackup()
237 {
238  SLM_WARN_IF("Data already init", m_transformMesh || m_mesh);
239  if (!m_mesh && !m_transformMesh)
240  {
241  m_currentIncrement = 0;
242  m_currentDeformation = 0;
243 
244  auto mesh = this->getInOut< ::fwData::Mesh >(s_MESH_KEY);
246 
247  lock.upgrade();
249  mesh->allocatePointColors( ::fwData::Mesh::RGB );
250  lock.downgrade();
251 
252  m_mesh = ::fwData::Object::copy( mesh );
253 
254  m_transformMesh = ::fwData::Object::copy( mesh );
255  }
256 }
257 
258 //-----------------------------------------------------------------------------
259 
260 }
VTKSIMPLEMESH_API void stopDeformation()
Stops mesh deformation.
virtual VTKSIMPLEMESH_API void updating() override
Updating method. Deforms the mesh.
virtual VTKSIMPLEMESH_API ~SSimpleMeshDeformation() noexcept
Destructor.
#define SLM_TRACE_FUNC()
Trace contextual function signature.
Definition: spyLog.hpp:329
A helper to lock object on upgradable mode.
FWCORE_API void stop()
Stop the timer. stop() will not reset the timer.
Definition: HiResTimer.cpp:32
A helper to lock object on read mode.
#define OSLM_INFO(message)
Definition: spyLog.hpp:252
FWCORE_API::fwCore::HiResClock::HiResClockType getElapsedTimeInMilliSec()
Definition: HiResTimer.cpp:66
static FWDATATOOLS_API void generatePointNormals(::fwData::Mesh::sptr mesh)
Generate point normals for the mesh.
Service used to demonstrate how to deform a mesh.
FWDATATOOLS_API::fwData::Mesh::PointsMultiArrayType getPoints() const
Returns the internal corresponding array as a boost::multi_array_ref.
FWDATATOOLS_API::fwData::Mesh::PointColorsMultiArrayType getPointColors() const
Returns the internal corresponding array as a boost::multi_array_ref.
This interface defines control service API. Does nothing particularly, can be considered as a default...
Definition: IController.hpp:23
#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
static FWDATA_API::fwData::Object::sptr copy(const ::fwData::Object::csptr &source)
return a copy of the source. if source is a null pointer, return a null pointer.
The namespace vtkSimpleMesh contains a service which renders one mesh (fwData::Mesh).
VTKSIMPLEMESH_API SSimpleMeshDeformation() noexcept
Constructor.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_VERTEX_MODIFIED_SIG
Key in m_signals map of signal m_sigVertexModified.
virtual VTKSIMPLEMESH_API void starting() override
Starting method. Initialize timer.
FWCORE_API void reset(::fwCore::HiResClock::HiResClockType initial_value=0.)
Reset the timer and leave it in the same state it was (started or stopped).
Definition: HiResTimer.cpp:39
FWCORE_API void start()
Start the timer.
Definition: HiResTimer.cpp:24
virtual VTKSIMPLEMESH_API void configuring() override
Configuring method.
VTKSIMPLEMESH_API void startDeformation()
Starts mesh deformation.
std::shared_ptr< ::fwThread::Worker > m_associatedWorker
Associated worker.
Definition: IService.hpp:699
virtual VTKSIMPLEMESH_API void stopping() override
Stopping method.
Data holding a geometric structure composed of points, lines, triangles, quads or polygons...
#define SLM_WARN_IF(message, cond)
Definition: spyLog.hpp:265
Helper to manage Mesh. Lock the mesh buffer before to modify it.