1 /*
2 * Medical Image Registration ToolKit (MIRTK)
3 *
4 * Copyright 2008-2015 Imperial College London
5 * Copyright 2008-2013 Daniel Rueckert, Julia Schnabel
6 * Copyright 2013-2015 Andreas Schuh
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21 #ifndef MIRTK_MultiLevelTransformation_H
22 #define MIRTK_MultiLevelTransformation_H
23
24 #include "mirtk/Transformation.h"
25 #include "mirtk/RigidTransformation.h"
26 #include "mirtk/AffineTransformation.h"
27 #include "mirtk/FreeFormTransformation.h"
28
29 #include <cstdlib>
30 #include <iostream>
31
32
33 namespace mirtk {
34
35
36 const int MAX_TRANS = 200;
37
38
39 /**
40 * Base class for multi-level transformations.
41 *
42 * This is the abstract base class which defines a common interface for all
43 * multi-level transformations. Each derived class has to implement at least
44 * the abstract methods and some of the virtual ones. Most other methods call
45 * these virtual methods and should not be required to be overridden in
46 * subclasses.
47 */
48 class MultiLevelTransformation : public Transformation
49 {
50 mirtkAbstractTransformationMacro(MultiLevelTransformation);
51
52 public:
53
54 /// Type of local transformation status
55 typedef Status FFDStatus;
56
57 protected:
58
59 // ---------------------------------------------------------------------------
60 // Data members
61
62 /// Global transformation
63 AffineTransformation _GlobalTransformation;
64
65 /// Local transformations
66 FreeFormTransformation *_LocalTransformation[MAX_TRANS];
67
68 /// Whether this class is responsible for destructing the local transformation
69 bool _LocalTransformationOwner[MAX_TRANS];
70
71 /// Status of local transformations
72 FFDStatus _LocalTransformationStatus[MAX_TRANS];
73
74 /// Number of local transformations
75 int _NumberOfLevels;
76
77 // ---------------------------------------------------------------------------
78 // Construction/Destruction
79
80 /// Default constructor
81 MultiLevelTransformation();
82
83 /// Construct multi-level transformation given a rigid transformation
84 MultiLevelTransformation(const RigidTransformation &);
85
86 /// Construct multi-level transformation given an affine transformation
87 MultiLevelTransformation(const AffineTransformation &);
88
89 /// Copy constructor
90 MultiLevelTransformation(const MultiLevelTransformation &);
91
92 public:
93
94 /// Destructor
95 virtual ~MultiLevelTransformation();
96
97 // ---------------------------------------------------------------------------
98 // Approximation
99
100 /// Approximate displacements: This function takes a set of points and a set
101 /// of displacements and finds a transformation which approximates these
102 /// displacements. After approximation, the displacements are replaced by the
103 /// residual displacement errors at the points.
104 ///
105 /// \note This function does not change the global transformation.
106 /// Use ApproximateAsNew to also approximate a new global transformation.
107 virtual double Approximate(const ImageAttributes &, double *, double *, double *,
108 int = 1, double = .0);
109
110 /// Approximate displacements: This function takes a set of points and a set
111 /// of displacements and finds a transformation which approximates these
112 /// displacements. After approximation, the displacements are replaced by the
113 /// residual displacement errors at the points.
114 ///
115 /// \note This function does not change the global transformation.
116 /// Use ApproximateAsNew to also approximate a new global transformation.
117 virtual double Approximate(const double *, const double *, const double *,
118 double *, double *, double *, int,
119 int = 1, double = .0);
120
121 /// Approximate displacements: This function takes a set of points and a set
122 /// of displacements and finds a transformation which approximates these
123 /// displacements. After approximation, the displacements are replaced by the
124 /// residual displacement errors at the points.
125 ///
126 /// \note This function does not change the global transformation.
127 /// Use ApproximateAsNew to also approximate a new global transformation.
128 virtual double Approximate(const double *, const double *, const double *, const double *,
129 double *, double *, double *, int,
130 int = 1, double = .0);
131
132 /// Approximate displacements: This function takes a set of points and a set
133 /// of displacements and finds a !new! transformation which approximates these
134 /// displacements. After approximation, the displacements are replaced by the
135 /// residual displacement errors at the points.
136 ///
137 /// \note This function also modifies the global transformation.
138 /// Use Reset and Approximate instead if this is not desired.
139 virtual double ApproximateAsNew(const ImageAttributes &, double *, double *, double *,
140 int = 1, double = .0);
141
142 /// Approximate displacements: This function takes a set of points and a set
143 /// of displacements and finds a !new! transformation which approximates these
144 /// displacements. After approximation, the displacements are replaced by the
145 /// residual displacement errors at the points.
146 ///
147 /// \note This function also modifies the global transformation.
148 /// Use Reset and Approximate instead if this is not desired.
149 virtual double ApproximateAsNew(const double *, const double *, const double *,
150 double *, double *, double *, int,
151 int = 1, double = .0);
152
153 /// Approximate displacements: This function takes a set of points and a set
154 /// of displacements and finds a !new! transformation which approximates these
155 /// displacements. After approximation, the displacements are replaced by the
156 /// residual displacement errors at the points.
157 ///
158 /// \note This function also modifies the global transformation.
159 /// Use Reset and Approximate instead if this is not desired.
160 virtual double ApproximateAsNew(const double *, const double *, const double *, const double *,
161 double *, double *, double *, int,
162 int = 1, double = .0);
163
164 /// Approximate displacements: This function takes a set of points and a set
165 /// of displacements and finds !new! parameters such that the resulting
166 /// transformation approximates the displacements as good as possible.
167 virtual void ApproximateDOFs(const double *, const double *, const double *, const double *,
168 const double *, const double *, const double *, int);
169
170 /// Finds gradient of approximation error: This function takes a set of points
171 /// and a set of errors. It finds a gradient w.r.t. the transformation parameters
172 /// which minimizes the L2 norm of the approximation error and adds it to the
173 /// input gradient with the given weight.
174 virtual void ApproximateDOFsGradient(const double *, const double *, const double *, const double *,
175 const double *, const double *, const double *, int,
176 double *, double = 1.0) const;
177
178 // ---------------------------------------------------------------------------
179 // Transformation parameters (DoFs)
180
181 /// Copy active transformation parameters (DoFs) from given
182 /// transformation if possible and return \c false, otherwise
183 virtual bool CopyFrom(const Transformation *);
184
185 /// Get norm of the gradient vector
186 virtual double DOFGradientNorm(const double *) const;
187
188 /// Get number of transformation parameters
189 virtual int NumberOfDOFs() const;
190
191 /// Put value of transformation parameter
192 virtual void Put(int, double);
193
194 /// Put values of transformation parameters
195 virtual void Put(const DOFValue *);
196
197 /// Add change to transformation parameters
198 virtual void Add(const DOFValue *);
199
200 /// Update transformation parameters given parametric gradient
201 virtual double Update(const DOFValue *);
202
203 /// Get value of transformation parameter
204 virtual double Get(int) const;
205
206 /// Get values of transformation parameters
207 virtual void Get(DOFValue *) const;
208
209 /// Put status of transformation parameter
210 virtual void PutStatus(int, DOFStatus);
211
212 /// Get status of transformation parameter
213 virtual DOFStatus GetStatus(int) const;
214
215 /// Checks whether transformation depends on the same vector of parameters
216 virtual bool HasSameDOFsAs(const Transformation *) const;
217
218 /// Checks whether transformation is an identity mapping
219 virtual bool IsIdentity() const;
220
221 /// Reset transformation (does not remove local transformations)
222 virtual void Reset();
223
224 /// Reset transformation and remove all local transformations
225 virtual void Clear();
226
227 // ---------------------------------------------------------------------------
228 // Parameters (non-DoFs)
229
230 // Import other overloads
231 using Transformation::Parameter;
232
233 /// Set named (non-DoF) parameter from value as string
234 virtual bool Set(const char *, const char *);
235
236 /// Get (non-DoF) parameters as key/value as string map
237 virtual ParameterList Parameter() const;
238
239 // ---------------------------------------------------------------------------
240 // Levels
241
242 /// Returns the number of levels
243 virtual int NumberOfLevels() const;
244
245 /// Returns the number of active levels
246 virtual int NumberOfActiveLevels() const;
247
248 /// Returns the number of passive levels
249 virtual int NumberOfPassiveLevels() const;
250
251 /// Returns the total number of control points
252 virtual int NumberOfCPs(bool = false) const;
253
254 /// Returns the total number of active control points on all active levels
255 virtual int NumberOfActiveCPs() const;
256
257 /// Gets global transformation
258 virtual AffineTransformation *GetGlobalTransformation();
259
260 /// Get global transformation
261 virtual const AffineTransformation *GetGlobalTransformation() const;
262
263 /// Gets local transformation
264 virtual FreeFormTransformation *GetLocalTransformation(int);
265
266 /// Gets local transformation
267 virtual const FreeFormTransformation *GetLocalTransformation(int) const;
268
269 /// Put local transformation and return pointer to previous one (needs to be deleted if not used)
270 virtual FreeFormTransformation *PutLocalTransformation(FreeFormTransformation *, int, bool = true);
271
272 /// Push local transformation on stack (append transformation)
273 virtual void PushLocalTransformation(FreeFormTransformation *, bool = true);
274
275 /// Insert local transformation
276 virtual void InsertLocalTransformation(FreeFormTransformation *, int = 0, bool = true);
277
278 /// Pop local transformation from stack (remove last transformation)
279 virtual FreeFormTransformation *PopLocalTransformation();
280
281 /// Remove local transformation and return the pointer (need to be deleted if not used)
282 virtual FreeFormTransformation *RemoveLocalTransformation(int = 0);
283
284 /// Combine local transformations on stack
285 virtual void CombineLocalTransformation();
286
287 /// Put status of local transformation
288 virtual void LocalTransformationStatus(int, FFDStatus);
289
290 /// Get status of local transformation
291 virtual FFDStatus LocalTransformationStatus(int) const;
292
293 /// Get whether local transformation is active
294 virtual bool LocalTransformationIsActive(int) const;
295
296 /// Convert the global transformation from a matrix representation to a
297 /// FFD and incorporate it with any existing local transformation
298 virtual void MergeGlobalIntoLocalDisplacement();
299
300 protected:
301
302 /// Checks whether a given transformation is supported as local transformation
303 virtual void CheckTransformation(FreeFormTransformation *) const;
304
305 /// Helper function for MergeGlobalIntoLocalDisplacement
306 void InterpolateGlobalDisplacement(FreeFormTransformation *);
307
308 public:
309
310 // ---------------------------------------------------------------------------
311 // Point transformation
312
313 // Do not hide methods of base class
314 using Transformation::Transform;
315 using Transformation::LocalDisplacement;
316 using Transformation::Displacement;
317 using Transformation::Inverse;
318 using Transformation::LocalInverseDisplacement;
319 using Transformation::InverseDisplacement;
320
321 /// Whether the caching of the transformation displacements is required
322 /// (or preferred) by this transformation. For some transformations such as
323 /// those parameterized by velocities, caching of the displacements for
324 /// each target voxel results in better performance or is needed for example
325 /// for the scaling and squaring method.
326 virtual bool RequiresCachingOfDisplacements() const;
327
328 /// Transforms a single point using the global transformation component only
329 virtual void GlobalTransform(double &, double &, double &, double = 0, double = NaN) const;
330
331 /// Transforms a single point using the local transformation component only
332 virtual void LocalTransform(int, int, double &, double &, double &, double = 0, double = NaN) const;
333
334 /// Transforms a single point using the local transformation component only
335 virtual void LocalTransform(int, double &, double &, double &, double = 0, double = NaN) const;
336
337 /// Transforms a single point using the local transformation component only
338 virtual void LocalTransform(double &, double &, double &, double = 0, double = NaN) const;
339
340 /// Transforms a single point
341 virtual void Transform(int, int, double &, double &, double &, double = 0, double = NaN) const = 0;
342
343 /// Transforms a single point
344 virtual void Transform(int, double &, double &, double &, double = 0, double = NaN) const;
345
346 /// Transforms a single point
347 virtual void Transform(double &, double &, double &, double = 0, double = NaN) const;
348
349 /// Transforms a single point
350 virtual void Transform(int, int, Point &, double = 0, double = NaN) const;
351
352 /// Transforms a single point
353 virtual void Transform(int, Point &, double = 0, double = NaN) const;
354
355 /// Transforms a set of points
356 virtual void Transform(int, int, PointSet &, double = 0, double = NaN) const;
357
358 /// Transforms a set of points
359 virtual void Transform(int, PointSet &, double = 0, double = NaN) const;
360
361 /// Calculates the displacement of a single point using the local transformation component only
362 virtual void LocalDisplacement(int, int, double &, double &, double &, double = 0, double = NaN) const;
363
364 /// Calculates the displacement of a single point using the local transformation component only
365 virtual void LocalDisplacement(int, double &, double &, double &, double = 0, double = NaN) const;
366
367 /// Calculates the displacement of a single point
368 virtual void Displacement(int, int, double &, double &, double &, double = 0, double = NaN) const;
369
370 /// Calculates the displacement of a single point
371 virtual void Displacement(int, double &, double &, double &, double = 0, double = NaN) const;
372
373 /// Calculates the displacement vectors for a whole image domain
374 virtual void Displacement(int, int, GenericImage<double> &, double = NaN, const WorldCoordsImage * = NULL) const;
375
376 /// Calculates the displacement vectors for a whole image domain
377 virtual void Displacement(int, int, GenericImage<float> &, double = NaN, const WorldCoordsImage * = NULL) const;
378
379 /// Calculates the displacement vectors for a whole image domain
380 virtual void Displacement(int, GenericImage<double> &, double = NaN, const WorldCoordsImage * = NULL) const;
381
382 /// Calculates the displacement vectors for a whole image domain
383 virtual void Displacement(int, GenericImage<float> &, double = NaN, const WorldCoordsImage * = NULL) const;
384
385 /// Calculates the displacement vectors for a whole image domain
386 ///
387 /// \attention The displacements are computed at the positions after applying the
388 /// current displacements at each voxel. These displacements are then
389 /// added to the current displacements. Therefore, set the input
390 /// displacements to zero if only interested in the displacements of
391 /// this transformation at the voxel positions.
392 virtual void Displacement(int, int, GenericImage<double> &, double, double = NaN, const WorldCoordsImage * = NULL) const;
393
394 /// Calculates the displacement vectors for a whole image domain
395 ///
396 /// \attention The displacements are computed at the positions after applying the
397 /// current displacements at each voxel. These displacements are then
398 /// added to the current displacements. Therefore, set the input
399 /// displacements to zero if only interested in the displacements of
400 /// this transformation at the voxel positions.
401 virtual void Displacement(int, int, GenericImage<float> &, double, double = NaN, const WorldCoordsImage * = NULL) const;
402
403 /// Calculates the displacement vectors for a whole image domain
404 ///
405 /// \attention The displacements are computed at the positions after applying the
406 /// current displacements at each voxel. These displacements are then
407 /// added to the current displacements. Therefore, set the input
408 /// displacements to zero if only interested in the displacements of
409 /// this transformation at the voxel positions.
410 virtual void Displacement(int, GenericImage<double> &, double, double = NaN, const WorldCoordsImage * = NULL) const;
411
412 /// Calculates the displacement vectors for a whole image domain
413 ///
414 /// \attention The displacements are computed at the positions after applying the
415 /// current displacements at each voxel. These displacements are then
416 /// added to the current displacements. Therefore, set the input
417 /// displacements to zero if only interested in the displacements of
418 /// this transformation at the voxel positions.
419 virtual void Displacement(int, GenericImage<float> &, double, double = NaN, const WorldCoordsImage * = NULL) const;
420
421 /// Calculates the displacement vectors for a whole image domain
422 ///
423 /// \attention The displacements are computed at the positions after applying the
424 /// current displacements at each voxel. These displacements are then
425 /// added to the current displacements. Therefore, set the input
426 /// displacements to zero if only interested in the displacements of
427 /// this transformation at the voxel positions.
428 virtual void Displacement(GenericImage<double> &, double, double = NaN, const WorldCoordsImage * = NULL) const;
429
430 /// Calculates the displacement vectors for a whole image domain
431 ///
432 /// \attention The displacements are computed at the positions after applying the
433 /// current displacements at each voxel. These displacements are then
434 /// added to the current displacements. Therefore, set the input
435 /// displacements to zero if only interested in the displacements of
436 /// this transformation at the voxel positions.
437 virtual void Displacement(GenericImage<float> &, double, double = NaN, const WorldCoordsImage * = NULL) const;
438
439 /// Transforms a single point using the inverse of the global transformation only
440 virtual void GlobalInverse(double &, double &, double &, double = 0, double = NaN) const;
441
442 /// Transforms a single point using the inverse of the local transformation only
443 virtual bool LocalInverse(int, int, double &, double &, double &, double = 0, double = NaN) const;
444
445 /// Transforms a single point using the inverse of the local transformation only
446 virtual bool LocalInverse(int, double &, double &, double &, double = 0, double = NaN) const;
447
448 /// Transforms a single point using the inverse of the local transformation only
449 virtual bool LocalInverse(double &, double &, double &, double = 0, double = NaN) const;
450
451 /// Transforms a single point using the inverse of the transformation
452 virtual bool Inverse(int, int, double &, double &, double &, double = 0, double = NaN) const;
453
454 /// Transforms a single point using the inverse of the transformation
455 virtual bool Inverse(int, double &, double &, double &, double = 0, double = NaN) const;
456
457 /// Transforms a single point using the inverse of the transformation
458 virtual bool Inverse(double &, double &, double &, double = 0, double = NaN) const;
459
460 /// Calculates the displacement of a single point using the inverse of the local transformation only
461 virtual bool LocalInverseDisplacement(int, int, double &, double &, double &, double = 0, double = NaN) const;
462
463 /// Calculates the displacement of a single point using the inverse of the local transformation only
464 virtual bool LocalInverseDisplacement(int, double &, double &, double &, double = 0, double = NaN) const;
465
466 /// Calculates the displacement of a single point using the inverse of the transformation
467 virtual bool InverseDisplacement(int, int, double &, double &, double &, double = 0, double = NaN) const;
468
469 /// Calculates the displacement of a single point using the inverse of the transformation
470 virtual bool InverseDisplacement(int, double &, double &, double &, double = 0, double = NaN) const;
471
472 /// Calculates the inverse displacement vectors for a whole image domain
473 ///
474 /// \attention The displacements are computed at the positions after applying the
475 /// current displacements at each voxel. These displacements are then
476 /// added to the current displacements. Therefore, set the input
477 /// displacements to zero if only interested in the displacements of
478 /// this transformation at the voxel positions.
479 ///
480 /// \returns Number of points at which transformation is non-invertible.
481 virtual int InverseDisplacement(int, int, GenericImage<double> &, double, double = NaN, const WorldCoordsImage * = NULL) const;
482
483 /// Calculates the inverse displacement vectors for a whole image domain
484 ///
485 /// \attention The displacements are computed at the positions after applying the
486 /// current displacements at each voxel. These displacements are then
487 /// added to the current displacements. Therefore, set the input
488 /// displacements to zero if only interested in the displacements of
489 /// this transformation at the voxel positions.
490 ///
491 /// \returns Number of points at which transformation is non-invertible.
492 virtual int InverseDisplacement(int, int, GenericImage<float> &, double, double = NaN, const WorldCoordsImage * = NULL) const;
493
494 /// Calculates the inverse displacement vectors for a whole image domain
495 ///
496 /// \attention The displacements are computed at the positions after applying the
497 /// current displacements at each voxel. These displacements are then
498 /// added to the current displacements. Therefore, set the input
499 /// displacements to zero if only interested in the displacements of
500 /// this transformation at the voxel positions.
501 ///
502 /// \returns Number of points at which transformation is non-invertible.
503 virtual int InverseDisplacement(int, GenericImage<double> &, double, double = NaN, const WorldCoordsImage * = NULL) const;
504
505 /// Calculates the inverse displacement vectors for a whole image domain
506 ///
507 /// \attention The displacements are computed at the positions after applying the
508 /// current displacements at each voxel. These displacements are then
509 /// added to the current displacements. Therefore, set the input
510 /// displacements to zero if only interested in the displacements of
511 /// this transformation at the voxel positions.
512 ///
513 /// \returns Number of points at which transformation is non-invertible.
514 virtual int InverseDisplacement(int, GenericImage<float> &, double, double = NaN, const WorldCoordsImage * = NULL) const;
515
516 /// Calculates the inverse displacement vectors for a whole image domain
517 ///
518 /// \attention The displacements are computed at the positions after applying the
519 /// current displacements at each voxel. These displacements are then
520 /// added to the current displacements. Therefore, set the input
521 /// displacements to zero if only interested in the displacements of
522 /// this transformation at the voxel positions.
523 ///
524 /// \returns Number of points at which transformation is non-invertible.
525 virtual int InverseDisplacement(GenericImage<double> &, double, double = NaN, const WorldCoordsImage * = NULL) const;
526
527 /// Calculates the inverse displacement vectors for a whole image domain
528 ///
529 /// \attention The displacements are computed at the positions after applying the
530 /// current displacements at each voxel. These displacements are then
531 /// added to the current displacements. Therefore, set the input
532 /// displacements to zero if only interested in the displacements of
533 /// this transformation at the voxel positions.
534 ///
535 /// \returns Number of points at which transformation is non-invertible.
536 virtual int InverseDisplacement(GenericImage<float> &, double, double = NaN, const WorldCoordsImage * = NULL) const;
537
538 // ---------------------------------------------------------------------------
539 // Derivatives
540
541 // Do not hide methods of base class
542 using Transformation::GlobalJacobian;
543 using Transformation::LocalJacobian;
544 using Transformation::Jacobian;
545
546 /// Calculates the Jacobian of the global transformation w.r.t world coordinates
547 virtual void GlobalJacobian(Matrix &, double, double, double, double = 0, double = NaN) const;
548
549 /// Calculates the Jacobian of the local transformation w.r.t world coordinates
550 virtual void LocalJacobian(int, Matrix &, double, double, double, double = 0, double = NaN) const;
551
552 /// Calculates the Jacobian of the local transformation w.r.t world coordinates
553 virtual void LocalJacobian(Matrix &, double, double, double, double = 0, double = NaN) const;
554
555 /// Calculates the Jacobian of the transformation w.r.t world coordinates
556 virtual void Jacobian(int, int, Matrix &, double, double, double, double = 0, double = NaN) const;
557
558 /// Calculates the Jacobian of the transformation w.r.t world coordinates
559 virtual void Jacobian(int, Matrix &, double, double, double, double = 0, double = NaN) const;
560
561 /// Calculates the Jacobian of the transformation w.r.t world coordinates
562 virtual void Jacobian(Matrix &, double, double, double, double = 0, double = NaN) const;
563
564 /// Calculates the determinant of the Jacobian of the local transformation w.r.t world coordinates
565 virtual double LocalJacobian(int, double, double, double, double = 0, double = NaN) const;
566
567 /// Calculates the determinant of the Jacobian of the transformation w.r.t world coordinates
568 virtual double Jacobian(int, int, double, double, double, double = 0, double = NaN) const;
569
570 /// Calculates the determinant of the Jacobian of the transformation w.r.t world coordinates
571 virtual double Jacobian(int, double, double, double, double = 0, double = NaN) const;
572
573 /// Calculates the Hessian for each component of the global transformation w.r.t world coordinates
574 virtual void GlobalHessian(Matrix [3], double, double, double, double = 0, double = NaN) const;
575
576 /// Calculates the Hessian for each component of the local transformation w.r.t world coordinates
577 virtual void LocalHessian(int, Matrix [3], double, double, double, double = 0, double = NaN) const;
578
579 /// Calculates the Hessian for each component of the local transformation w.r.t world coordinates
580 virtual void LocalHessian(Matrix [3], double, double, double, double = 0, double = NaN) const;
581
582 /// Calculates the Hessian for each component of the transformation w.r.t world coordinates
583 virtual void Hessian(int, int, Matrix [3], double, double, double, double = 0, double = NaN) const;
584
585 /// Calculates the Hessian for each component of the transformation w.r.t world coordinates
586 virtual void Hessian(int, Matrix [3], double, double, double, double = 0, double = NaN) const;
587
588 /// Calculates the Hessian for each component of the transformation w.r.t world coordinates
589 virtual void Hessian(Matrix [3], double, double, double, double = 0, double = NaN) const;
590
591 /// Calculates the Jacobian of the transformation w.r.t the transformation parameters
592 virtual void JacobianDOFs(double [3], int, double, double, double, double = 0, double = NaN) const;
593
594 /// Calculates the derivative of the Jacobian of the transformation (w.r.t. world coordinates) w.r.t. a transformation parameter
595 virtual void DeriveJacobianWrtDOF(Matrix &, int, double, double, double, double = 0, double = NaN) const;
596
597 // ---------------------------------------------------------------------------
598 // Properties
599
600 /// Calculates the bending energy of the transformation
601 virtual double BendingEnergy(int, int, double, double, double, double = 0, double = NaN, bool = true) const;
602
603 /// Calculates the bending energy of the transformation
604 virtual double BendingEnergy(int, double, double, double, double = 0, double = NaN, bool = true) const;
605
606 /// Calculates the bending energy of the transformation
607 virtual double BendingEnergy(double, double, double, double = 0, double = NaN, bool = true) const;
608
609 // ---------------------------------------------------------------------------
610 // I/O
611
612 // Do not hide methods of base class
613 using Transformation::Print;
614
615 /// Prints the parameters of the transformation
616 virtual void Print(ostream &, Indent = 0) const;
617
618 protected:
619
620 /// Reads transformation parameters from a file stream
621 virtual Cifstream &ReadDOFs(Cifstream &, TransformationType);
622
623 /// Writes transformation parameters to a file stream
624 virtual Cofstream &WriteDOFs(Cofstream &) const;
625
626 };
627
628 ////////////////////////////////////////////////////////////////////////////////
629 // Inline definitions
630 ////////////////////////////////////////////////////////////////////////////////
631
632 // =============================================================================
633 // Transformation parameters
634 // =============================================================================
635
636 // -----------------------------------------------------------------------------
DOFIndexToLocalTransformation(const MultiLevelTransformation * mffd,int idx,const FreeFormTransformation * & ffd,int & dof)637 inline int DOFIndexToLocalTransformation(const MultiLevelTransformation *mffd, int idx,
638 const FreeFormTransformation *&ffd, int &dof)
639 {
640 mirtkAssert(idx >= 0, "DoF index must be positive");
641 dof = idx;
642 for (int l = 0; l < mffd->NumberOfLevels(); ++l) {
643 if (!mffd->LocalTransformationIsActive(l)) continue;
644 ffd = mffd->GetLocalTransformation(l);
645 if (dof < ffd->NumberOfDOFs()) return l;
646 dof -= ffd->NumberOfDOFs();
647 }
648 ffd = NULL;
649 mirtkAssert(false, "DoF index out-of-bounds");
650 return -1;
651 }
652
653 // -----------------------------------------------------------------------------
DOFIndexToLocalTransformation(MultiLevelTransformation * mffd,int idx,FreeFormTransformation * & ffd,int & dof)654 inline int DOFIndexToLocalTransformation(MultiLevelTransformation *mffd, int idx,
655 FreeFormTransformation *&ffd, int &dof)
656 {
657 mirtkAssert(idx >= 0, "DoF index must be positive");
658 dof = idx;
659 for (int l = 0; l < mffd->NumberOfLevels(); ++l) {
660 if (!mffd->LocalTransformationIsActive(l)) continue;
661 ffd = mffd->GetLocalTransformation(l);
662 if (dof < ffd->NumberOfDOFs()) return l;
663 dof -= ffd->NumberOfDOFs();
664 }
665 ffd = NULL;
666 mirtkAssert(false, "DoF index out-of-bounds");
667 return -1;
668 }
669
670 // =============================================================================
671 // Levels
672 // =============================================================================
673
674 // -----------------------------------------------------------------------------
NumberOfLevels()675 inline int MultiLevelTransformation::NumberOfLevels() const
676 {
677 return _NumberOfLevels;
678 }
679
680 // -----------------------------------------------------------------------------
NumberOfActiveLevels()681 inline int MultiLevelTransformation::NumberOfActiveLevels() const
682 {
683 int n = 0;
684 for (int i = 0; i < _NumberOfLevels; ++i) {
685 if (_LocalTransformationStatus[i] == Active) ++n;
686 }
687 return n;
688 }
689
690 // -----------------------------------------------------------------------------
NumberOfPassiveLevels()691 inline int MultiLevelTransformation::NumberOfPassiveLevels() const
692 {
693 return _NumberOfLevels - this->NumberOfActiveLevels();
694 }
695
696 // -----------------------------------------------------------------------------
GetGlobalTransformation()697 inline AffineTransformation *MultiLevelTransformation::GetGlobalTransformation()
698 {
699 return &_GlobalTransformation;
700 }
701
702 // -----------------------------------------------------------------------------
GetGlobalTransformation()703 inline const AffineTransformation *MultiLevelTransformation::GetGlobalTransformation() const
704 {
705 return &_GlobalTransformation;
706 }
707
708 // -----------------------------------------------------------------------------
GetLocalTransformation(int i)709 inline FreeFormTransformation *MultiLevelTransformation::GetLocalTransformation(int i)
710 {
711 if (i < 0) i += _NumberOfLevels;
712 return (0 <= i && i < _NumberOfLevels) ? _LocalTransformation[i] : NULL;
713 }
714
715 // -----------------------------------------------------------------------------
GetLocalTransformation(int i)716 inline const FreeFormTransformation *MultiLevelTransformation::GetLocalTransformation(int i) const
717 {
718 if (i < 0) i += _NumberOfLevels;
719 return (0 <= i && i < _NumberOfLevels) ? _LocalTransformation[i] : NULL;
720 }
721
722 // -----------------------------------------------------------------------------
LocalTransformationStatus(int i,FFDStatus status)723 inline void MultiLevelTransformation::LocalTransformationStatus(int i, FFDStatus status)
724 {
725 if (i < 0) i += _NumberOfLevels;
726 _LocalTransformationStatus[i] = status;
727 }
728
729 // -----------------------------------------------------------------------------
730 inline MultiLevelTransformation::FFDStatus
LocalTransformationStatus(int i)731 MultiLevelTransformation::LocalTransformationStatus(int i) const
732 {
733 if (i < 0) i += _NumberOfLevels;
734 return _LocalTransformationStatus[i];
735 }
736
737 // -----------------------------------------------------------------------------
LocalTransformationIsActive(int i)738 inline bool MultiLevelTransformation::LocalTransformationIsActive(int i) const
739 {
740 if (i < 0) i += _NumberOfLevels;
741 return (_LocalTransformationStatus[i] == Active);
742 }
743
744 // =============================================================================
745 // Point transformation
746 // =============================================================================
747
748 // -----------------------------------------------------------------------------
RequiresCachingOfDisplacements()749 inline bool MultiLevelTransformation::RequiresCachingOfDisplacements() const
750 {
751 for (int i = 0; i < this->NumberOfLevels(); ++i) {
752 if (this->GetLocalTransformation(i)->RequiresCachingOfDisplacements()) return true;
753 }
754 return false;
755 }
756
757 // -----------------------------------------------------------------------------
GlobalTransform(double & x,double & y,double & z,double t,double t0)758 inline void MultiLevelTransformation::GlobalTransform(double &x, double &y, double &z, double t, double t0) const
759 {
760 this->GetGlobalTransformation()->Transform(x, y, z, t, t0);
761 }
762
763 // -----------------------------------------------------------------------------
764 // Note: The Transformation interface requires that every transformation is
765 // the sum of global and local transformations, i.e., T = T_global + T_local.
766 // This allows a common interpretation of what LocalTransform does.
LocalTransform(int m,int n,double & x,double & y,double & z,double t,double t0)767 inline void MultiLevelTransformation::LocalTransform(int m, int n, double &x, double &y, double &z, double t, double t0) const
768 {
769 if (m < 0) {
770 // Compute y = x + (T(x) - T_global(x))
771 double x1 = x, y1 = y, z1 = z;
772 double x2 = x, y2 = y, z2 = z;
773 this->GetGlobalTransformation()->Transform(x1, y1, z1);
774 this->Transform(-1, n, x2, y2, z2, t, t0);
775 x += (x2 - x1);
776 y += (y2 - y1);
777 z += (z2 - z1);
778 } else {
779 this->Transform(m, n, x, y, z, t, t0);
780 }
781 }
782
783 // -----------------------------------------------------------------------------
LocalTransform(int n,double & x,double & y,double & z,double t,double t0)784 inline void MultiLevelTransformation::LocalTransform(int n, double &x, double &y, double &z, double t, double t0) const
785 {
786 this->LocalTransform(0, n, x, y, z, t, t0);
787 }
788
789 // -----------------------------------------------------------------------------
LocalTransform(double & x,double & y,double & z,double t,double t0)790 inline void MultiLevelTransformation::LocalTransform(double &x, double &y, double &z, double t, double t0) const
791 {
792 this->LocalTransform(-1, x, y, z, t, t0);
793 }
794
795 // -----------------------------------------------------------------------------
Transform(int n,double & x,double & y,double & z,double t,double t0)796 inline void MultiLevelTransformation::Transform(int n, double &x, double &y, double &z, double t, double t0) const
797 {
798 this->Transform(-1, n, x, y, z, t, t0);
799 }
800
801 // -----------------------------------------------------------------------------
Transform(double & x,double & y,double & z,double t,double t0)802 inline void MultiLevelTransformation::Transform(double &x, double &y, double &z, double t, double t0) const
803 {
804 this->Transform(-1, x, y, z, t, t0);
805 }
806
807 // -----------------------------------------------------------------------------
Transform(int l,int n,Point & p,double t,double t0)808 inline void MultiLevelTransformation::Transform(int l, int n, Point &p, double t, double t0) const
809 {
810 this->Transform(l, n, p._x, p._y, p._z, t, t0);
811 }
812
813 // -----------------------------------------------------------------------------
Transform(int n,Point & p,double t,double t0)814 inline void MultiLevelTransformation::Transform(int n, Point &p, double t, double t0) const
815 {
816 this->Transform(0, n, p, t, t0);
817 }
818
819 // -----------------------------------------------------------------------------
Transform(int l,int n,PointSet & pset,double t,double t0)820 inline void MultiLevelTransformation::Transform(int l, int n, PointSet &pset, double t, double t0) const
821 {
822 for (int i = 0; i < pset.Size(); i++) this->Transform(l, n, pset(i), t, t0);
823 }
824
825 // -----------------------------------------------------------------------------
Transform(int n,PointSet & pset,double t,double t0)826 inline void MultiLevelTransformation::Transform(int n, PointSet &pset, double t, double t0) const
827 {
828 this->Transform(0, n, pset, t, t0);
829 }
830
831 // -----------------------------------------------------------------------------
LocalDisplacement(int l,int n,double & x,double & y,double & z,double t,double t0)832 inline void MultiLevelTransformation::LocalDisplacement(int l, int n, double &x, double &y, double &z, double t, double t0) const
833 {
834 const double u = x;
835 const double v = y;
836 const double w = z;
837
838 this->LocalTransform(l, n, x, y, z, t, t0);
839
840 x -= u;
841 y -= v;
842 z -= w;
843 }
844
845 // -----------------------------------------------------------------------------
LocalDisplacement(int n,double & x,double & y,double & z,double t,double t0)846 inline void MultiLevelTransformation::LocalDisplacement(int n, double &x, double &y, double &z, double t, double t0) const
847 {
848 this->LocalDisplacement(0, n, x, y, z, t, t0);
849 }
850
851 // -----------------------------------------------------------------------------
Displacement(int l,int n,double & x,double & y,double & z,double t,double t0)852 inline void MultiLevelTransformation::Displacement(int l, int n, double &x, double &y, double &z, double t, double t0) const
853 {
854 const double u = x;
855 const double v = y;
856 const double w = z;
857
858 this->Transform(l, n, x, y, z, t, t0);
859
860 x -= u;
861 y -= v;
862 z -= w;
863 }
864
865 // -----------------------------------------------------------------------------
Displacement(int n,double & x,double & y,double & z,double t,double t0)866 inline void MultiLevelTransformation::Displacement(int n, double &x, double &y, double &z, double t, double t0) const
867 {
868 this->Displacement(-1, n, x, y, z, t, t0);
869 }
870
871 // -----------------------------------------------------------------------------
Displacement(int l,int n,GenericImage<double> & disp,double t0,const WorldCoordsImage * i2w)872 inline void MultiLevelTransformation::Displacement(int l, int n, GenericImage<double> &disp, double t0, const WorldCoordsImage *i2w) const
873 {
874 disp = .0;
875 this->Displacement(l, n, disp, disp.GetTOrigin(), t0, i2w);
876 }
877
878 // -----------------------------------------------------------------------------
Displacement(int l,int n,GenericImage<float> & disp,double t0,const WorldCoordsImage * i2w)879 inline void MultiLevelTransformation::Displacement(int l, int n, GenericImage<float> &disp, double t0, const WorldCoordsImage *i2w) const
880 {
881 disp = .0f;
882 this->Displacement(l, n, disp, disp.GetTOrigin(), t0, i2w);
883 }
884
885 // -----------------------------------------------------------------------------
Displacement(int n,GenericImage<double> & disp,double t0,const WorldCoordsImage * i2w)886 inline void MultiLevelTransformation::Displacement(int n, GenericImage<double> &disp, double t0, const WorldCoordsImage *i2w) const
887 {
888 this->Displacement(-1, n, disp, t0, i2w);
889 }
890
891 // -----------------------------------------------------------------------------
Displacement(int n,GenericImage<float> & disp,double t0,const WorldCoordsImage * i2w)892 inline void MultiLevelTransformation::Displacement(int n, GenericImage<float> &disp, double t0, const WorldCoordsImage *i2w) const
893 {
894 this->Displacement(-1, n, disp, t0, i2w);
895 }
896
897 // -----------------------------------------------------------------------------
Displacement(int n,GenericImage<double> & disp,double t,double t0,const WorldCoordsImage * wc)898 inline void MultiLevelTransformation::Displacement(int n, GenericImage<double> &disp, double t, double t0, const WorldCoordsImage *wc) const
899 {
900 this->Displacement(-1, n, disp, t, t0, wc);
901 }
902
903 // -----------------------------------------------------------------------------
Displacement(int n,GenericImage<float> & disp,double t,double t0,const WorldCoordsImage * wc)904 inline void MultiLevelTransformation::Displacement(int n, GenericImage<float> &disp, double t, double t0, const WorldCoordsImage *wc) const
905 {
906 this->Displacement(-1, n, disp, t, t0, wc);
907 }
908
909 // -----------------------------------------------------------------------------
Displacement(GenericImage<double> & disp,double t,double t0,const WorldCoordsImage * wc)910 inline void MultiLevelTransformation::Displacement(GenericImage<double> &disp, double t, double t0, const WorldCoordsImage *wc) const
911 {
912 this->Displacement(-1, disp, t, t0, wc);
913 }
914
915 // -----------------------------------------------------------------------------
Displacement(GenericImage<float> & disp,double t,double t0,const WorldCoordsImage * wc)916 inline void MultiLevelTransformation::Displacement(GenericImage<float> &disp, double t, double t0, const WorldCoordsImage *wc) const
917 {
918 this->Displacement(-1, disp, t, t0, wc);
919 }
920
921 // -----------------------------------------------------------------------------
GlobalInverse(double & x,double & y,double & z,double t,double t0)922 inline void MultiLevelTransformation::GlobalInverse(double &x, double &y, double &z, double t, double t0) const
923 {
924 this->GetGlobalTransformation()->Inverse(x, y, z, t, t0);
925 }
926
927 // -----------------------------------------------------------------------------
928 // Note: The Transformation interface requires that every transformation is
929 // the sum of global and local transformations, i.e., T = T_global + T_local.
930 // This allows a common interpretation of what LocalTransform does.
LocalInverse(int m,int n,double & x,double & y,double & z,double t,double t0)931 inline bool MultiLevelTransformation::LocalInverse(int m, int n, double &x, double &y, double &z, double t, double t0) const
932 {
933 if (m < 0) {
934 // Compute y = x + (inv T(x) - inv T_global(x))
935 double x1 = x, y1 = y, z1 = z;
936 double x2 = x, y2 = y, z2 = z;
937 this->GetGlobalTransformation()->Inverse(x1, y1, z1);
938 bool ok = this->Inverse(-1, n, x2, y2, z2, t, t0);
939 x += (x2 - x1);
940 y += (y2 - y1);
941 z += (z2 - z1);
942 return ok;
943 } else {
944 return this->Inverse(m, n, x, y, z, t, t0);
945 }
946 }
947
948 // -----------------------------------------------------------------------------
LocalInverse(int n,double & x,double & y,double & z,double t,double t0)949 inline bool MultiLevelTransformation::LocalInverse(int n, double &x, double &y, double &z, double t, double t0) const
950 {
951 return this->LocalInverse(0, n, x, y, z, t, t0);
952 }
953
954 // -----------------------------------------------------------------------------
LocalInverse(double & x,double & y,double & z,double t,double t0)955 inline bool MultiLevelTransformation::LocalInverse(double &x, double &y, double &z, double t, double t0) const
956 {
957 return this->LocalInverse(-1, x, y, z, t, t0);
958 }
959
960 // -----------------------------------------------------------------------------
Inverse(int n,double & x,double & y,double & z,double t,double t0)961 inline bool MultiLevelTransformation::Inverse(int n, double &x, double &y, double &z, double t, double t0) const
962 {
963 return this->Inverse(-1, n, x, y, z, t, t0);
964 }
965
966 // -----------------------------------------------------------------------------
Inverse(double & x,double & y,double & z,double t,double t0)967 inline bool MultiLevelTransformation::Inverse(double &x, double &y, double &z, double t, double t0) const
968 {
969 return this->Inverse(-1, x, y, z, t, t0);
970 }
971
972 // -----------------------------------------------------------------------------
LocalInverseDisplacement(int l,int n,double & x,double & y,double & z,double t,double t0)973 inline bool MultiLevelTransformation::LocalInverseDisplacement(int l, int n, double &x, double &y, double &z, double t, double t0) const
974 {
975 const double u = x;
976 const double v = y;
977 const double w = z;
978
979 bool ok = this->LocalInverse(l, n, x, y, z, t, t0);
980
981 x -= u;
982 y -= v;
983 z -= w;
984
985 return ok;
986 }
987
988 // -----------------------------------------------------------------------------
LocalInverseDisplacement(int n,double & x,double & y,double & z,double t,double t0)989 inline bool MultiLevelTransformation::LocalInverseDisplacement(int n, double &x, double &y, double &z, double t, double t0) const
990 {
991 return this->LocalInverseDisplacement(0, n, x, y, z, t, t0);
992 }
993
994 // -----------------------------------------------------------------------------
InverseDisplacement(int l,int n,double & x,double & y,double & z,double t,double t0)995 inline bool MultiLevelTransformation::InverseDisplacement(int l, int n, double &x, double &y, double &z, double t, double t0) const
996 {
997 const double u = x;
998 const double v = y;
999 const double w = z;
1000
1001 bool ok = this->Inverse(l, n, x, y, z, t, t0);
1002
1003 x -= u;
1004 y -= v;
1005 z -= w;
1006
1007 return ok;
1008 }
1009
1010 // -----------------------------------------------------------------------------
InverseDisplacement(int n,double & x,double & y,double & z,double t,double t0)1011 inline bool MultiLevelTransformation::InverseDisplacement(int n, double &x, double &y, double &z, double t, double t0) const
1012 {
1013 return this->InverseDisplacement(-1, n, x, y, z, t, t0);
1014 }
1015
1016 // -----------------------------------------------------------------------------
InverseDisplacement(int n,GenericImage<double> & disp,double t,double t0,const WorldCoordsImage * wc)1017 inline int MultiLevelTransformation::InverseDisplacement(int n, GenericImage<double> &disp, double t, double t0, const WorldCoordsImage *wc) const
1018 {
1019 return this->InverseDisplacement(-1, n, disp, t, t0, wc);
1020 }
1021
1022 // -----------------------------------------------------------------------------
InverseDisplacement(int n,GenericImage<float> & disp,double t,double t0,const WorldCoordsImage * wc)1023 inline int MultiLevelTransformation::InverseDisplacement(int n, GenericImage<float> &disp, double t, double t0, const WorldCoordsImage *wc) const
1024 {
1025 return this->InverseDisplacement(-1, n, disp, t, t0, wc);
1026 }
1027
1028 // -----------------------------------------------------------------------------
InverseDisplacement(GenericImage<double> & disp,double t,double t0,const WorldCoordsImage * wc)1029 inline int MultiLevelTransformation::InverseDisplacement(GenericImage<double> &disp, double t, double t0, const WorldCoordsImage *wc) const
1030 {
1031 return this->InverseDisplacement(-1, disp, t, t0, wc);
1032 }
1033
1034 // -----------------------------------------------------------------------------
InverseDisplacement(GenericImage<float> & disp,double t,double t0,const WorldCoordsImage * wc)1035 inline int MultiLevelTransformation::InverseDisplacement(GenericImage<float> &disp, double t, double t0, const WorldCoordsImage *wc) const
1036 {
1037 return this->InverseDisplacement(-1, disp, t, t0, wc);
1038 }
1039
1040 // =============================================================================
1041 // Derivatives
1042 // =============================================================================
1043
1044 // -----------------------------------------------------------------------------
Jacobian(int,int,Matrix &,double,double,double,double,double)1045 inline void MultiLevelTransformation::Jacobian(int, int, Matrix &, double, double, double, double, double) const
1046 {
1047 cerr << this->NameOfClass() << "::Jacobian(int, int, ...): Not implemented" << endl;
1048 exit(1);
1049 }
1050
1051 // -----------------------------------------------------------------------------
Jacobian(int n,Matrix & jac,double x,double y,double z,double t,double t0)1052 inline void MultiLevelTransformation::Jacobian(int n, Matrix &jac, double x, double y, double z, double t, double t0) const
1053 {
1054 this->Jacobian(-1, n, jac, x, y, z, t, t0);
1055 }
1056
1057 // -----------------------------------------------------------------------------
Jacobian(Matrix & jac,double x,double y,double z,double t,double t0)1058 inline void MultiLevelTransformation::Jacobian(Matrix &jac, double x, double y, double z, double t, double t0) const
1059 {
1060 this->Jacobian(-1, -1, jac, x, y, z, t, t0);
1061 }
1062
1063 // -----------------------------------------------------------------------------
GlobalJacobian(Matrix & jac,double x,double y,double z,double t,double t0)1064 inline void MultiLevelTransformation::GlobalJacobian(Matrix &jac, double x, double y, double z, double t, double t0) const
1065 {
1066 this->GetGlobalTransformation()->Jacobian(jac, x, y, z, t, t0);
1067 }
1068
1069 // -----------------------------------------------------------------------------
LocalJacobian(int n,Matrix & jac,double x,double y,double z,double t,double t0)1070 inline void MultiLevelTransformation::LocalJacobian(int n, Matrix &jac, double x, double y, double z, double t, double t0) const
1071 {
1072 this->Jacobian(0, n, jac, x, y, z, t, t0);
1073 }
1074
1075 // -----------------------------------------------------------------------------
LocalJacobian(Matrix & jac,double x,double y,double z,double t,double t0)1076 inline void MultiLevelTransformation::LocalJacobian(Matrix &jac, double x, double y, double z, double t, double t0) const
1077 {
1078 this->Jacobian(0, -1, jac, x, y, z, t, t0);
1079 }
1080
1081 // -----------------------------------------------------------------------------
Jacobian(int m,int n,double x,double y,double z,double t,double t0)1082 inline double MultiLevelTransformation::Jacobian(int m, int n, double x, double y, double z, double t, double t0) const
1083 {
1084 Matrix jac(3, 3);
1085 this->Jacobian(m, n, jac, x, y, z, t, t0);
1086 return jac.Det3x3();
1087 }
1088
1089 // -----------------------------------------------------------------------------
Jacobian(int n,double x,double y,double z,double t,double t0)1090 inline double MultiLevelTransformation::Jacobian(int n, double x, double y, double z, double t, double t0) const
1091 {
1092 return this->Jacobian(-1, n, x, y, z, t, t0);
1093 }
1094
1095 // -----------------------------------------------------------------------------
LocalJacobian(int n,double x,double y,double z,double t,double t0)1096 inline double MultiLevelTransformation::LocalJacobian(int n, double x, double y, double z, double t, double t0) const
1097 {
1098 return this->Jacobian(0, n, x, y, z, t, t0);
1099 }
1100
1101 // -----------------------------------------------------------------------------
Hessian(int,int,Matrix[3],double,double,double,double,double)1102 inline void MultiLevelTransformation::Hessian(int, int, Matrix [3], double, double, double, double, double) const
1103 {
1104 cerr << this->NameOfClass() << "::Hessian(int, int,...): Not implemented" << endl;
1105 exit(1);
1106 }
1107
1108 // -----------------------------------------------------------------------------
Hessian(int n,Matrix hessian[3],double x,double y,double z,double t,double t0)1109 inline void MultiLevelTransformation::Hessian(int n, Matrix hessian[3], double x, double y, double z, double t, double t0) const
1110 {
1111 this->Hessian(-1, n, hessian, x, y, z, t, t0);
1112 }
1113
1114 // -----------------------------------------------------------------------------
Hessian(Matrix hessian[3],double x,double y,double z,double t,double t0)1115 inline void MultiLevelTransformation::Hessian(Matrix hessian[3], double x, double y, double z, double t, double t0) const
1116 {
1117 this->Hessian(-1, -1, hessian, x, y, z, t, t0);
1118 }
1119
1120 // -----------------------------------------------------------------------------
GlobalHessian(Matrix hessian[3],double x,double y,double z,double t,double t0)1121 inline void MultiLevelTransformation::GlobalHessian(Matrix hessian[3], double x, double y, double z, double t, double t0) const
1122 {
1123 this->GetGlobalTransformation()->Hessian(hessian, x, y, z, t, t0);
1124 }
1125
1126 // -----------------------------------------------------------------------------
LocalHessian(int n,Matrix hessian[3],double x,double y,double z,double t,double t0)1127 inline void MultiLevelTransformation::LocalHessian(int n, Matrix hessian[3], double x, double y, double z, double t, double t0) const
1128 {
1129 this->Hessian(0, n, hessian, x, y, z, t, t0);
1130 }
1131
1132 // -----------------------------------------------------------------------------
LocalHessian(Matrix hessian[3],double x,double y,double z,double t,double t0)1133 inline void MultiLevelTransformation::LocalHessian(Matrix hessian[3], double x, double y, double z, double t, double t0) const
1134 {
1135 this->Hessian(0, -1, hessian, x, y, z, t, t0);
1136 }
1137
1138 // -----------------------------------------------------------------------------
DeriveJacobianWrtDOF(Matrix & jac,int dof,double x,double y,double z,double t,double t0)1139 inline void MultiLevelTransformation::DeriveJacobianWrtDOF(Matrix &jac, int dof, double x, double y, double z, double t, double t0) const
1140 {
1141 cerr << this->NameOfClass() << "::DeriveJacobianWrtDOF: Not implemented" << endl;
1142 exit(1);
1143 }
1144
1145 // =============================================================================
1146 // Properties
1147 // =============================================================================
1148
1149 // -----------------------------------------------------------------------------
BendingEnergy(int m,int n,double x,double y,double z,double t,double t0,bool wrt_world)1150 inline double MultiLevelTransformation::BendingEnergy(int m, int n, double x, double y, double z, double t, double t0, bool wrt_world) const
1151 {
1152 double bending = .0;
1153 const int l1 = (m < 0 ? 0 : m);
1154 const int l2 = (n < 0 || n > this->NumberOfLevels() ? this->NumberOfLevels() : n);
1155 for (int l = l1; l < l2; ++l) {
1156 bending += this->GetLocalTransformation(l)->BendingEnergy(x, y, z, t, t0, wrt_world);
1157 }
1158 return bending;
1159 }
1160
1161 // -----------------------------------------------------------------------------
BendingEnergy(int n,double x,double y,double z,double t,double t0,bool wrt_world)1162 inline double MultiLevelTransformation::BendingEnergy(int n, double x, double y, double z, double t, double t0, bool wrt_world) const
1163 {
1164 return this->BendingEnergy(0, n, x, y, z, t, t0, wrt_world);
1165 }
1166
1167 // -----------------------------------------------------------------------------
BendingEnergy(double x,double y,double z,double t,double t0,bool wrt_world)1168 inline double MultiLevelTransformation::BendingEnergy(double x, double y, double z, double t, double t0, bool wrt_world) const
1169 {
1170 return this->BendingEnergy(0, -1, x, y, z, t, t0, wrt_world);
1171 }
1172
1173
1174 } // namespace mirtk
1175
1176 #endif // MIRTK_MultiLevelTransformation_H
1177