PointSetForce.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2013-2016 Imperial College London
5  * Copyright 2013-2016 Andreas Schuh
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_PointSetForce_H
21 #define MIRTK_PointSetForce_H
22 
23 #include "mirtk/EnergyTerm.h"
24 
25 #include "mirtk/UnorderedMap.h"
26 #include "mirtk/Vector3D.h"
27 #include "mirtk/RegisteredPointSet.h"
28 
29 #include "vtkType.h"
30 #include "vtkSmartPointer.h"
31 #include "vtkDataArray.h"
32 #include "vtkPoints.h"
33 
34 
35 namespace mirtk {
36 
37 
38 /**
39  * Base class for point set force terms
40  *
41  * Subclasses implement in particular internal and external forces for
42  * deformable surface models. Internal force terms may further be used to
43  * regularize the deformation of a surface during image/point set registration.
44  */
45 class PointSetForce : public EnergyTerm
46 {
47  mirtkAbstractMacro(PointSetForce);
48 
49  // ---------------------------------------------------------------------------
50  // Types
51 public:
52 
53  /// Type of gradient w.r.t a single transformed data point
55 
56  /// Adjacency matrix with edge IDs
58 
59  /// Table of n-connected node neighbors
61 
62  // ---------------------------------------------------------------------------
63  // Attributes
64 protected:
65 
66  /// Transformed point set
68 
69  /// Number of gradient averaging iterations
70  mirtkPublicAttributeMacro(int, GradientAveraging);
71 
72  /// Whether to only average gradient vectors pointing in the same direction
73  /// as the unsmoothed gradient at the central node (i.e., positive dot product)
74  mirtkPublicAttributeMacro(bool, AverageSignedGradients);
75 
76  /// Whether to only average the magnitude of the gradient vectors
77  mirtkPublicAttributeMacro(bool, AverageGradientMagnitude);
78 
79  /// Whether this force is only acting on the point set surface
80  ///
81  /// This read-only attribute must be set by the subclass constructor.
82  /// It is in particular set by the SurfaceForce and SurfaceConstraint
83  /// constructors.
85 
86  /// Number of points
88 
89  /// Negative node forces/gradient of external force term
90  mirtkComponentMacro(GradientType, Gradient);
91 
92  /// Size of gradient vector
93  mirtkAttributeMacro(int, GradientSize);
94 
95  /// Number of summands in gradient computation
96  ///
97  /// Intended for use by EvaluateGradient implementations only.
98  /// Memory must be allocated by subclass, but will be freed by the base class.
99  mirtkAggregateMacro(int, Count);
100 
101  /// Size of count vector
102  mirtkAttributeMacro(int, CountSize);
103 
104  /// Whether Update has not been called since initialization
105  mirtkAttributeMacro(bool, InitialUpdate);
106 
107  // ---------------------------------------------------------------------------
108  // Point set accessors
109 
110 protected:
111 
112  /// Get point set on which this force is acting on
113  vtkPointSet *OriginalPointSet() const;
114 
115  /// Get point set on which this force is acting on
116  vtkPointSet *DeformedPointSet() const;
117 
118  /// Get point set on which this force is acting on
119  vtkPolyData *OriginalSurface() const;
120 
121  /// Get point set on which this force is acting on
122  vtkPolyData *DeformedSurface() const;
123 
124  /// Get points of point set on which this force is acting on
125  vtkPoints *Points() const;
126 
127  /// Get initial point status array
128  vtkDataArray *InitialStatus() const;
129 
130  /// Get point status array
131  vtkDataArray *Status() const;
132 
133  /// Get point normals array
134  vtkDataArray *Normals() const;
135 
136  /// Get point data
137  vtkPointData *PointData() const;
138 
139  /// Get edge table of point set mesh
140  const EdgeTable *Edges() const;
141 
142  /// Get edge table of point set mesh
143  SharedPtr<const EdgeTable> SharedEdgeTable() const;
144 
145  /// Get edge-connectivity table of point set node neighbors
146  const NodeNeighbors *Neighbors(int = -1) const;
147 
148  // ---------------------------------------------------------------------------
149  // Point set attributes
150 private:
151 
152  typedef UnorderedMap<string, string> NameMap;
153  typedef NameMap::iterator NameMapIterator;
154  typedef NameMap::const_iterator NameMapConstIterator;
155 
156  /// Maps internal point data name to actual unique point data array name
157  NameMap _PointDataName;
158 
159 protected:
160 
161  /// Get point data array of deformed point set
162  ///
163  /// \param[in] name Name of array as used when the array was added before.
164  /// This name may differ from the actual unique array name.
165  /// \param[in] optional Whether the array may not exist. If \c false, this
166  /// function raises an error if the array does not exist.
167  ///
168  /// \return Point data array or nullptr if not found (only if \p optional = \c true).
169  vtkDataArray *PointData(const char *name, bool optional = false) const;
170 
171  /// Add given array to point data attributes of deformed point set
172  ///
173  /// This function should be used by subclasses to add point data arrays to
174  /// the point set (or its surface, respectively, if \c _SurfaceForce is \c true).
175  /// The added point data is interpolated at new node positions whenever the
176  /// deformed point set is being remeshed during the optimization.
177  ///
178  /// \param[in] name Name of array. The actual name of the point data array
179  /// will be made unique by this function which stores an
180  /// internal map from the given name to the unique array name.
181  /// \param[in] data Point data array.
182  /// \param[in] global Whether point data array is shared among point forces.
183  /// If \c true, the array \p name is used unmodified such
184  /// that other force terms can reuse the array.
185  void AddPointData(const char *name, vtkSmartPointer<vtkDataArray> &data, bool global = false);
186 
187  /// Add new point data array of given type with specified number of components
188  ///
189  /// This function should be used by subclasses to add point data arrays to
190  /// the point set (or its surface, respectively, if \c _SurfaceForce is \c true).
191  /// The added point data is interpolated at new node positions whenever the
192  /// deformed point set is being remeshed during the optimization.
193  ///
194  /// If an array with the given \p name already exists, it is reused to avoid
195  /// unnecessary allocations unless the data type or number of components mismatch.
196  /// If _NumberOfPoints is set before by PointForce::Initialize, the
197  /// corresponding number of array tuples are allocated by this function.
198  /// Otherwise, the array is only instantiated, but not allocated.
199  ///
200  /// \param[in] name Name of array. The actual name of the point data array
201  /// will be made unique by this function which stores an
202  /// internal map from the given name to the unique array name.
203  /// \param[in] c Number of components.
204  /// \param[in] type Type of data array (e.g., VTK_FLOAT, the default).
205  /// \param[in] global Whether point data array is shared among point forces.
206  /// If \c true, the array \p name is used unmodified such
207  /// that other force terms can reuse the array.
208  ///
209  /// \return Pointer to (newly instantiated) array.
210  vtkDataArray *AddPointData(const char *name, int c = 1, int type = VTK_FLOAT, bool global = false);
211 
212  /// Remove named array from point data attributes of deformed point set
213  ///
214  /// \param[in] name Name of array as used when the array was added before.
215  /// This name may differ from the actual unique array name.
216  void RemovePointData(const char *name);
217 
218  // ---------------------------------------------------------------------------
219  // Construction/Destruction
220 protected:
221 
222  /// Constructor
223  PointSetForce(const char * = "", double = 1.0);
224 
225  /// Copy constructor
226  PointSetForce(const PointSetForce &);
227 
228  /// Assignment operator
230 
231  /// Allocate memory for (non-parametric) gradient
232  void AllocateGradient(int);
233 
234  /// Allocate _Count memory
235  void AllocateCount(int);
236 
237  /// Copy attributes of this class from another instance
238  void CopyAttributes(const PointSetForce &);
239 
240 public:
241 
242  /// Destructor
243  virtual ~PointSetForce();
244 
245  // ---------------------------------------------------------------------------
246  // Initialization
247 protected:
248 
249  /// Common (re-)initialization steps of this class only (non-virtual function!)
250  void Init();
251 
252  /// Get initial points, possibly pre-transformed by global transformation
253  vtkSmartPointer<vtkPoints> GetInitialPoints() const;
254 
255 public:
256 
257  /// Initialize force term once input and parameters have been set
258  virtual void Initialize();
259 
260  /// Reinitialize force term after change of input topology
261  ///
262  /// This function is called in particular when an input surface has been
263  /// reparameterized, e.g., by a local remeshing filter.
264  virtual void Reinitialize();
265 
266  // ---------------------------------------------------------------------------
267  // Evaluation
268 
269  /// Update moving input points and internal state of force term
270  virtual void Update(bool = true);
271 
272 protected:
273 
274  /// Evaluate gradient of force term
275  ///
276  /// \param[in,out] gradient Gradient to which the computed gradient of the
277  /// force term is added after multiplying by \p weight.
278  /// \param[in] step Step length for finite differences (unused).
279  /// \param[in] weight Weight of force term.
280  virtual void EvaluateGradient(double *gradient, double step, double weight);
281 
282  // ---------------------------------------------------------------------------
283  // Debugging
284 public:
285 
286  /// Write input of force term
287  virtual void WriteDataSets(const char *, const char *, bool = true) const;
288 
289  /// Write gradient of force term
290  virtual void WriteGradient(const char *, const char *) const;
291 
292 };
293 
294 ////////////////////////////////////////////////////////////////////////////////
295 // Inline definitions
296 ////////////////////////////////////////////////////////////////////////////////
297 
298 // -----------------------------------------------------------------------------
299 inline vtkPointSet *PointSetForce::OriginalPointSet() const
300 {
301  if (_SurfaceForce) return _PointSet->InputSurface();
302  else return _PointSet->InputPointSet();
303 }
304 
305 // -----------------------------------------------------------------------------
306 inline vtkPointSet *PointSetForce::DeformedPointSet() const
307 {
308  if (_SurfaceForce) return _PointSet->Surface();
309  else return _PointSet->PointSet();
310 }
311 
312 // -----------------------------------------------------------------------------
313 inline vtkPolyData *PointSetForce::OriginalSurface() const
314 {
315  return _PointSet->InputSurface();
316 }
317 
318 // -----------------------------------------------------------------------------
319 inline vtkPolyData *PointSetForce::DeformedSurface() const
320 {
321  return _PointSet->Surface();
322 }
323 
324 // -----------------------------------------------------------------------------
325 inline vtkPoints *PointSetForce::Points() const
326 {
327  return _SurfaceForce ? _PointSet->SurfacePoints() : _PointSet->Points();
328 }
329 
330 // -----------------------------------------------------------------------------
331 inline vtkDataArray *PointSetForce::InitialStatus() const
332 {
333  return _SurfaceForce ? _PointSet->InitialSurfaceStatus() : _PointSet->InitialStatus();
334 }
335 
336 // -----------------------------------------------------------------------------
337 inline vtkDataArray *PointSetForce::Status() const
338 {
339  return _SurfaceForce ? _PointSet->SurfaceStatus() : _PointSet->Status();
340 }
341 
342 // -----------------------------------------------------------------------------
343 inline vtkDataArray *PointSetForce::Normals() const
344 {
345  if (!_SurfaceForce) {
346  Throw(ERR_LogicError, __FUNCTION__, "Only surface meshes have point normals!");
347  }
348  return _PointSet->SurfaceNormals();
349 }
350 
351 // -----------------------------------------------------------------------------
353 {
354  return _SurfaceForce ? _PointSet->SurfaceEdges() : _PointSet->Edges();
355 }
356 
357 // -----------------------------------------------------------------------------
358 inline SharedPtr<const PointSetForce::EdgeTable> PointSetForce::SharedEdgeTable() const
359 {
360  return _SurfaceForce ? _PointSet->SharedSurfaceEdgeTable() : _PointSet->SharedEdgeTable();
361 }
362 
363 // -----------------------------------------------------------------------------
365 {
366  return _SurfaceForce ? _PointSet->SurfaceNeighbors(n) : _PointSet->Neighbors(n);
367 }
368 
369 // -----------------------------------------------------------------------------
370 inline vtkPointData *PointSetForce::PointData() const
371 {
372  return DeformedPointSet()->GetPointData();
373 }
374 
375 
376 } // namespace mirtk
377 
378 #endif // MIRTK_PointSetForce_H
vtkDataArray * InitialStatus() const
Get initial point status array.
mirtkPublicAttributeMacro(int, GradientAveraging)
Number of gradient averaging iterations.
PointSetForce & operator=(const PointSetForce &)
Assignment operator.
virtual void Initialize()
Initialize force term once input and parameters have been set.
vtkPointData * PointData() const
Get point data.
RegisteredPointSet::NodeNeighbors NodeNeighbors
Table of n-connected node neighbors.
Definition: PointSetForce.h:60
virtual void Update(bool=true)
Update moving input points and internal state of force term.
vtkPointSet * OriginalPointSet() const
Get point set on which this force is acting on.
vtkSmartPointer< vtkPoints > GetInitialPoints() const
Get initial points, possibly pre-transformed by global transformation.
mirtkPublicAggregateMacro(RegisteredPointSet, PointSet)
Transformed point set.
mirtkReadOnlyAttributeMacro(bool, SurfaceForce)
SharedPtr< const EdgeTable > SharedEdgeTable() const
Get edge table of point set mesh.
vtkPointSet * DeformedPointSet() const
Get point set on which this force is acting on.
RegisteredPointSet::EdgeTable EdgeTable
Adjacency matrix with edge IDs.
Definition: PointSetForce.h:57
void CopyAttributes(const PointSetForce &)
Copy attributes of this class from another instance.
Vector3D< double > GradientType
Type of gradient w.r.t a single transformed data point.
Definition: PointSetForce.h:54
Definition: IOConfig.h:41
virtual ~PointSetForce()
Destructor.
virtual void Reinitialize()
const NodeNeighbors * Neighbors(int=-1) const
Get edge-connectivity table of point set node neighbors.
mirtkAttributeMacro(int, GradientSize)
Size of gradient vector.
mirtkAggregateMacro(int, Count)
void AllocateGradient(int)
Allocate memory for (non-parametric) gradient.
const EdgeTable * Edges() const
Get edge table of point set mesh.
void AddPointData(const char *name, vtkSmartPointer< vtkDataArray > &data, bool global=false)
virtual void WriteGradient(const char *, const char *) const
Write gradient of force term.
vtkPolyData * DeformedSurface() const
Get point set on which this force is acting on.
vtkPolyData * OriginalSurface() const
Get point set on which this force is acting on.
void RemovePointData(const char *name)
virtual void WriteDataSets(const char *, const char *, bool=true) const
Write input of force term.
vtkDataArray * Status() const
Get point status array.
vtkPoints * Points() const
Get points of point set on which this force is acting on.
void Throw(ErrorType err, const char *func, Args... args) const
Definition: Object.h:166
void Init()
Common (re-)initialization steps of this class only (non-virtual function!)
void AllocateCount(int)
Allocate _Count memory.
virtual void EvaluateGradient(double *gradient, double step, double weight)
PointSetForce(const char *="", double=1.0)
Constructor.
mirtkComponentMacro(GradientType, Gradient)
Negative node forces/gradient of external force term.
void Gradient(double *gradient, double step)
vtkDataArray * Normals() const
Get point normals array.
int NumberOfPoints(vtkDataSet *)
Number of points.