1 /*
2  Copyright (C) 2014 Nicolas Mellado <nmellado0@gmail.com>
3  Copyright (C) 2015 Gael Guennebaud <gael.guennebaud@inria.fr>
4 
5  This Source Code Form is subject to the terms of the Mozilla Public
6  License, v. 2.0. If a copy of the MPL was not distributed with this
7  file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9 
10 
11 #ifndef _GRENAILLE_COVARIANCE_PLANE_FIT_
12 #define _GRENAILLE_COVARIANCE_PLANE_FIT_
13 
14 #include <Eigen/Eigenvalues>
15 #include "enums.h"
16 
17 namespace Grenaille
18 {
19 
20 /*!
21     \brief Plane fitting procedure using only points position
22 
23     \note This procedure requires two passes to fit a plane
24 
25     This class can also computes the surface variation measure introduced in
26     \cite Pauly:2002:PSSimplification. The solver used to analyse the covariance
27     matrix is stored for further use.
28 
29     \inherit Concept::FittingProcedureConcept
30 
31     \warning This class is currently untested and should not be used !
32 
33     \see CompactPlane
34 */
35 template < class DataPoint, class _WFunctor, typename T >
36 class CovariancePlaneFit : public T
37 {
38 private:
39     typedef T Base;
40 
41 protected:
42     enum
43     {
44         Check = Base::PROVIDES_PLANE
45     };
46 
47 public:
48 
49     /*! \brief Scalar type inherited from DataPoint*/
50     typedef typename Base::Scalar     Scalar;
51     /*! \brief Vector type inherited from DataPoint*/
52     typedef typename Base::VectorType VectorType;
53     /*! \brief Vector type inherited from DataPoint*/
54     typedef typename Base::MatrixType MatrixType;
55     /*! \brief Weight Function*/
56     typedef _WFunctor                 WFunctor;
57     /*! \brief Solver used to analyse the covariance matrix*/
58     typedef Eigen::SelfAdjointEigenSolver<MatrixType> Solver;
59 
60  protected:
61 
62     // computation data
63     Scalar  m_sumW;       /*!< \brief Sum of queries weight.*/
64     VectorType m_cog,     /*!< \brief Gravity center of the neighborhood */
65                m_evalPos; /*!< \brief Center of the evaluation basis */
66     MatrixType m_cov;     /*!< \brief Covariance matrix */
67 
68     Solver m_solver;  /*!<\brief Solver used to analyse the covariance matrix */
69 
70     WFunctor m_w;     /*!< \brief Weight function (must inherits BaseWeightFunc) */
71 
72 public:
73 
74     /*! \brief Default constructor */
CovariancePlaneFit()75     MULTIARCH inline CovariancePlaneFit() : Base() {}
76 
77     /**************************************************************************/
78     /* Initialization                                                         */
79     /**************************************************************************/
80     /*! \copydoc Concept::FittingProcedureConcept::setWeightFunc() */
setWeightFunc(const WFunctor & _w)81     MULTIARCH inline void setWeightFunc (const WFunctor& _w) { m_w  = _w; }
82 
83     /*! \copydoc Concept::FittingProcedureConcept::init() */
84     MULTIARCH inline void init (const VectorType& _evalPos);
85 
86     /**************************************************************************/
87     /* Processing                                                             */
88     /**************************************************************************/
89     /*! \copydoc Concept::FittingProcedureConcept::addNeighbor() */
90     MULTIARCH inline bool addNeighbor(const DataPoint &_nei);
91 
92     /*! \copydoc Concept::FittingProcedureConcept::finalize() */
93     MULTIARCH inline FIT_RESULT finalize();
94 
95     /**************************************************************************/
96     /* Results                                                                */
97     /**************************************************************************/
98 
99     using Base::potential;
100 
101     /*! \brief Value of the scalar field at the evaluation point */
potential()102     MULTIARCH inline Scalar potential() const { return Base::potential(m_evalPos); }
103 
104     /*! \brief Value of the normal of the primitive at the evaluation point */
normal()105     MULTIARCH inline VectorType normal() const { return Base::m_p.template head<DataPoint::Dim>(); }
106 
107     /*! \brief Reading access to the Solver used to analyse the covariance
108       matrix */
solver()109     MULTIARCH inline const Solver& solver() const { return m_solver; }
110 
111     /*! \brief Implements \cite Pauly:2002:PSSimplification surface variation.
112 
113         It computes the ratio \f$ d \frac{\lambda_0}{\sum_i \lambda_i} \f$ with \c d the dimension of the ambient space.
114 
115         \return 0 for invalid fits
116     */
117     MULTIARCH inline Scalar surfaceVariation() const;
118 }; //class CovariancePlaneFit
119 
120 namespace internal {
121 
122 using ::Grenaille::internal::FitSpaceDer;
123 using ::Grenaille::internal::FitScaleDer;
124 
125 /*!
126     \brief Internal generic class computing the derivatives of covariance plane fits
127     \inherit Concept::FittingExtensionConcept
128 
129     The differentiation can be done automatically in scale and/or space, by
130     combining the enum values FitScaleDer and FitSpaceDer in the template
131     parameter Type.
132 
133     The differenciated values are stored in static arrays. The size of the
134     arrays is computed with respect to the derivation type (scale and/or space)
135     and the number of the dimension of the ambiant space.
136     By convention, the scale derivatives are stored at index 0 when Type
137     contains at least FitScaleDer. The size of these arrays can be known using
138     derDimension(), and the differentiation type by isScaleDer() and
139     isSpaceDer().
140 */
141 template < class DataPoint, class _WFunctor, typename T, int Type>
142 class CovariancePlaneDer : public T
143 {
144 private:
145     typedef T Base; /*!< \brief Generic base type */
146 
147 
148 protected:
149     enum
150     {
151         Check = Base::PROVIDES_PLANE,             /*!< \brief Needs plane */
152         PROVIDES_COVARIANCE_PLANE_DERIVATIVE,      /*!< \brief Provides derivatives for hyper-planes */
153         PROVIDES_NORMAL_DERIVATIVE
154     };
155 
156     static const int NbDerivatives   = ((Type & FitScaleDer) ? 1 : 0 ) + ((Type & FitSpaceDer) ? DataPoint::Dim : 0);
157     static const int DerStorageOrder = (Type & FitSpaceDer) ? Eigen::RowMajor : Eigen::ColMajor;
158 
159 public:
160     typedef typename Base::Scalar     Scalar;     /*!< \brief Inherited scalar type*/
161     typedef typename Base::VectorType VectorType; /*!< \brief Inherited vector type*/
162     typedef typename Base::MatrixType MatrixType; /*!< \brief Inherited matrix type*/
163     typedef typename Base::WFunctor   WFunctor;   /*!< \brief Weight Function*/
164 
165     /*! \brief Static array of scalars with a size adapted to the differentiation type */
166     typedef Eigen::Matrix<Scalar, DataPoint::Dim, NbDerivatives, DerStorageOrder> VectorArray;
167 
168     /*! \brief Static array of scalars with a size adapted to the differentiation type */
169     typedef Eigen::Matrix<Scalar, 1, NbDerivatives> ScalarArray;
170 private:
171     // computation data
172     ScalarArray m_dSumW;      /*!< \brief Sum of weight derivatives */
173     MatrixType  m_dCov[NbDerivatives];
174 
175     VectorArray m_dCog;       /*!< \brief Derivatives of the centroid */
176     VectorArray m_dNormal;    /*!< \brief Derivatives of the hyper-plane normal */
177     ScalarArray m_dDist;      /*!< \brief Derivatives of the MLS scalar field */
178 
179 public:
180 
181     /************************************************************************/
182     /* Initialization                                                       */
183     /************************************************************************/
184     /*! \see Concept::FittingProcedureConcept::init() */
185     MULTIARCH void init(const VectorType &evalPos);
186 
187     /************************************************************************/
188     /* Processing                                                           */
189     /************************************************************************/
190     /*! \see Concept::FittingProcedureConcept::addNeighbor() */
191     MULTIARCH bool addNeighbor(const DataPoint  &nei);
192     /*! \see Concept::FittingProcedureConcept::finalize() */
193     MULTIARCH FIT_RESULT finalize();
194 
195 
196     /**************************************************************************/
197     /* Use results                                                            */
198     /**************************************************************************/
199 
200     /*! \brief Returns the derivatives of the scalar field at the evaluation point */
dPotential()201     MULTIARCH inline ScalarArray dPotential() const { return m_dDist; }
202 
203     /*! \brief Returns the derivatives of the primitive normal */
dNormal()204     MULTIARCH inline VectorArray dNormal() const { return m_dNormal; }
205 
206     /*! \brief State specified at compilation time to differenciate the fit in scale */
isScaleDer()207     MULTIARCH inline bool isScaleDer() const {return bool(Type & FitScaleDer);}
208     /*! \brief State specified at compilation time to differenciate the fit in space */
isSpaceDer()209     MULTIARCH inline bool isSpaceDer() const {return bool(Type & FitSpaceDer);}
210     /*! \brief Number of dimensions used for the differentiation */
derDimension()211     MULTIARCH inline unsigned int derDimension() const { return NbDerivatives;}
212 
213 }; //class CovariancePlaneDer
214 
215 }// namespace internal
216 
217 /*!
218     \brief Differentiation in scale of the CovariancePlaneFit
219     \inherit Concept::FittingExtensionConcept
220 
221     Requierement:
222     \verbatim PROVIDES_COVARIANCE_PLANE \endverbatim
223     Provide:
224     \verbatim PROVIDES_COVARIANCE_PLANE_SCALE_DERIVATIVE \endverbatim
225 */
226 template < class DataPoint, class _WFunctor, typename T>
227 class CovariancePlaneScaleDer:public internal::CovariancePlaneDer<DataPoint, _WFunctor, T, internal::FitScaleDer>
228 {
229 protected:
230     /*! \brief Inherited class */
231     typedef internal::CovariancePlaneDer<DataPoint, _WFunctor, T, internal::FitScaleDer> Base;
232     enum { PROVIDES_COVARIANCE_PLANE_SCALE_DERIVATIVE, PROVIDES_NORMAL_SCALE_DERIVATIVE };
233 };
234 
235 
236 /*!
237     \brief Spatial differentiation of the CovariancePlaneFit
238     \inherit Concept::FittingExtensionConcept
239 
240     Requierement:
241     \verbatim PROVIDES_COVARIANCE_PLANE \endverbatim
242     Provide:
243     \verbatim PROVIDES_COVARIANCE_PLANE_SPACE_DERIVATIVE \endverbatim
244 */
245 template < class DataPoint, class _WFunctor, typename T>
246 class CovariancePlaneSpaceDer:public internal::CovariancePlaneDer<DataPoint, _WFunctor, T, internal::FitSpaceDer>
247 {
248 protected:
249     /*! \brief Inherited class */
250     typedef internal::CovariancePlaneDer<DataPoint, _WFunctor, T, internal::FitSpaceDer> Base;
251     enum { PROVIDES_COVARIANCE_PLANE_SPACE_DERIVATIVE, PROVIDES_NORMAL_SPACE_DERIVATIVE };
252 };
253 
254 
255 /*!
256     \brief Differentiation both in scale and space of the CovariancePlaneFit
257     \inherit Concept::FittingExtensionConcept
258 
259     Requierement:
260     \verbatim PROVIDES_COVARIANCE_PLANE \endverbatim
261     Provide:
262     \verbatim PROVIDES_COVARIANCE_PLANE_SCALE_DERIVATIVE
263     PROVIDES_COVARIANCE_PLANE_SPACE_DERIVATIVE
264     \endverbatim
265 */
266 template < class DataPoint, class _WFunctor, typename T>
267 class CovariancePlaneScaleSpaceDer:public internal::CovariancePlaneDer<DataPoint, _WFunctor, T, internal::FitSpaceDer | internal::FitScaleDer>
268 {
269 protected:
270     /*! \brief Inherited class */
271     typedef internal::CovariancePlaneDer<DataPoint, _WFunctor, T, internal::FitSpaceDer | internal::FitScaleDer> Base;
272     enum
273     {
274         PROVIDES_COVARIANCE_PLANE_SCALE_DERIVATIVE,
275         PROVIDES_COVARIANCE_PLANE_SPACE_DERIVATIVE,
276         PROVIDES_NORMAL_SCALE_DERIVATIVE,
277         PROVIDES_NORMAL_SPACE_DERIVATIVE
278     };
279 };
280 
281 #include "covariancePlaneFit.hpp"
282 
283 } //namespace Grenaille
284 
285 #endif
286