MeshlessVolumeMapper.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2015-2016 Imperial College London
5  * Copyright 2015-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_MeshlessVolumeMapper_H
21 #define MIRTK_MeshlessVolumeMapper_H
22 
23 #include "mirtk/VolumeMapper.h"
24 
25 #include "mirtk/Array.h"
26 #include "mirtk/PointSet.h"
27 #include "mirtk/MeshlessMap.h"
28 
29 #include "vtkAbstractCellLocator.h"
30 
31 
32 namespace mirtk {
33 
34 
35 /**
36  * Base class of filters which compute a volumetric map of the interior of a
37  * piecewise linear complex (PLC) using the method of fundamental solutions (MFS)
38  *
39  * Iteratively computes a volumetric map of the interior of the input point
40  * set using the method of fundamental solutions (MFS). This implementation
41  * is based on the (bi-)harmonic volumetric mapping methods presented in
42  * (Li et al., 2010) and (Xu et al., 2013).
43  *
44  * Boundary (constraint) points and source (singularity) points are sampled
45  * using the geometry adaptive sampling algorithm as outlined in Section 4.1
46  * of (Li et al., 2010).
47  *
48  * The type of volumetric map (e.g., harmonic or biharmonic) depends on the
49  * particular linear system which is defined by the subclass implementation of
50  * the pure virtual base class functions GetCoefficientMatrix, AddRegularization,
51  * and GetRightHandSide. This system is solved using the LU decomposition as
52  * outlined in (Xu et al., 2013).
53  *
54  * - Li et al. (2010). Feature-aligned harmonic volumetric mapping using MFS.
55  * Computers and Graphics (Pergamon), 34(3), 242–251. doi:10.1016/j.cag.2010.03.004
56  * - Xu et al. (2013). Biharmonic volumetric mapping using fundamental
57  * solutions. IEEE Transactions on Visualization and Computer Graphics,
58  * 19(5), 787–798. doi:10.1109/TVCG.2012.173
59  */
61 {
62  mirtkAbstractMacro(MeshlessVolumeMapper);
63 
64  // ---------------------------------------------------------------------------
65  // Attributes
66 
67  /// Ratio of number of contraints points divided by number of input surface points
68  mirtkPublicAttributeMacro(double, BoundaryPointsRatio);
69 
70  /// Ratio of total number of source points divided by number of input surface points
71  mirtkPublicAttributeMacro(double, SourcePointsRatio);
72 
73  /// Maximum number of source points in each subset
74  mirtkPublicAttributeMacro(int, MaximumNumberOfSourcePoints);
75 
76  /// Number of iterations / approximation functions
77  mirtkPublicAttributeMacro(int, NumberOfIterations);
78 
79  /// Number of lattice points for implicit surface representation
80  mirtkPublicAttributeMacro(int, ImplicitSurfaceSize);
81 
82  /// Spacing of lattice points for implicit surface representation
83  mirtkPublicAttributeMacro(double, ImplicitSurfaceSpacing);
84 
85  /// Distance of the offset surface from the input surface
86  ///
87  /// If negative, the absolute value is multiplied by the length of the
88  /// diagonal of the input point set bounding box to get the absolute surface
89  /// distance offset value.
90  mirtkPublicAttributeMacro(double, DistanceOffset);
91 
92  /// Upper threshold of condition number of coefficient matrix
93  mirtkPublicAttributeMacro(double, MaximumConditionNumber);
94 
95  /// Decimated offset surface from which to sample the source points
96  mirtkReadOnlyAttributeMacro(vtkSmartPointer<vtkPolyData>, OffsetSurface);
97 
98  /// Locator used to find closest point on offset surface
99  mirtkAttributeMacro(vtkSmartPointer<vtkAbstractCellLocator>, OffsetPointLocator);
100 
101  /// Partition of source points
102  mirtkAttributeMacro(Array<Array<int> >, SourcePartition);
103 
104  /// Residual boundary map
105  mirtkAttributeMacro(vtkSmartPointer<vtkDataArray>, ResidualMap);
106 
107 protected:
108 
109  /// Get total number of boundary / constraints points
110  int NumberOfBoundaryPoints() const;
111 
112  /// Get total number of source / singularity points
113  int NumberOfSourcePoints() const;
114 
115  /// Get number of source points subsets
116  int NumberOfSourcePointSets() const;
117 
118  /// Get number of source points in k-th subset
119  int NumberOfSourcePoints(int) const;
120 
121  /// Get index of i-th point of k-th source points subset
122  int SourcePointIndex(int k, int i) const;
123 
124  /// Copy attributes of this class from another instance
125  void CopyAttributes(const MeshlessVolumeMapper &);
126 
127  // ---------------------------------------------------------------------------
128  // Construction/Destruction
129 
130  /// Default constructor
132 
133  /// Copy constructor
135 
136  /// Assignment operator
138 
139 public:
140 
141  /// Destructor
142  virtual ~MeshlessVolumeMapper();
143 
144  // ---------------------------------------------------------------------------
145  // Execution
146 
147 protected:
148 
149  /// Get closest point on offset surface
150  ///
151  /// \param[in] x Boundary point.
152  /// \param[in] p Closest source point on offset surface.
153  void GetClosestPointOnOffsetSurface(double x[3], double p[3]);
154 
155  /// Update boundary surface with corresponding boundary map as point data
156  virtual void UpdateBoundary(vtkPolyData *);
157 
158  /// Sample boundary points from input surface
159  virtual void PlaceBoundaryPoints();
160 
161  /// Compute and sample offset surface for placement of source points
162  virtual void PlaceSourcePoints();
163 
164  /// Add new source point
165  ///
166  /// \param[in] q Source point coordinates.
167  ///
168  /// \returns Whether source point was added or too close to existing point.
169  virtual bool AddSourcePoint(double q[3]);
170 
171  /// Evenly partition source points into smaller subsets
172  virtual void PartitionSourcePoints();
173 
174  /// Initialize residual boundary map
175  virtual void InitializeResidualMap();
176 
177  /// Update residual boundary map
178  ///
179  /// \returns Mean squared error of boundary map approximation.
180  virtual double UpdateResidualMap(double * = nullptr,
181  double * = nullptr,
182  double * = nullptr);
183 
184  /// Initialize filter after input and parameters are set
185  virtual void Initialize();
186 
187  /// Compute meshless map coefficients
188  virtual void Solve();
189 
190  // ---------------------------------------------------------------------------
191  // Linear system
192 
193 protected:
194 
195  /// Get coefficients matrix corresponding to the least squares fitting term(s)
196  /// of the quadratic energy function at constraints points
197  ///
198  /// \param[in] k Index of source points subset.
199  /// \param[out] coeff Coefficients matrix.
200  virtual void GetCoefficients(int k, Matrix &coeff) const = 0;
201 
202  /// Get right-hand side of linear system
203  ///
204  /// \param[in] k Index of source points subset.
205  /// \param[out] b Right-hand side of linear system.
206  virtual void GetConstraints(int k, Matrix &b) const = 0;
207 
208  /// Add solution of linear system to weights of volumetric map
209  ///
210  /// \param[in] k Index of source points subset.
211  /// \param[in] w Solution of linear system.
212  virtual void AddWeights(int k, const Matrix &w) = 0;
213 
214 };
215 
216 ////////////////////////////////////////////////////////////////////////////////
217 // Inline definitions
218 ////////////////////////////////////////////////////////////////////////////////
219 
220 // -----------------------------------------------------------------------------
222 {
223  return static_cast<int>(_Boundary->GetNumberOfPoints());
224 }
225 
226 // -----------------------------------------------------------------------------
228 {
229  if (_Output) {
230  MeshlessMap *map = dynamic_cast<MeshlessMap *>(_Output.get());
231  return map->NumberOfSourcePoints();
232  }
233  return static_cast<int>(_OffsetSurface->GetNumberOfPoints());
234 }
235 
236 // -----------------------------------------------------------------------------
238 {
239  return static_cast<int>(_SourcePartition.size());
240 }
241 
242 // -----------------------------------------------------------------------------
244 {
245  return static_cast<int>(_SourcePartition[k].size());
246 }
247 
248 // -----------------------------------------------------------------------------
249 inline int MeshlessVolumeMapper::SourcePointIndex(int k, int i) const
250 {
251  return _SourcePartition[k][i];
252 }
253 
254 
255 } // namespace mirtk
256 
257 #endif // MIRTK_MeshlessVolumeMapper_H
virtual void PlaceSourcePoints()
Compute and sample offset surface for placement of source points.
virtual double UpdateResidualMap(double *=nullptr, double *=nullptr, double *=nullptr)
virtual void PlaceBoundaryPoints()
Sample boundary points from input surface.
int NumberOfSourcePoints() const
Get number of source points.
Definition: MeshlessMap.h:153
virtual void GetCoefficients(int k, Matrix &coeff) const =0
virtual void AddWeights(int k, const Matrix &w)=0
virtual void UpdateBoundary(vtkPolyData *)
Update boundary surface with corresponding boundary map as point data.
MeshlessVolumeMapper & operator=(const MeshlessVolumeMapper &)
Assignment operator.
Definition: IOConfig.h:41
int NumberOfBoundaryPoints() const
Get total number of boundary / constraints points.
virtual void Initialize()
Initialize filter after input and parameters are set.
void GetClosestPointOnOffsetSurface(double x[3], double p[3])
void CopyAttributes(const MeshlessVolumeMapper &)
Copy attributes of this class from another instance.
int SourcePointIndex(int k, int i) const
Get index of i-th point of k-th source points subset.
int NumberOfSourcePoints() const
Get total number of source / singularity points.
virtual bool AddSourcePoint(double q[3])
MeshlessVolumeMapper()
Default constructor.
virtual void Solve()
Compute meshless map coefficients.
virtual ~MeshlessVolumeMapper()
Destructor.
virtual void InitializeResidualMap()
Initialize residual boundary map.
int NumberOfSourcePointSets() const
Get number of source points subsets.
virtual void GetConstraints(int k, Matrix &b) const =0
virtual void PartitionSourcePoints()
Evenly partition source points into smaller subsets.