Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add plane Frame #79

Draft
wants to merge 15 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions Ponca/Fitting
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "src/Fitting/linePrimitive.h"
#include "src/Fitting/plane.h"
#include "src/Fitting/algebraicSphere.h"
#include "src/Fitting/localFrame.h"

// Fitting tools
#include "src/Fitting/mean.h"
Expand Down
49 changes: 12 additions & 37 deletions Ponca/src/Fitting/covariancePlaneFit.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@

#pragma once

#include "./plane.h"
#include "./primitive.h"
#include "./mean.h" // used to define CovarianceLineFit
#include "./covarianceFit.h" // use to define CovariancePlaneFit
#include "./defines.h"
#include "./mean.h" // used to define CovariancePlaneFit
#include "./plane.h" // used to define CovariancePlaneFit
#include "./localFrame.h" // used to define CovariancePlaneFit
#include "./covarianceFit.h" // used to define CovariancePlaneFit

#include <Eigen/Eigenvalues>

Expand All @@ -38,46 +39,19 @@ PONCA_FITTING_DECLARE_MATRIX_TYPE
protected:
enum
{
Check = Base::PROVIDES_PLANE &&
Base::PROVIDES_POSITION_COVARIANCE,
/*!
* \brief Expose a method worldToTangentPlane(VectorType), which turns a point
* \brief Fit the tangent plane and store it into Plane and LocalFrame which turn a point
* in ambient 3D space to the tangent plane.
* \see worldToTangentPlane
* \see tangentPlaneToWorld
* \see LocalFrame
*/
PROVIDES_TANGENT_PLANE_BASIS
};
Check = Base::PROVIDES_POSITION_COVARIANCE &&
Base::PROVIDES_LOCAL_FRAME
};

public:
PONCA_EXPLICIT_CAST_OPERATORS(CovariancePlaneFitImpl,covariancePlaneFit)
PONCA_FITTING_DECLARE_FINALIZE

/**************************************************************************/
/* Results */
/**************************************************************************/

/*!
* \brief Express a point in ambient space relatively to the tangent plane.
*
* Output vector is: [h, u, v]^T, where u, v are 2d coordinates on the plane,
* and h the height of the sample.
* \tparam ignoreTranslation must be set to true when passing vectors instead of points
* \param _q Point coordinates expressed in ambient space
* \return Point coordinates expressed in local tangent frame
*/
template <bool ignoreTranslation = false>
PONCA_MULTIARCH inline VectorType worldToTangentPlane(const VectorType &_q) const;

/*!
* \brief Transform a point from the tangent plane [h, u, v]^T to ambient space
*
* \tparam ignoreTranslation must be set to true when passing vectors instead of points
* \param _q Point coordinates expressed in local tangent frame
* \return Point coordinates expressed in ambient space
*/
template <bool ignoreTranslation = false>
PONCA_MULTIARCH inline VectorType tangentPlaneToWorld(const VectorType &_q) const;
}; //class CovariancePlaneFitImpl

/// \brief Helper alias for Plane fitting on 3D points using CovariancePlaneFitImpl
Expand All @@ -87,7 +61,8 @@ PONCA_FITTING_DECLARE_MATRIX_TYPE
CovariancePlaneFitImpl<DataPoint, _WFunctor,
CovarianceFitBase<DataPoint, _WFunctor,
MeanPosition<DataPoint, _WFunctor,
Plane<DataPoint, _WFunctor,T>>>>;
LocalFrame<DataPoint, _WFunctor,
Plane<DataPoint, _WFunctor,T>>>>>;
//! [CovariancePlaneFit Definition]

