1 /*
2  Copyright (C) 2014 Nicolas Mellado <nmellado0@gmail.com>
3 
4  This Source Code Form is subject to the terms of the Mozilla Public
5  License, v. 2.0. If a copy of the MPL was not distributed with this
6  file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 */
8 
9 
10 #ifndef _GRENAILLE_PLANE_
11 #define _GRENAILLE_PLANE_
12 
13 #include "primitive.h" // PrimitiveBase
14 
15 namespace Grenaille
16 {
17 
18 /*!
19     \brief Implicit hyperplane defined by an homogeneous vector \f$\mathbf{p}\f$.
20 
21     In n-dimensionnal space, the plane is defined as
22     the \f$0\f$-isosurface of the scalar field
23 
24     \f$ s_\mathbf{u}(\mathbf{x}) =
25     \left[ \mathbf{x}^T \; 1 \;\right]^T \cdot \mathbf{p} \f$.
26 
27     This class uses a compact storage of n+1 scalars in n-dimensionnal space. It
28     can be sensitive to the data scale, leading to potential instabilities
29     due to round errors at large scales.
30     \todo Add standard plane storing 2n scalars (direction and center).
31 
32 
33     This primitive requires the definition of n-dimensionnal vectors
34     (VectorType) and homogeneous n-dimensionnal vectors (HVectorType) in
35     Concept::PointConcept.
36 
37     This primitive provides:
38     \verbatim PROVIDES_PLANE \endverbatim
39 
40     \note The first n-components of the plane must define a normalized vector
41 
42 */
43 template < class DataPoint, class _WFunctor, typename T = void  >
44 class CompactPlane : public PrimitiveBase<DataPoint, _WFunctor>
45 {
46 private:
47 
48     typedef PrimitiveBase<DataPoint, _WFunctor> Base;
49 
50 protected:
51 
52     enum
53     {
54         PROVIDES_PLANE /*!< \brief Provides a Plane primitive */
55     };
56 
57 public:
58 
59     /*! \brief Scalar type inherited from DataPoint */
60     typedef typename DataPoint::Scalar      Scalar;
61     /*! \brief Vector type inherited from DataPoint */
62     typedef typename DataPoint::VectorType  VectorType;
63     /*! \brief Matrix type inherited from DataPoint */
64     typedef typename DataPoint::MatrixType  MatrixType;
65     /*! \brief Homogeneous vector type inherited from DataPoint */
66     typedef typename DataPoint::HVectorType HVectorType;
67     /*! \brief Weight Function */
68     typedef _WFunctor                       WFunctor;
69 
70 // results
71 public:
72 
73     HVectorType m_p; /*!< \brief Homogeneous plane representation */
74 
75 public:
76 
77     /*! \brief Default constructor */
CompactPlane()78     MULTIARCH inline CompactPlane()
79         : Base()
80     {
81         resetPrimitive();
82     }
83 
84     /*! \brief Set the scalar field values to 0 and reset the isNormalized()
85          status */
resetPrimitive()86     MULTIARCH inline void resetPrimitive()
87     {
88         Base::resetPrimitive();
89         m_p = HVectorType::Zero();
90     }
91 
92     /* \brief Init the plane from a direction and a position
93        \param _dir Orientation of the plane
94        \param _pos Position of the plane
95     */
setPlane(const VectorType & _dir,const VectorType & _pos)96     MULTIARCH inline void setPlane (const VectorType& _dir,
97                                     const VectorType& _pos)
98     {
99         m_p.template head<DataPoint::Dim>() = _dir.normalized();
100         m_p.template tail<1>()<< -_pos.dot(m_p.template head<DataPoint::Dim>());
101     }
102 
103     //! \brief Value of the scalar field at the location \f$ \mathbf{q} \f$
potential(const VectorType & _q)104     MULTIARCH inline Scalar potential (const VectorType& _q) const
105     {
106         // Project on the normal vector and add the offset value
107         return    m_p.template head<DataPoint::Dim>().dot(_q) +
108                *( m_p.template tail<1>().data() );
109     }
110 
111     //! \brief Project a point on the plane
project(const VectorType & _q)112     MULTIARCH inline VectorType project (const VectorType& _q) const
113     {
114         // The potential is the distance from the point to the plane
115         return _q - potential(_q) * m_p.template head<DataPoint::Dim>();
116     }
117 
118     //! \brief Scalar field gradient direction at \f$ \mathbf{q}\f$
primitiveGradient(const VectorType &)119     MULTIARCH inline VectorType primitiveGradient (const VectorType&) const
120     {
121         // Uniform gradient defined only by the orientation of the plane
122         return m_p.template head<DataPoint::Dim>();
123     }
124 
125 
126 }; //class Plane
127 
128 }
129 #endif  // _GRENAILLE_PLANE_
130