Polynomial.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_Polynomial_H
21 #define MIRTK_Polynomial_H
22 
23 #include "mirtk/Object.h"
24 
25 #include "mirtk/Assert.h"
26 #include "mirtk/Array.h"
27 #include "mirtk/Status.h"
28 #include "mirtk/Vector.h"
29 #include "mirtk/Vector3.h"
30 #include "mirtk/Matrix.h"
31 #include "mirtk/Matrix3x3.h"
32 #include "mirtk/PointSet.h"
33 #include "mirtk/OrderedSet.h"
34 
35 
36 namespace mirtk {
37 
38 
39 /**
40  * N-dimensional polynomial regression model.
41  *
42  * This implementation is based on the polyfitn and polyvaln MATLAB functions
43  * written and distributed on MathCentral by John D'Errico.
44  *
45  * \sa http://uk.mathworks.com/matlabcentral/fileexchange/34765-polyfitn
46  */
47 class Polynomial : public Object
48 {
49  mirtkObjectMacro(Polynomial);
50 
51  // ---------------------------------------------------------------------------
52  // Attributes
53 
54  /// Order of the polynomial model, i.e., the highest exponent
55  mirtkReadOnlyAttributeMacro(int, Order);
56 
57  /// Dimension of the independent variable space
58  mirtkReadOnlyAttributeMacro(int, Dimension);
59 
60  /// Exponents of the model for each independent variable
61  ///
62  /// Each column corresponds to one variable, and each
63  /// row to the exponents of each term for one variable.
64  mirtkReadOnlyAttributeMacro(Matrix, ModelTerms);
65 
66  /// Coefficients of each model term
67  mirtkReadOnlyAttributeMacro(Vector, Coefficients);
68 
69  /// Status of coefficients, only active coefficients are free
70  mirtkAttributeMacro(Array<enum Status>, Status);
71 
72  /// Copy attributes of this class from another instance
73  void CopyAttributes(const Polynomial &);
74 
75  // ---------------------------------------------------------------------------
76  // Construction/Destruction
77 public:
78 
79  /// Constructor
80  ///
81  /// \param[in] order Order of the polynomial, i.e., highest model term exponent.
82  Polynomial(int order = 2);
83 
84  /// Construct complete polynomial
85  ///
86  /// \param[in] p Dimension of independent variable space.
87  /// \param[in] order Order of the polynomial, i.e., highest model term exponent.
88  /// \param[in] coeff Coefficients of each model term. If not specified, the
89  /// coefficients are initialized to zero.
90  /// Use Coefficients(const Vector &) in this case to set the
91  /// coefficients of the model terms after model construction.
92  Polynomial(int p, int order, const Vector &coeff = Vector());
93 
94  /// Copy constructor
95  Polynomial(const Polynomial &);
96 
97  /// Assignment operator
99 
100  /// Destructor
101  virtual ~Polynomial();
102 
103  /// Build complete polynomial regression model of given order
104  ///
105  /// \param[in] p Dimension of independent variable space.
106  /// \param[in] order Order of polynomial model, i.e., highest model term exponent.
107  /// When non-positive, the current order of the model is used.
108  ///
109  /// \returns Number of model terms.
110  int Initialize(int p, int order = 0);
111 
112  /// Number of model terms/coefficients
113  int NumberOfTerms() const;
114 
115  /// Number of passive model terms/coefficients
116  int NumberOfPassiveTerms() const;
117 
118  /// Number of active model terms/coefficients
119  int NumberOfActiveTerms() const;
120 
121  /// Get exponent of independent variable in specified model term
122  ///
123  /// \param[in] i Index of model term.
124  /// \param[in] j Index of independent variable.
125  ///
126  /// \returns Exponent of j-th independent variable in i-th model term.
127  int Exponent(int i, int j = 0) const;
128 
129  /// Whether i-th term is a constant term
130  ///
131  /// \param[in] i Index of model term.
132  ///
133  /// \returns Whether all exponents of i-th term are zero.
134  bool IsConstant(int i) const;
135 
136  /// Set coefficients of polynomial model terms
137  ///
138  /// \param[in] coeff Coefficient vector of length NumberOfTerms().
139  void Coefficients(const Vector &coeff);
140 
141  /// Set coefficient of i-th term
142  ///
143  /// \param[in] i Index of model term.
144  /// \param[in] c Model term coefficient.
145  void Coefficient(int i, double c);
146 
147  /// Get coefficient of i-th term
148  ///
149  /// \param[in] i Index of model term.
150  ///
151  /// \returns Coefficient of i-th term.
152  double Coefficient(int i) const;
153 
154  /// Set status of i-th coefficient
155  ///
156  /// \param[in] i Index of coefficient.
157  /// \param[in] s Status of coefficient.
158  void Status(int i, enum Status s);
159 
160  /// Get status of i-th coefficient
161  ///
162  /// \param[in] i Index of coefficient.
163  ///
164  /// \returns Status of i-th coefficient.
165  enum Status Status(int i) const;
166 
167  /// Set all model coefficients to zero
168  void SetCoefficientsToZero();
169 
170  /// Sets coefficient(s) of constant model terms
171  ///
172  /// \param[in] value Coefficient value.
173  /// \param[in] status Status of constant model terms. Set to Passive by
174  /// default, i.e., constant terms are fixed for model fitting.
175  void SetConstantCoefficient(double value, enum Status status = Passive);
176 
177  // ---------------------------------------------------------------------------
178  // Regression
179 public:
180 
181  /// Fits polynomial regression model to one or more independent variables
182  ///
183  /// \param[in] x Values of independent variables, a matrix of size (n x p), where
184  /// n is the number of data points and
185  /// p is the dimension of the independent variable space.
186  /// \param[in] y Values of dependent variable.
187  ///
188  /// \returns RMS error of the regression.
189  double Fit(const Matrix &x, const Vector &y);
190 
191  /// Fits polynomial regression model to one or more independent variables
192  ///
193  /// \param[in] x Values of independent variables, a matrix of size (n x p), where
194  /// n is the number of data points and
195  /// p is the dimension of the independent variable space.
196  /// \param[in] subset Indices of points to use for fitting.
197  /// \param[in] y Values of dependent variable.
198  ///
199  /// \returns RMS error of the regression.
200  double Fit(const Matrix &x, const Vector &y, const Array<int> &subset);
201 
202  /// Fits polynomial regression model to one or more independent variables
203  ///
204  /// \param[in] x Values of independent variables, a matrix of size (n x p), where
205  /// n is the number of data points and
206  /// p is the dimension of the independent variable space.
207  /// \param[in] subset Indices of points to use for fitting.
208  /// \param[in] y Values of dependent variable.
209  ///
210  /// \returns RMS error of the regression.
211  double Fit(const Matrix &x, const Vector &y, const OrderedSet<int> &subset);
212 
213  /// Fits polynomial regression model to one or more independent variables
214  ///
215  /// \param[in] x Values of independent variables.
216  /// The dimension of the independent variable space is 2 or 3.
217  /// \param[in] y Values of dependent variable.
218  /// \param[in] twoD Whether to ignore z coordinate.
219  ///
220  /// \returns RMS error of the regression.
221  double Fit(const PointSet &x, const Vector &y, bool twoD = false);
222 
223  /// Fits polynomial regression model to one independent variable
224  ///
225  /// \param[in] x Values of independent variable.
226  /// \param[in] y Values of dependent variable.
227  ///
228  /// \returns RMS error of the regression.
229  double Fit(const Vector &x, const Vector &y);
230 
231  /// Fits polynomial surface model to 3D point cloud
232  ///
233  /// The dependent variable of the surface model is the algebraic distance of a
234  /// point from the surface. This function sets the coefficients of constant model
235  /// term(s) to 1 and excludes them from the fit to avoid the trivial solution
236  /// of the homogeneous linear system of equations.
237  ///
238  /// \param[in] x Points on surface.
239  ///
240  /// \returns RMS error of the regression.
241  double FitSurface(const PointSet &x);
242 
243  /// Fits polynomial surface model to subset of 3D point cloud
244  ///
245  /// The dependent variable of the surface model is the algebraic distance of a
246  /// point from the surface. This function sets the coefficients of constant model
247  /// term(s) to 1 and excludes them from the fit to avoid the trivial solution
248  /// of the homogeneous linear system of equations.
249  ///
250  /// \param[in] x Points on surface.
251  /// \param[in] subset Indices of points to use for fitting.
252  ///
253  /// \returns RMS error of the regression.
254  double FitSurface(const PointSet &x, const Array<int> &subset);
255 
256  /// Fits polynomial surface model to subset of 3D point cloud
257  ///
258  /// The dependent variable of the surface model is the algebraic distance of a
259  /// point from the surface. This function sets the coefficients of constant model
260  /// term(s) to 1 and excludes them from the fit to avoid the trivial solution
261  /// of the homogeneous linear system of equations.
262  ///
263  /// \param[in] x Points on surface.
264  /// \param[in] subset Indices of points to use for fitting.
265  ///
266  /// \returns RMS error of the regression.
267  double FitSurface(const PointSet &x, const OrderedSet<int> &subset);
268 
269  /// Fits polynomial surface model to 3D point cloud
270  ///
271  /// The dependent variable of the surface model is the algebraic distance of a
272  /// point from the surface.
273  ///
274  /// \param[in] x Points on surface.
275  /// \param[in] n Surface normals at input points.
276  /// \param[in] c Offset along normal direction for points inside and outside
277  /// the surface to be modelled.
278  ///
279  /// \returns RMS error of the regression.
280  double FitSurface(const PointSet &x, const PointSet &n, double c = 1.0);
281 
282  /// Fits polynomial surface model to subset of 3D point cloud
283  ///
284  /// The dependent variable of the surface model is the distance of a point from
285  /// the surface.
286  ///
287  /// \param[in] x Points on surface.
288  /// \param[in] n Surface normals at input points.
289  /// \param[in] subset Indices of points to use for fitting.
290  /// \param[in] c Offset along normal direction for points inside and outside
291  /// the surface to be modelled.
292  ///
293  /// \returns RMS error of the regression.
294  double FitSurface(const PointSet &x, const PointSet &n,
295  const Array<int> &subset, double c = 1.0);
296 
297  /// Fits polynomial surface model to subset of 3D point cloud
298  ///
299  /// The dependent variable of the surface model is the distance of a point from
300  /// the surface.
301  ///
302  /// \param[in] x Points on surface.
303  /// \param[in] n Surface normals at input points.
304  /// \param[in] subset Indices of points to use for fitting.
305  /// \param[in] c Offset along normal direction for points inside and outside
306  /// the surface to be modelled.
307  ///
308  /// \returns RMS error of the regression.
309  double FitSurface(const PointSet &x, const PointSet &n,
310  const OrderedSet<int> &subset, double c = 1.0);
311 
312  // ---------------------------------------------------------------------------
313  // Evaluation
314 
315  /// Evaluates polynomial for n p-dimensional data points
316  ///
317  /// \param[in] x Matrix of size (n x p), where n is the number of data points
318  /// to evaluate, and p is the dimension of the independent variable
319  /// space of the polynomial model.
320  ///
321  /// \returns Regressed value.
322  Vector Evaluate(const Matrix &x) const;
323 
324  /// Evaluates polynomial for n 2- or 3-dimensional data points
325  ///
326  /// \param[in] x Data points. The dimension of the model must be 2 or 3.
327  /// \param[in] twoD Whether to ignore z coordinate.
328  ///
329  /// \returns Regressed value.
330  Vector Evaluate(const PointSet &x, bool twoD = false) const;
331 
332  /// Evaluates polynomial for n 1-dimensional data points
333  ///
334  /// \param[in] x Values of independent variable. The dimension of the model must be 1.
335  ///
336  /// \returns Regressed values.
337  Vector Evaluate(const Vector &x) const;
338 
339  /// Evaluates polynomial for one 3D point
340  ///
341  /// \param[in] x Data point. The dimension of the model must be 2 or 3.
342  /// \param[in] twoD Whether to ignore z coordinate.
343  ///
344  /// \returns Regressed value.
345  double Evaluate(const Point &x, bool twoD = false) const;
346 
347  /// Evaluates polynomial for one 3D point
348  ///
349  /// \param[in] x First point coordinate.
350  /// \param[in] y Second point coordinate.
351  /// \param[in] z Third point coordinate.
352  ///
353  /// \returns Regressed value.
354  double Evaluate(double x, double y, double z) const;
355 
356  /// Evaluates polynomial for one 2D point
357  ///
358  /// \param[in] x First point coordinate.
359  /// \param[in] y Second point coordinate.
360  ///
361  /// \returns Regressed value.
362  double Evaluate(double x, double y) const;
363 
364  /// Evaluates polynomial for one independent variable value
365  ///
366  /// \param[in] x Data point. The dimension of the model must be 1.
367  ///
368  /// \returns Regressed value.
369  double Evaluate(double x) const;
370 
371  // ---------------------------------------------------------------------------
372  // 1st order derivatives
373 
374  /// Evaluate 1st order partial derivative of polynomial
375  ///
376  /// \param[in] j Index of independent variable w.r.t. which the derivative is taken.
377  /// \param[in] x Matrix of size (n x p), where n is the number of data points
378  /// to evaluate, and p is the dimension of the independent variable
379  /// space of the polynomial model.
380  ///
381  /// \returns Values of 1st order derivative evaluated at given data points.
382  Vector Evaluate1stOrderDerivative(int j, const Matrix &x) const;
383 
384  /// Evaluate 1st order partial derivative of polynomial
385  ///
386  /// \param[in] j Index of independent variable w.r.t. which the derivative is taken.
387  /// \param[in] x Data points. The dimension of the model must be 2 or 3.
388  /// \param[in] twoD Whether to ignore z coordinate.
389  ///
390  /// \returns Values of 1st order derivative evaluated at given data points.
391  Vector Evaluate1stOrderDerivative(int j, const PointSet &x, bool twoD = false) const;
392 
393  /// Evaluate 1st order partial derivative of polynomial
394  ///
395  /// \param[in] j Index of independent variable w.r.t. which the derivative is taken.
396  /// \param[in] x Values of independent variable. The dimension of the model must be 1.
397  ///
398  /// \returns Values of 1st order derivative evaluated at given data points.
399  Vector Evaluate1stOrderDerivative(int j, const Vector &x) const;
400 
401  /// Evaluate 1st order partial derivative of polynomial
402  ///
403  /// \param[in] j Index of independent variable w.r.t. which the derivative is taken.
404  /// \param[in] x Data point. The dimension of the model must be 2 or 3.
405  /// \param[in] twoD Whether to ignore z coordinate.
406  ///
407  /// \returns Value of 1st order derivative evaluated at given data point.
408  double Evaluate1stOrderDerivative(int j, const Point &x, bool twoD = false) const;
409 
410  /// Evaluate 1st order partial derivative of polynomial
411  ///
412  /// \param[in] j Index of independent variable w.r.t. which the derivative is taken.
413  /// \param[in] x Data point. The dimension of the model must be 1.
414  ///
415  /// \returns Value of 1st order derivative evaluated at given data point.
416  double Evaluate1stOrderDerivative(int j, double x) const;
417 
418  /// Evaluate gradient of 3D polynomial
419  ///
420  /// \param[in] x Data point. The dimension of the model must be 3.
421  ///
422  /// \returns Values of 1st order derivatives evaluated at given data point.
423  Vector3 EvaluateGradient(const Point &x) const;
424 
425  // ---------------------------------------------------------------------------
426  // 2nd order derivatives
427 
428  /// Evaluate 2nd order partial derivative of polynomial
429  ///
430  /// \param[in] x Matrix of size (n x p), where n is the number of data points
431  /// to evaluate, and p is the dimension of the independent variable
432  /// space of the polynomial model.
433  /// \param[in] j1 Index of independent variable w.r.t. which the 1st derivative is taken.
434  /// \param[in] j2 Index of independent variable w.r.t. which the 2nd derivative is taken.
435  ///
436  /// \returns Values of 2nd order derivative evaluated at given data points.
437  Vector Evaluate2ndOrderDerivative(int j1, int j2, const Matrix &x) const;
438 
439  /// Evaluate 2nd order partial derivative of polynomial
440  ///
441  /// \param[in] j1 Index of independent variable w.r.t. which the 1st derivative is taken.
442  /// \param[in] j2 Index of independent variable w.r.t. which the 2nd derivative is taken.
443  /// \param[in] x Data points. The dimension of the model must be 2 or 3.
444  /// \param[in] twoD Whether to ignore z coordinate.
445  ///
446  /// \returns Values of 2nd order derivative evaluated at given data points.
447  Vector Evaluate2ndOrderDerivative(int j1, int j2, const PointSet &x, bool twoD = false) const;
448 
449  /// Evaluate 2nd order partial derivative of polynomial
450  ///
451  /// \param[in] j1 Index of independent variable w.r.t. which the 1st derivative is taken.
452  /// \param[in] j2 Index of independent variable w.r.t. which the 2nd derivative is taken.
453  /// \param[in] x Values of independent variable. The dimension of the model must be 1.
454  ///
455  /// \returns Values of 2nd order derivative evaluated at given data points.
456  Vector Evaluate2ndOrderDerivative(int j1, int j2, const Vector &x) const;
457 
458  /// Evaluate 2nd order partial derivative of polynomial
459  ///
460  /// \param[in] j1 Index of independent variable w.r.t. which the 1st derivative is taken.
461  /// \param[in] j2 Index of independent variable w.r.t. which the 2nd derivative is taken.
462  /// \param[in] x Data point. The dimension of the model must be 2 or 3.
463  /// \param[in] twoD Whether to ignore z coordinate.
464  ///
465  /// \returns Value of 2nd order derivative evaluated at given data point.
466  double Evaluate2ndOrderDerivative(int j1, int j2, const Point &x, bool twoD = false) const;
467 
468  /// Evaluate 2nd order partial derivative of polynomial
469  ///
470  /// \param[in] j1 Index of independent variable w.r.t. which the 1st derivative is taken.
471  /// \param[in] j2 Index of independent variable w.r.t. which the 2nd derivative is taken.
472  /// \param[in] x Data point. The dimension of the model must be 1.
473  ///
474  /// \returns Value of 2nd order derivative evaluated at given data point.
475  double Evaluate2ndOrderDerivative(int j1, int j2, double x) const;
476 
477  /// Evaluate Hessian of 3D polynomial
478  ///
479  /// \param[in] x Data point. The dimension of the model must be 3.
480  ///
481  /// \returns Values of 2nd order derivatives evaluated at given data point.
482  Matrix3x3 EvaluateHessian(const Point &x) const;
483 
484  // ---------------------------------------------------------------------------
485  // Implicit surface
486 
487  /// Compute Taubin distance of a point to the implicit polynomial surface
488  ///
489  /// The Taubin distance is the agebraic distance, i.e., the value of the
490  /// implicit polynomial function at \p x, divided the norm of its gradient.
491  /// It is a first-order approximation to the Euclidean distance of the point
492  /// to the closest point on the surface.
493  ///
494  /// \param[in] x Data point. The dimension of the model must be 3.
495  ///
496  /// \returns Taubin distance of the point to the surface.
497  double EvaluateTaubinDistance(const Point &x) const;
498 
499  /// Evaluate Gaussian curvature of implicit polynomial surface
500  ///
501  /// Ron Goldman, Curvature formulas for implicit curves and surfaces,
502  /// Computer Aided Geometric Design 22 (2005) 632–658.
503  ///
504  /// \sa http://www.cgeo.ulg.ac.be/CAO/Goldman_Curvature_formulas_implicit.pdf
505  ///
506  /// \param[in] x Data point. The dimension of the model must be 3.
507  ///
508  /// \returns Gaussian curvature of implicit surface at \p x.
509  double EvaluateGaussianCurvature(const Point &x) const;
510 
511  /// Evaluate mean curvature of implicit polynomial surface
512  ///
513  /// Ron Goldman, Curvature formulas for implicit curves and surfaces,
514  /// Computer Aided Geometric Design 22 (2005) 632–658.
515  ///
516  /// \sa http://www.cgeo.ulg.ac.be/CAO/Goldman_Curvature_formulas_implicit.pdf
517  ///
518  /// \param[in] x Data point. The dimension of the model must be 3.
519  ///
520  /// \returns Mean curvature of implicit surface at \p x.
521  double EvaluateMeanCurvature(const Point &x) const;
522 
523  // ---------------------------------------------------------------------------
524  // Debugging
525 
526  /// Print polynomial model equation
527  ostream &Print(ostream &os, Indent = 0) const;
528 
529  /// Print polynomial model equation
530  void Print(Indent = 0) const;
531 
532 };
533 
534 ////////////////////////////////////////////////////////////////////////////////
535 // Inline definitions
536 ////////////////////////////////////////////////////////////////////////////////
537 
538 // =============================================================================
539 // Construction/Destruction
540 // =============================================================================
541 
542 // -----------------------------------------------------------------------------
543 inline int Polynomial::NumberOfTerms() const
544 {
545  return _ModelTerms.Rows();
546 }
547 
548 // -----------------------------------------------------------------------------
550 {
551  int n = 0;
552  for (int i = 0; i < NumberOfTerms(); ++i) {
553  if (Status(i) == Passive) ++n;
554  }
555  return n;
556 }
557 
558 // -----------------------------------------------------------------------------
560 {
561  return NumberOfTerms() - NumberOfPassiveTerms();
562 }
563 
564 // -----------------------------------------------------------------------------
565 inline int Polynomial::Exponent(int i, int j) const
566 {
567  mirtkAssert(i < NumberOfTerms(), "model term index is within bounds");
568  mirtkAssert(j < _Dimension, "variable index is within bounds");
569  return static_cast<int>(_ModelTerms(i, j));
570 }
571 
572 // -----------------------------------------------------------------------------
573 inline bool Polynomial::IsConstant(int i) const
574 {
575  mirtkAssert(i < NumberOfTerms(), "model term index is within bounds");
576  return (_ModelTerms.RowSum(i) == .0);
577 }
578 
579 // -----------------------------------------------------------------------------
580 inline void Polynomial::Coefficients(const Vector &coeff)
581 {
582  mirtkAssert(coeff.Rows() == NumberOfTerms(), "coefficient vector has element for each term");
583  _Coefficients = coeff;
584 }
585 
586 // -----------------------------------------------------------------------------
587 inline void Polynomial::Coefficient(int i, double c)
588 {
589  mirtkAssert(i < NumberOfTerms(), "model term index is within bounds");
590  _Coefficients(i) = c;
591 }
592 
593 // -----------------------------------------------------------------------------
594 inline double Polynomial::Coefficient(int i) const
595 {
596  mirtkAssert(i < NumberOfTerms(), "model term index is within bounds");
597  return _Coefficients(i);
598 }
599 
600 // -----------------------------------------------------------------------------
601 inline void Polynomial::Status(int i, enum Status s)
602 {
603  mirtkAssert(i < NumberOfTerms(), "coefficient index is within bounds");
604  _Status[i] = s;
605 }
606 
607 // -----------------------------------------------------------------------------
608 inline enum Status Polynomial::Status(int i) const
609 {
610  mirtkAssert(i < NumberOfTerms(), "coefficient index is within bounds");
611  return _Status[i];
612 }
613 
614 // -----------------------------------------------------------------------------
616 {
617  _Coefficients = .0;
618 }
619 
620 // =============================================================================
621 // Regression
622 // =============================================================================
623 
624 // -----------------------------------------------------------------------------
625 inline double Polynomial::Fit(const PointSet &x, const Vector &y, bool twoD)
626 {
627  return Fit(Matrix(x, twoD), y);
628 }
629 
630 // -----------------------------------------------------------------------------
631 inline double Polynomial::Fit(const Vector &x, const Vector &y)
632 {
633  return Fit(Matrix(x), y);
634 }
635 
636 // =============================================================================
637 // Evaluation
638 // =============================================================================
639 
640 // -----------------------------------------------------------------------------
641 inline Vector Polynomial::Evaluate(const PointSet &x, bool twoD) const
642 {
643  mirtkAssert(twoD ? _Dimension == 2 : _Dimension == 3,
644  "dimension of independent variable space must be " << (twoD ? 2 : 3));
645  return Evaluate(Matrix(x, twoD));
646 }
647 
648 // -----------------------------------------------------------------------------
649 inline Vector Polynomial::Evaluate(const Vector &x) const
650 {
651  mirtkAssert(_Dimension == 1, "dimension of independent variable space must be 1");
652  return Evaluate(Matrix(x));
653 }
654 
655 // -----------------------------------------------------------------------------
656 inline double Polynomial::Evaluate(const Point &p, bool twoD) const
657 {
658  mirtkAssert(twoD ? _Dimension == 2 : _Dimension == 3,
659  "dimension of independent variable space must be " << (twoD ? 2 : 3));
660  Matrix x(1, twoD ? 2 : 3);
661  x(0, 0) = p._x;
662  x(0, 1) = p._y;
663  if (!twoD) x(0, 2) = p._z;
664  return Evaluate(x)(0);
665 }
666 
667 // -----------------------------------------------------------------------------
668 inline double Polynomial::Evaluate(double x, double y, double z) const
669 {
670  mirtkAssert(_Dimension == 3, "dimension of independent variable space must be 3");
671  Matrix m(1, 3);
672  m(0, 0) = x;
673  m(0, 1) = y;
674  m(0, 2) = z;
675  return Evaluate(m)(0);
676 }
677 
678 // -----------------------------------------------------------------------------
679 inline double Polynomial::Evaluate(double x, double y) const
680 {
681  mirtkAssert(_Dimension == 2, "dimension of independent variable space must be 2");
682  Matrix m(1, 2);
683  m(0, 0) = x;
684  m(0, 1) = y;
685  return Evaluate(m)(0);
686 }
687 
688 // -----------------------------------------------------------------------------
689 inline double Polynomial::Evaluate(double x) const
690 {
691  mirtkAssert(_Dimension == 1, "dimension of independent variable space must be 1");
692  Matrix m(1, 1);
693  m(0, 0) = x;
694  return Evaluate(m)(0);
695 }
696 
697 // =============================================================================
698 // 1st order derivatives
699 // =============================================================================
700 
701 // -----------------------------------------------------------------------------
702 inline Vector Polynomial::Evaluate1stOrderDerivative(int j1, const PointSet &x, bool twoD) const
703 {
704  mirtkAssert(twoD ? _Dimension == 2 : _Dimension == 3,
705  "dimension of independent variable space must be " << (twoD ? 2 : 3));
706  return Evaluate1stOrderDerivative(j1, Matrix(x, twoD));
707 }
708 
709 // -----------------------------------------------------------------------------
711 {
712  mirtkAssert(_Dimension == 1, "dimension of independent variable space must be 1");
713  return Evaluate1stOrderDerivative(j1, Matrix(x));
714 }
715 
716 // -----------------------------------------------------------------------------
717 inline double Polynomial::Evaluate1stOrderDerivative(int j1, const Point &p, bool twoD) const
718 {
719  mirtkAssert(twoD ? _Dimension == 2 : _Dimension == 3,
720  "dimension of independent variable space must be " << (twoD ? 2 : 3));
721  Matrix x(1, twoD ? 2 : 3);
722  x(0, 0) = p._x;
723  x(0, 1) = p._y;
724  if (!twoD) x(0, 2) = p._z;
725  return Evaluate1stOrderDerivative(j1, x)(0);
726 }
727 
728 // -----------------------------------------------------------------------------
729 inline double Polynomial::Evaluate1stOrderDerivative(int j1, double x) const
730 {
731  mirtkAssert(_Dimension == 1, "dimension of independent variable space must be 1");
732  Matrix m(1, 1);
733  m(0, 0) = x;
734  return Evaluate1stOrderDerivative(j1, m)(0);
735 }
736 
737 // =============================================================================
738 // 2nd order derivatives
739 // =============================================================================
740 
741 // -----------------------------------------------------------------------------
742 inline Vector Polynomial::Evaluate2ndOrderDerivative(int j1, int j2, const PointSet &x, bool twoD) const
743 {
744  mirtkAssert(twoD ? _Dimension == 2 : _Dimension == 3,
745  "dimension of independent variable space must be " << (twoD ? 2 : 3));
746  return Evaluate2ndOrderDerivative(j1, j2, Matrix(x, twoD));
747 }
748 
749 // -----------------------------------------------------------------------------
750 inline Vector Polynomial::Evaluate2ndOrderDerivative(int j1, int j2, const Vector &x) const
751 {
752  mirtkAssert(_Dimension == 1, "dimension of independent variable space must be 1");
753  return Evaluate2ndOrderDerivative(j1, j2, Matrix(x));
754 }
755 
756 // -----------------------------------------------------------------------------
757 inline double Polynomial::Evaluate2ndOrderDerivative(int j1, int j2, const Point &p, bool twoD) const
758 {
759  mirtkAssert(twoD ? _Dimension == 2 : _Dimension == 3,
760  "dimension of independent variable space must be " << (twoD ? 2 : 3));
761  Matrix x(1, twoD ? 2 : 3);
762  x(0, 0) = p._x;
763  x(0, 1) = p._y;
764  if (!twoD) x(0, 2) = p._z;
765  return Evaluate2ndOrderDerivative(j1, j2, x)(0);
766 }
767 
768 // -----------------------------------------------------------------------------
769 inline double Polynomial::Evaluate2ndOrderDerivative(int j1, int j2, double x) const
770 {
771  mirtkAssert(_Dimension == 1, "dimension of independent variable space must be 1");
772  Matrix m(1, 1);
773  m(0, 0) = x;
774  return Evaluate2ndOrderDerivative(j1, j2, m)(0);
775 }
776 
777 // =============================================================================
778 // Debugging
779 // =============================================================================
780 
781 // -----------------------------------------------------------------------------
782 inline void Polynomial::Print(Indent indent) const
783 {
784  Print(cout, indent);
785 }
786 
787 
788 } // namespace mirtk
789 
790 #endif // MIRTK_Polynomial_H
double Fit(const Matrix &x, const Vector &y)
void SetConstantCoefficient(double value, enum Status status=Passive)
double FitSurface(const PointSet &x)
virtual ~Polynomial()
Destructor.
double EvaluateGaussianCurvature(const Point &x) const
double _x
x coordinate of Point
Definition: Point.h:46
double EvaluateMeanCurvature(const Point &x) const
Matrix3x3 EvaluateHessian(const Point &x) const
Vector Evaluate(const Matrix &x) const
Polynomial & operator=(const Polynomial &)
Assignment operator.
int Exponent(int i, int j=0) const
Definition: Polynomial.h:565
Vector3 EvaluateGradient(const Point &x) const
Status
Enumeration of common states for entities such as objective function parameters.
Definition: Status.h:28
Definition: IOConfig.h:41
int Rows() const
Returns number of rows.
Definition: Vector.h:438
int Dimension(vtkDataSet *)
Determine dimension of data set.
int NumberOfPassiveTerms() const
Number of passive model terms/coefficients.
Definition: Polynomial.h:549
void Coefficient(int i, double c)
Definition: Polynomial.h:587
bool IsConstant(int i) const
Definition: Polynomial.h:573
void SetCoefficientsToZero()
Set all model coefficients to zero.
Definition: Polynomial.h:615
int Initialize(int p, int order=0)
int NumberOfTerms() const
Number of model terms/coefficients.
Definition: Polynomial.h:543
Vector Evaluate1stOrderDerivative(int j, const Matrix &x) const
void Coefficients(const Vector &coeff)
Definition: Polynomial.h:580
int NumberOfActiveTerms() const
Number of active model terms/coefficients.
Definition: Polynomial.h:559
Polynomial(int order=2)
ostream & Print(ostream &os, Indent=0) const
Print polynomial model equation.
double _z
z coordinate of Point
Definition: Point.h:48
double _y
y coordinate of Point
Definition: Point.h:47
double EvaluateTaubinDistance(const Point &x) const
Vector Evaluate2ndOrderDerivative(int j1, int j2, const Matrix &x) const
void Status(int i, enum Status s)
Definition: Polynomial.h:601