/*!
Expand Down
31 changes: 3 additions & 28 deletions Ponca/src/Fitting/covariancePlaneFit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,37 +15,12 @@ CovariancePlaneFitImpl<DataPoint, _WFunctor, T>::finalize ()
if (Base::plane().isValid()) Base::m_eCurrentState = CONFLICT_ERROR_FOUND;
Base::setPlane(Base::m_solver.eigenvectors().col(0), Base::barycenter());
}

VectorType m_u = Base::m_solver.eigenvectors().col(1);
VectorType m_v = Base::m_solver.eigenvectors().col(2);
Base::setFrameUV (m_u, m_v);
return Base::m_eCurrentState;
}

template < class DataPoint, class _WFunctor, typename T>
template <bool ignoreTranslation>
typename CovariancePlaneFitImpl<DataPoint, _WFunctor, T>::VectorType
CovariancePlaneFitImpl<DataPoint, _WFunctor, T>::worldToTangentPlane (const VectorType& _q) const
{
if (ignoreTranslation)
return Base::m_solver.eigenvectors().transpose() * _q;
else {
// apply rotation and translation to get uv coordinates
return Base::m_solver.eigenvectors().transpose() * (Base::m_w.convertToLocalBasis(_q));
}
}

template < class DataPoint, class _WFunctor, typename T>
template <bool ignoreTranslation>
typename CovariancePlaneFitImpl<DataPoint, _WFunctor, T>::VectorType
CovariancePlaneFitImpl<DataPoint, _WFunctor, T>::tangentPlaneToWorld (const VectorType& _lq) const
{
if (ignoreTranslation)
return Base::m_solver.eigenvectors().transpose().inverse() * _lq;
else {
return Base::m_solver.eigenvectors().transpose().inverse() * _lq + Base::m_w.basisCenter();
}
}



template < class DataPoint, class _WFunctor, int DiffType, typename T>
FIT_RESULT
CovariancePlaneDerImpl<DataPoint, _WFunctor, DiffType, T>::finalize()
Expand Down
112 changes: 112 additions & 0 deletions Ponca/src/Fitting/localFrame.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#pragma once

#include "./defines.h"

#include PONCA_MULTIARCH_INCLUDE_STD(cmath)
#include PONCA_MULTIARCH_INCLUDE_STD(limits)

namespace Ponca
{
/*!
\brief Class provides a local Frame

This class can be used to do base change from the global frame to a local frame described by its axis m_u and m_v.
The local frame is defined by the three vectors m_u, m_v and Base::primitiveGradient().

It could be used to do the translation/rotation of a point.

\see worldToLocalFrame
\see localFrameToWorld
*/
template < class DataPoint, class _WFunctor, typename T >
class LocalFrame : public T
{
PONCA_FITTING_DECLARE_DEFAULT_TYPES
PONCA_FITTING_DECLARE_MATRIX_TYPE

private:

// local frame
VectorType m_u;
VectorType m_v;

protected:
enum
{
PROVIDES_LOCAL_FRAME /*!< \brief Provides LocalFrame */
};

public:
PONCA_EXPLICIT_CAST_OPERATORS(LocalFrame,localFrame)

/*! \brief Set the vectors of the local frame to zero
* \param _basisCenter Center of the local frame
*/
PONCA_MULTIARCH inline void init(const VectorType& _basisCenter = VectorType::Zero())
{
Base::init(_basisCenter);
m_u = VectorType::Zero();
m_v = VectorType::Zero();
}

/*!
* \brief Return the first axis of the local frame
*/
PONCA_MULTIARCH inline const VectorType& getFrameU() const { return m_u; }

/*!
* \brief Return the second axis of the local frame
*/
PONCA_MULTIARCH inline const VectorType& getFrameV() const { return m_v; }

/*!
* \brief Set the axis of the local frame
*
* The frame will be defined by the two vectors m_u and m_v and the normal given by Base::primitiveGradient().
* At the end, we have the basis B = [Base::primitiveGradient(), _u, _v].
* \param _u First axis of the local frame
* \param _v Second axis of the local frame
*/
PONCA_MULTIARCH inline void setFrameUV(const VectorType& _u, const VectorType& _v) {
m_u = _u;
m_v = _v;
}

/*!
* \brief Given a normal vector, this function computes a local coordinate frame (orthogonal basis).
*
* It starts by generating a non-collinear vector to the normal (to ensure that the their cross product is non-zero).
* The vector, obtained via the cross product, becomes the first axis (m_u) of the frame.
* The second axis (m_v) is computed by taking the cross product between the normal and the first axis.
* At the end, we obtain the basis B = [Base::primitiveGradient(), m_u, m_v].
* \param _norm Normal vector for which the local frame will be computed.
*/
PONCA_MULTIARCH inline void computeFrameFromNormalVector(const VectorType& _norm);

/*!
* \brief Express a point in ambient space relatively to the local frame.
*
* Output vector is: [h, u, v]^T, where u, v are 2d coordinates on the plane,
* and h the height of the sample.
* \tparam ignoreTranslation must be set to true when passing vectors instead of points
* \param _q Point coordinates expressed in ambient space
* \return Point coordinates expressed in local frame
*/
template <bool ignoreTranslation = false>
PONCA_MULTIARCH inline VectorType worldToLocalFrame(const VectorType &_q) const;

/*!
* \brief Transform a point from the local frame [h, u, v]^T to ambient space
*
* \tparam ignoreTranslation must be set to true when passing vectors instead of points
* \param _q Point coordinates expressed in local frame
* \return Point coordinates expressed in ambient space
*/
template <bool ignoreTranslation = false>
PONCA_MULTIARCH inline VectorType localFrameToWorld(const VectorType &_q) const;

}; //class LocalFrame

