Skip to content

Commit

Permalink
Merge branch 'master' into fix_tests
Browse files Browse the repository at this point in the history
  • Loading branch information
nmellado authored Jun 21, 2023
2 parents 6c4b1be + f947bf3 commit 3efbe1e
Show file tree
Hide file tree
Showing 21 changed files with 209 additions and 99 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ improved doc.
- API
- [spatialPartitioning] Add kd-tree traits type (#80)
- [fitting] Add Primitive::getNumNeighbors (#86)
- [fitting] Change naming convention and rational for principal curvatures in CurvatureEstimatorBase (#94)

- Bug-fixes and code improvements
- [spatialPartitioning] Fix unwanted function hiding with DryFit::setWeightFunc (#86)
- [spatialPartitioning] Fix missing include directive in kdTreeTraits.h (#92)
- [fitting] Fix a potential bug when using multi-pass fitting (#89)
- [fitting] Fix a bug in CovarianceFit (#93)
- [fitting] Remove deadcode in Basket (#86)
Expand All @@ -22,7 +24,7 @@ improved doc.
- Fix WeightKernel test (failing on windows due to finite differences) (#91)

-Docs
- [spatialPartitioning] Update module page with a minimal doc and examples (#86)
- [spatialPartitioning] Update module page with a minimal doc and examples (#86, #92)
- [spatialPartitioning] Add NanoFlann example (#86)

--------------------------------------------------------------------------------
Expand Down
61 changes: 28 additions & 33 deletions Ponca/src/Fitting/curvature.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ namespace Ponca
template < class DataPoint, class _WFunctor, int DiffType, typename T>
/**
*
* \brief Base class for any 3d curvature estimator: holds \f$k_1\f$, \f$k_2\f$ and associated vectors
* \brief Base class for any 3d curvature estimator: holds \f$k_{\min}\f$, \f$k_{\max}\f$ and associated vectors,
* such that \f$ k_{\min} <= k_{\max} \f$
*/
class CurvatureEstimatorBase : public T
{
Expand All @@ -30,14 +31,14 @@ namespace Ponca
};

private:
/// \brief Principal curvature with highest absolute magnitude
Scalar m_k1 {0},
/// \brief Principal curvature with smallest absolute magnitude
m_k2 {0};
/// \brief Direction associated to the principal curvature with highest absolute magnitude
VectorType m_v1 {VectorType::Zero()},
/// \brief Direction associated to the principal curvature with highest smallest magnitude
m_v2 {VectorType::Zero()};
/// \brief Minimal principal curvature
Scalar m_kmin {0},
/// \brief Maximal principal curvature
m_kmax {0};
/// \brief Direction associated to the minimal principal curvature
VectorType m_vmin {VectorType::Zero()},
/// \brief Direction associated to the maximal principal curvature
m_vmax {VectorType::Zero()};

/// \brief Internal state indicating if the curvature are set to default (false), or have been computed (true)
bool m_isValid {false};
Expand All @@ -54,38 +55,32 @@ namespace Ponca
/**************************************************************************/
/* Use results */
/**************************************************************************/
//! \brief Returns an estimate of the first principal curvature value
//!
//! It is the greatest curvature in <b>absolute value</b>.
PONCA_MULTIARCH inline Scalar k1() const { return m_k1; }

//! \brief Returns an estimate of the second principal curvature value
//!
//! It is the smallest curvature in <b>absolute value</b>.
PONCA_MULTIARCH inline Scalar k2() const { return m_k2; }

//! \brief Returns an estimate of the first principal curvature direction
//!
//! It is the greatest curvature in <b>absolute value</b>.
PONCA_MULTIARCH inline VectorType k1Direction() const { return m_v1; }

//! \brief Returns an estimate of the second principal curvature direction
//!
//! It is the smallest curvature in <b>absolute value</b>.
PONCA_MULTIARCH inline VectorType k2Direction() const { return m_v2; }
//! \brief Returns an estimate of the minimal principal curvature value
PONCA_MULTIARCH inline Scalar kmin() const { return m_kmin; }

//! \brief Returns an estimate of the maximal principal curvature value
PONCA_MULTIARCH inline Scalar kmax() const { return m_kmax; }

//! \brief Returns an estimate of the minimal principal curvature direction
PONCA_MULTIARCH inline VectorType kminDirection() const { return m_vmin; }

//! \brief Returns an estimate of the maximal principal curvature direction
PONCA_MULTIARCH inline VectorType kmaxDirection() const { return m_vmax; }

//! \brief Returns an estimate of the mean curvature
PONCA_MULTIARCH inline Scalar kMean() const { return (m_k1 + m_k2)/Scalar(2);}
PONCA_MULTIARCH inline Scalar kMean() const { return (m_kmin + m_kmax)/Scalar(2);}

//! \brief Returns an estimate of the Gaussian curvature
PONCA_MULTIARCH inline Scalar GaussianCurvature() const { return m_k1 * m_k2;}
PONCA_MULTIARCH inline Scalar GaussianCurvature() const { return m_kmin * m_kmax;}

protected:
/// \brief Set curvature values. To be called in finalize() by child classes
///
/// Principal curvatures are re-ordered depending on their magnitude,
/// such that \f$ |k_1| > |k_2| \f$
PONCA_MULTIARCH inline void setCurvatureValues(Scalar k1, Scalar k2, const VectorType& v1, const VectorType& v2);
/// If the given parameters are such that \f$ k_{\min} > k_{\max} \f$, then this
/// method swap the two curvature values and directions and store them such that
/// \f$ k_{\min} <= k_{\max} \f$.
///
PONCA_MULTIARCH inline void setCurvatureValues(Scalar kmin, Scalar kmax, const VectorType& vmin, const VectorType& vmax);
};

} //namespace Ponca
Expand Down
32 changes: 14 additions & 18 deletions Ponca/src/Fitting/curvature.hpp
Original file line number Diff line number Diff line change
@@ -1,36 +1,32 @@
#include PONCA_MULTIARCH_INCLUDE_STD(cmath) //abs

namespace Ponca {
template<class DataPoint, class _WFunctor, int DiffType, typename T>
void
CurvatureEstimatorBase<DataPoint, _WFunctor, DiffType, T>::init(const VectorType &_evalPos) {
Base::init(_evalPos);
m_k1 = 0;
m_k2 = 0;
m_v1 = VectorType::Zero();
m_v2 = VectorType::Zero();
m_kmin = 0;
m_kmax = 0;
m_vmin = VectorType::Zero();
m_vmax = VectorType::Zero();
m_isValid = false;
}


template<class DataPoint, class _WFunctor, int DiffType, typename T>
void
CurvatureEstimatorBase<DataPoint, _WFunctor, DiffType, T>::setCurvatureValues(
Scalar k1, Scalar k2, const VectorType &v1, const VectorType &v2) {
PONCA_MULTIARCH_STD_MATH(abs)

if (abs(k1) < abs(k2)) {
m_k1 = k2;
m_k2 = k1;
m_v1 = v2;
m_v2 = v1;
Scalar kmin, Scalar kmax, const VectorType &vmin, const VectorType &vmax) {
if(kmin <= kmax) {
m_kmin = kmin;
m_kmax = kmax;
m_vmin = vmin;
m_vmax = vmax;
} else {
m_k1 = k1;
m_k2 = k2;
m_v1 = v1;
m_v2 = v2;
m_kmin = kmax;
m_kmax = kmin;
m_vmin = vmax;
m_vmax = vmin;
}

m_isValid = true;
}
}
38 changes: 19 additions & 19 deletions Ponca/src/Fitting/curvatureEstimation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,35 +148,35 @@ NormalCovarianceCurvatureEstimator<DataPoint, _WFunctor, DiffType, T>::finalize

m_solver.computeDirect(m_cov);

Scalar k1 = m_solver.eigenvalues()(1);
Scalar k2 = m_solver.eigenvalues()(2);
Scalar kmin = m_solver.eigenvalues()(1);
Scalar kmax = m_solver.eigenvalues()(2);

VectorType v1 = m_solver.eigenvectors().col(1);
VectorType v2 = m_solver.eigenvectors().col(2);
VectorType vmin = m_solver.eigenvectors().col(1);
VectorType vmax = m_solver.eigenvectors().col(2);

// fallback
// TODO(thib) which epsilon value should be chosen ?
Scalar epsilon = Scalar(1e-3);
if(k1<epsilon && k2<epsilon)
if(kmin<epsilon && kmax<epsilon)
{
k1 = Scalar(0);
k2 = Scalar(0);
kmin = Scalar(0);
kmax = Scalar(0);

// set principal directions from normals center of gravity
VectorType n = m_cog.normalized();
Index i0 = -1, i1 = -1, i2 = -1;
n.rowwise().squaredNorm().minCoeff(&i0);
i1 = (i0+1)%3;
i2 = (i0+2)%3;
v1[i0] = 0;
v1[i1] = n[i2];
v1[i2] = -n[i1];
v2[i0] = n[i1]*n[i1] + n[i2]*n[i2];
v2[i1] = -n[i1]*n[i0];
v2[i2] = -n[i2]*n[i0];
vmin[i0] = 0;
vmin[i1] = n[i2];
vmin[i2] = -n[i1];
vmax[i0] = n[i1]*n[i1] + n[i2]*n[i2];
vmax[i1] = -n[i1]*n[i0];
vmax[i2] = -n[i2]*n[i0];
}

Base::setCurvatureValues(k1, k2, v1, v2);
Base::setCurvatureValues(kmin, kmax, vmin, vmax);
}
return res;
}
Expand Down Expand Up @@ -259,8 +259,8 @@ ProjectedNormalCovarianceCurvatureEstimator<DataPoint, _WFunctor, DiffType, T>::

m_solver.computeDirect(m_cov);

Base::m_k1 = m_solver.eigenvalues()(0);
Base::m_k2 = m_solver.eigenvalues()(1);
Base::m_kmin = m_solver.eigenvalues()(0);
Base::m_kmax = m_solver.eigenvalues()(1);

// transform from local plane coordinates to world coordinates
Base::m_v1 = m_tframe * m_solver.eigenvectors().col(0);
Expand All @@ -269,10 +269,10 @@ ProjectedNormalCovarianceCurvatureEstimator<DataPoint, _WFunctor, DiffType, T>::
//TODO(thib) which epsilon value should be chosen ?
// Scalar epsilon = Eigen::NumTraits<Scalar>::dummy_precision();
Scalar epsilon = Scalar(1e-3);
if(Base::m_k1<epsilon && Base::m_k2<epsilon)
if(Base::m_kmin<epsilon && Base::m_kmax<epsilon)
{
Base::m_k1 = Scalar(0);
Base::m_k2 = Scalar(0);
Base::m_kmin = Scalar(0);
Base::m_kmax = Scalar(0);

// set principal directions from fitted plane
Base::m_v2 = m_tframe.col(0);
Expand Down
2 changes: 1 addition & 1 deletion Ponca/src/Fitting/mean.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ namespace Ponca {
PROVIDES_MEAN_POSITION_DERIVATIVE, /*!< \brief Provides derivative of the mean position*/
};

/*! \brief Derivatives of the of the input points vectors */
/*! \brief Derivatives of the input points vectors */
VectorArray m_dSumP {VectorArray::Zero()};

public:
Expand Down
2 changes: 1 addition & 1 deletion Ponca/src/Fitting/orientedSphereFit.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class OrientedSphereDerImpl : public T

}; //class OrientedSphereDerImpl

/// \brief Helper alias for Plane fitting on 3D points using CovariancePlaneFitImpl
/// \brief Helper alias for Oriented Sphere fitting on 3D points using OrientedSphereDerImpl
template < class DataPoint, class _WFunctor, int DiffType, typename T>
using OrientedSphereDer =
OrientedSphereDerImpl<DataPoint, _WFunctor, DiffType,
Expand Down
2 changes: 1 addition & 1 deletion Ponca/src/SpatialPartitioning/KdTree/kdTree.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ public :
NodeContainer m_nodes;
IndexContainer m_indices;

LeafSizeType m_min_cell_size;
LeafSizeType m_min_cell_size; ///< Minimal number of points per leaf
NodeCountType m_leaf_count; ///< Number of leaves in the Kdtree (computed during construction)
};

Expand Down
3 changes: 3 additions & 0 deletions Ponca/src/SpatialPartitioning/KdTree/kdTreeTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/


#pragma once

#include <Eigen/Geometry>

namespace Ponca {
#ifndef PARSED_WITH_DOXYGEN
namespace internal
Expand Down
1 change: 1 addition & 0 deletions doc/src/example.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- \subpage example_cu_ssc_page : Calculate Screen Space Curvature using CUDA/C++.
- \subpage example_python_ssc_page : Calculate Screen Space Curvature using CUDA/Python.
- @ref spatialpartitioning "Spatial Partitioning Module"
- \subpage example_cxx_neighbor_search : Nearest, k-nearest and range neighbor searches using Ponca::KdTree.
- \subpage example_cxx_nanoflann_page : Comparison between Nanoflann and Ponca KdTree APIs.

*/
14 changes: 14 additions & 0 deletions doc/src/example_cxx_neighbor_search.mdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/


/*!
\page example_cxx_neighbor_search Ponca::KdTree neighbor searches

This is an example of how to use Ponca::KdTree to perform nearest, k-nearest and range neighbor search.

\include cpp/ponca_neighbor_search.cpp
*/
2 changes: 1 addition & 1 deletion doc/src/ponca_module_fitting.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ namespace Ponca
\note There is currently no formal description of the API provided by each capability. This will be fixed in upcoming releases.
These relations are currently implicitly defined (and used), but not documented.
For instance, a tool with the capability `PROVIDES_PRINCIPAL_CURVATURES` provides the following methods:
`k1()`, `k2()`, `k1Direction()`, `k2Direction()`, `kMean()`, `GaussianCurvature()`, see CurvatureEstimatorBase.
`kmin()`, `kmax()`, `kminDirection()`, `kmaxDirection()`, `kMean()`, `GaussianCurvature()`, see CurvatureEstimatorBase.

In order to ease tools combinations, each class declare a set of *required* and *provided* capabilities, as listed in the two following table:

Expand Down
16 changes: 15 additions & 1 deletion doc/src/ponca_module_spatialpartitioning.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,12 @@ namespace Ponca
\note As queries are objets that are independent from the KdTree, they can be created and used in parallel from
multiple threads.

\warning Queries from an index (KdTreeKNearestIndexQuery, KdTreeNearestIndexQuery and KdTreeRangeIndexQuery) do not iterate on the queried index.

\subsection spatialpartitioning_kdtree_examples Examples
KdTree usage is demonstrated both in tests and examples:

Several KdTree queries are illustrated in the example \ref example_cxx_neighbor_search.
KdTree usage is also demonstrated both in tests and examples:
- `tests/src/basket.cpp`
- `tests/src/kdtree_knearest.cpp`
- `tests/src/kdtree_nearest.cpp`
Expand All @@ -54,6 +58,16 @@ namespace Ponca
Ponca::KdTreeBase is a customizable version of Ponca::KdTree, which can be controlled using `Traits`.
See KdTreeDefaultTraits for customization API.

\subsection spatialpartitioning_kdtree_implementation Implementation details

The kd-tree is a binary search tree that
- is balanced (cuts at the median at each node)
- cuts along the dimension that extends the most at each node
- has a maximal depth (KdTreeDefaultTraits::MAX_DEPTH)
- has a minimal number of points per leaf (KdTreeBase::m_min_cell_size)
- only stores points in the leafs
- uses depth-first search with a static stack for queries
- keeps the initial order of points

<center>[\ref user_manual_page "Go back to user manual"]</center>
*/
Expand Down
8 changes: 8 additions & 0 deletions examples/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,13 @@ target_include_directories(ponca_fit_line PRIVATE ${PONCA_src_ROOT})
add_dependencies(ponca-examples ponca_fit_line)
ponca_handle_eigen_dependency(ponca_fit_line)

set(ponca_neighbor_search_SRCS
ponca_neighbor_search.cpp
)
add_executable(ponca_neighbor_search ${ponca_neighbor_search_SRCS})
target_include_directories(ponca_neighbor_search PRIVATE ${PONCA_src_ROOT})
add_dependencies(ponca-examples ponca_neighbor_search)
ponca_handle_eigen_dependency(ponca_neighbor_search)

add_subdirectory(pcl)
add_subdirectory(nanoflann)
8 changes: 4 additions & 4 deletions examples/cpp/ponca_basic_cpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,10 @@ int main()
if(fit3.isStable())
{
cout << "eigen values: "<< endl;
cout << fit3.k1() << endl;
cout << fit3.k2() << endl;
cout << fit3.kmin() << endl;
cout << fit3.kmax() << endl;
cout << "eigen vectors: "<< endl;
cout << fit3.k1Direction() << endl << endl;
cout << fit3.k2Direction() << endl;
cout << fit3.kminDirection() << endl << endl;
cout << fit3.kmaxDirection() << endl;
}
}
Loading

0 comments on commit 3efbe1e

Please sign in to comment.