LeastSquaresConformalSurfaceMapper.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2016 Imperial College London
5  * Copyright 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_LeastSquaresConformalSurfaceMapper_H
21 #define MIRTK_LeastSquaresConformalSurfaceMapper_H
22 
23 #include "mirtk/FreeBoundarySurfaceMapper.h"
24 
25 #include "mirtk/Array.h"
26 
27 #include "vtkSmartPointer.h"
28 #include "vtkDataArray.h"
29 
30 
31 namespace mirtk {
32 
33 
34 /**
35  * Least squares conformal parameterization
36  *
37  * This filter implements the least squares conformal map (LSCM) proposed by
38  * Levy (2002) and the identical discrete natural conformal parameterization
39  * (DNCP) proposed by Meyer et al. (2002). It follows the formulation of in
40  * Mullen et al. (2002), where the LSCM is defined as the minimizer of the
41  * conformal energy \f$E_C(\vec{u}) = E_LSCM\vec{u} = E_D(\vec{u}) - A(\vec{u})\f$,
42  * where \f$E_D(\vec{u})\f$ is the discrete Dirichlet energy and
43  * \f$A(\vec{u})\f$ is the total area of the parameteric domain.
44  * The geometric cotangent weights are used to discretize the Laplace operator
45  * needed for the computation of the derivative of the Dirichlet energy.
46  *
47  * The LSCM requires at least two fixed points. When no point constraints are
48  * given, a boundary point is selected automatically. A second fixed boundary
49  * point is chosen to be as farthest away from the first fixed point as possible
50  * based on geodesic distances on the input surface mesh.
51  *
52  * - Levy et al. (2002). Least squares conformal maps for automatic texture atlas
53  * generation. ACM Trans. Graphics, 21(3), 362–371.
54  * - Desbrun, Meyer, and Alliez (2002). Intrinsic parameterizations of surface meshes.
55  * Computer Graphics Forum, 21(3), 209–218.
56  * - Mullen et al. (2008). Spectral conformal parameterization.
57  * Eurographics Symposium on Geometry Processing, 27(5), 1487–1494.
58  *
59  * \todo Implement area weighting extension as described in Mullen et al. (2008)
60  * to account for irregular surface sampling.
61  */
63 {
64  mirtkObjectMacro(LeastSquaresConformalSurfaceMapper);
65 
66  // ---------------------------------------------------------------------------
67  // Attributes
68 
69 private:
70 
71  /// Maximum number of iterations
72  ///
73  /// When the number of iterations is set to 1 a sparse direct solver is used.
74  mirtkPublicAttributeMacro(int, NumberOfIterations);
75 
76  /// Tolerance for sparse linear solver
77  mirtkPublicAttributeMacro(double, Tolerance);
78 
79  /// Index of point in set of points with free (i >= 0) or fixed (i < 0) values
80  mirtkAttributeMacro(Array<int>, PointIndex);
81 
82  /// IDs of surface points with free map values
83  mirtkAttributeMacro(Array<int>, FreePoints);
84 
85  /// IDs of surface points with fixed map values
86  mirtkAttributeMacro(Array<int>, FixedPoints);
87 
88  /// Map values at fixed points
89  mirtkAttributeMacro(Matrix, FixedValues);
90 
91  /// Computed map values at surface points
92  mirtkAttributeMacro(vtkSmartPointer<vtkDataArray>, Values);
93 
94  /// Copy attributes of this class from another instance
95  void CopyAttributes(const LeastSquaresConformalSurfaceMapper &);
96 
97  // ---------------------------------------------------------------------------
98  // Construction/Destruction
99 
100 public:
101 
102  /// Default constructor
104 
105  /// Copy constructor
107 
108  /// Assignment operator
110 
111  /// Destructor
113 
114  // ---------------------------------------------------------------------------
115  // Constraints
116 
117  /// Add hard point constraint
118  ///
119  /// \param[in] i Surface point index.
120  /// \param[in] u First constraint value component.
121  /// \param[in] v Second constraint value component.
122  void AddFixedPoint(int i, double u, double v);
123 
124  // ---------------------------------------------------------------------------
125  // Execution
126 
127 protected:
128 
129  /// Weight of undirected edge (i, j)
130  ///
131  /// \param[in] i First end point.
132  /// \param[in] j Second end point.
133  ///
134  /// \returns Weight of undirected edge (i, j).
135  virtual double Weight(int i, int j) const;
136 
137  /// Initialize filter after input and parameters are set
138  virtual void Initialize();
139 
140  /// Compute surface map
141  virtual void ComputeMap();
142 
143  /// Finalize filter execution
144  virtual void Finalize();
145 
146  // ---------------------------------------------------------------------------
147  // Auxiliaries
148 
149 public:
150 
151  /// Number of surface points with free map value
152  int NumberOfFreePoints() const;
153 
154  /// Number of surface points with fixed map value
155  int NumberOfFixedPoints() const;
156 
157  /// Whether the map value of the specified surface point is free
158  bool IsFreePoint(int i) const;
159 
160  /// Whether the map value of the specified surface point is fixed
161  bool IsFixedPoint(int i) const;
162 
163  /// Get index of i-th point with free map value or -1 if map value of point is fixed
164  ///
165  /// \param[in] i Surface point index.
166  ///
167  /// \return Index of point in set of points with free map value.
168  int FreePointIndex(int i) const;
169 
170  /// Get surface point ID of i-th point with free map value
171  ///
172  /// \param[in] i Index of point in set of points with free map value.
173  ///
174  /// \return Surface point index.
175  int FreePointId(int i) const;
176 
177  /// Get index of i-th point with fixed map value or -1 if map value of point is free
178  ///
179  /// \param[in] i Surface point index.
180  ///
181  /// \return Index of point in set of points with fixed map value.
182  int FixedPointIndex(int i) const;
183 
184  /// Get surface point ID of i-th point with fixed map value
185  ///
186  /// \param[in] i Index of point in set of points with fixed map value.
187  ///
188  /// \return Surface point index.
189  int FixedPointId(int i) const;
190 
191  /// Get component of map value at surface vertex
192  ///
193  /// \param[in] i Surface point index.
194  /// \param[in] j Map value component index.
195  ///
196  /// \return The j-th component of the map value evaluated at the i-th surface point.
197  double GetValue(int i, int j = 0) const;
198 
199  /// Get component of map value at i-th free point
200  ///
201  /// \param[in] i Index of point in set of points with free map value.
202  /// \param[in] j Map value component index.
203  ///
204  /// \return The j-th component of the map value evaluated at the i-th free point.
205  double GetFreeValue(int i, int j = 0) const;
206 
207  /// Get component of map value at i-th fixed point
208  ///
209  /// \param[in] i Index of point in set of points with fixed map value.
210  /// \param[in] j Map value component index.
211  ///
212  /// \return The j-th component of the map value evaluated at the i-th fixed point.
213  double GetFixedValue(int i, int j = 0) const;
214 
215 protected:
216 
217  /// Set scalar map value at surface vertex
218  ///
219  /// \param[in] i Surface point index.
220  /// \param[in] v Map value.
221  void SetValue(int i, double v);
222 
223  /// Set component of map value at surface vertex
224  ///
225  /// \param[in] i Surface point index.
226  /// \param[in] j Map component index.
227  /// \param[in] v Map component value.
228  void SetValue(int i, int j, double v);
229 
230  /// Set scalar map value at i-th free point
231  ///
232  /// \param[in] i Index of point in set of points with free map value.
233  /// \param[in] v Map value.
234  void SetFreeValue(int i, double v);
235 
236  /// Set component of map value at i-th free point
237  ///
238  /// \param[in] i Index of point in set of points with free map value.
239  /// \param[in] j Map component index.
240  /// \param[in] v Map component value.
241  void SetFreeValue(int i, int j, double v);
242 
243 };
244 
245 ////////////////////////////////////////////////////////////////////////////////
246 // Inline definitions
247 ////////////////////////////////////////////////////////////////////////////////
248 
249 // =============================================================================
250 // Auxiliaries
251 // =============================================================================
252 
253 // -----------------------------------------------------------------------------
255 {
256  return static_cast<int>(_FreePoints.size());
257 }
258 
259 // -----------------------------------------------------------------------------
261 {
262  return static_cast<int>(_FixedPoints.size());
263 }
264 
265 // -----------------------------------------------------------------------------
267 {
268  const int i = _PointIndex[ptId];
269  return (i < 0 ? -1 : i);
270 }
271 
272 // -----------------------------------------------------------------------------
274 {
275  return _FreePoints[i];
276 }
277 
278 // -----------------------------------------------------------------------------
280 {
281  return FreePointIndex(ptId) != -1;
282 }
283 
284 // -----------------------------------------------------------------------------
286 {
287  const int i = _PointIndex[ptId];
288  return (i < 0 ? (-i) - 1 : -1);
289 }
290 
291 // -----------------------------------------------------------------------------
293 {
294  return _FixedPoints[i];
295 }
296 
297 // -----------------------------------------------------------------------------
299 {
300  return FixedPointIndex(ptId) != -1;
301 }
302 
303 // -----------------------------------------------------------------------------
304 inline double LeastSquaresConformalSurfaceMapper::GetValue(int i, int j) const
305 {
306  return _Values->GetComponent(static_cast<vtkIdType>(i), j);
307 }
308 
309 // -----------------------------------------------------------------------------
310 inline double LeastSquaresConformalSurfaceMapper::GetFreeValue(int i, int j) const
311 {
312  return GetValue(FreePointId(i), j);
313 }
314 
315 // -----------------------------------------------------------------------------
316 inline double LeastSquaresConformalSurfaceMapper::GetFixedValue(int i, int j) const
317 {
318  return GetValue(FixedPointId(i), j);
319 }
320 
321 // -----------------------------------------------------------------------------
323 {
324  _Values->SetComponent(static_cast<vtkIdType>(i), 0, v);
325 }
326 
327 // -----------------------------------------------------------------------------
328 inline void LeastSquaresConformalSurfaceMapper::SetValue(int i, int j, double v)
329 {
330  _Values->SetComponent(static_cast<vtkIdType>(i), j, v);
331 }
332 
333 // -----------------------------------------------------------------------------
335 {
336  SetValue(FreePointId(i), v);
337 }
338 
339 // -----------------------------------------------------------------------------
340 inline void LeastSquaresConformalSurfaceMapper::SetFreeValue(int i, int j, double v)
341 {
342  SetValue(FreePointId(i), j, v);
343 }
344 
345 
346 } // namespace mirtk
347 
348 #endif // MIRTK_LeastSquaresConformalSurfaceMapper_H
bool IsFixedPoint(int i) const
Whether the map value of the specified surface point is fixed.
bool IsFreePoint(int i) const
Whether the map value of the specified surface point is free.
virtual double Weight(int i, int j) const
LeastSquaresConformalSurfaceMapper()
Default constructor.
int NumberOfFixedPoints() const
Number of surface points with fixed map value.
Definition: IOConfig.h:41
virtual void ComputeMap()
Compute surface map.
virtual ~LeastSquaresConformalSurfaceMapper()
Destructor.
virtual void Finalize()
Finalize filter execution.
virtual void Initialize()
Initialize filter after input and parameters are set.
int NumberOfFreePoints() const
Number of surface points with free map value.
void AddFixedPoint(int i, double u, double v)
LeastSquaresConformalSurfaceMapper & operator=(const LeastSquaresConformalSurfaceMapper &)
Assignment operator.