#include "localFrame.hpp"

} // namespace Ponca
48 changes: 48 additions & 0 deletions Ponca/src/Fitting/localFrame.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
template < class DataPoint, class _WFunctor, typename T>
template <bool ignoreTranslation>
typename LocalFrame<DataPoint, _WFunctor, T>::VectorType
LocalFrame<DataPoint, _WFunctor, T>::worldToLocalFrame (const VectorType& _q) const
{
MatrixType B;
B << Base::primitiveGradient(), m_u, m_v;
if (ignoreTranslation)
return B.transpose() * _q;
else {
// apply rotation and translation to get uv coordinates
return B.transpose() * (Base::m_w.convertToLocalBasis(_q));
}
}

template < class DataPoint, class _WFunctor, typename T>
template <bool ignoreTranslation>
typename LocalFrame<DataPoint, _WFunctor, T>::VectorType
LocalFrame<DataPoint, _WFunctor, T>::localFrameToWorld (const VectorType& _lq) const
{
MatrixType B;
B << Base::primitiveGradient(), m_u, m_v;
if (ignoreTranslation)
return B * _lq;
else {
return B * _lq + Base::m_w.basisCenter();
}
}

template < class DataPoint, class _WFunctor, typename T>
void
LocalFrame<DataPoint, _WFunctor, T>::computeFrameFromNormalVector (const VectorType& _norm)
{
// Creation of the vector 'a' non-collinear to the normal vector
VectorType a;
if (std::abs(_norm.x()) > std::abs(_norm.z())) {
a = VectorType(-_norm.y(), _norm.x(), 0);
} else {
a = VectorType(0, -_norm.z(), _norm.y());
}
a.normalize();
// Creation of the two vectors of the local frame (m_u and m_v) thanks to the cross product
VectorType m_u = _norm.cross(a);
VectorType m_v = _norm.cross(m_u);
m_u.normalize();
m_v.normalize();
setFrameUV (m_u, m_v);
}
38 changes: 29 additions & 9 deletions Ponca/src/Fitting/meanPlaneFit.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,22 @@

#pragma once

#include "./plane.h"
#include "./mean.h"
#include "./defines.h"
#include "./mean.h" // used to define MeanPlaneFit
#include "./plane.h" // used to define MeanPlaneFit
#include "./localFrame.h" // used to define MeanPlaneFit


namespace Ponca
{

/*!
\brief Plane fitting procedure computing the mean position and orientation
from oriented points
\brief Plane fitting procedure computing the frame plane using mean position and normal

\inherit Concept::FittingProcedureConcept

\see Plane

\todo Add local frame computation to enable PROVIDES_TANGENT_PLANE_BASIS
\see localFrame
*/
template < class DataPoint, class _WFunctor, typename T >
class MeanPlaneFitImpl : public T
Expand All @@ -31,22 +32,39 @@ PONCA_FITTING_DECLARE_DEFAULT_TYPES
PONCA_FITTING_DECLARE_MATRIX_TYPE

protected:
enum { Check = Base::PROVIDES_MEAN_POSITION && Base::PROVIDES_MEAN_NORMAL && Base::PROVIDES_PLANE };
enum { Check = Base::PROVIDES_PLANE
&& Base::PROVIDES_MEAN_POSITION
&& Base::PROVIDES_MEAN_NORMAL
&& Base::PROVIDES_LOCAL_FRAME
};


public:
PONCA_EXPLICIT_CAST_OPERATORS(MeanPlaneFitImpl,meanPlaneFit)

/*!
* \brief This function fits the plane using mean normal and position.

* We use the localFrame class to store the frame informations.
* Given the mean normal, we can compute the frame plane.
* m_u and m_v are computed using the cross product, to ensure orthogonality.
* \see LocalFrame
* \see computeFrameFromNormalVector
*/
PONCA_FITTING_APIDOC_FINALIZE
PONCA_MULTIARCH inline FIT_RESULT finalize()
{
// handle specific configurations
if(Base::finalize() == STABLE)
{
if (Base::plane().isValid()) Base::m_eCurrentState = CONFLICT_ERROR_FOUND;
Base::setPlane(Base::m_sumN / Base::getWeightSum(), Base::barycenter());
VectorType norm = Base::m_sumN / Base::getWeightSum();
Base::setPlane(norm, Base::barycenter());
Base::computeFrameFromNormalVector(norm);
}
return Base::m_eCurrentState;
}

}; //class MeanPlaneFitImpl

/// \brief Helper alias for Plane fitting on points using MeanPlaneFitImpl
Expand All @@ -56,6 +74,8 @@ PONCA_FITTING_DECLARE_MATRIX_TYPE
MeanPlaneFitImpl<DataPoint, _WFunctor,
MeanNormal<DataPoint, _WFunctor,
MeanPosition<DataPoint, _WFunctor,
Plane<DataPoint, _WFunctor,T>>>>;
LocalFrame<DataPoint, _WFunctor,
Plane<DataPoint, _WFunctor,T>>>>>;
//! [MeanPlaneFit Definition]

} //namespace Ponca
Loading