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 basket compute with ids #53

Merged
merged 10 commits into from
Dec 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
build*
*build*
.vscode
*~

Expand Down
20 changes: 17 additions & 3 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,27 @@ Ponca changelog
--------------------------------------------------------------------------------
Current head (v.0.2.1 RC)
- API
- [spatialpartitioning] Remove duplicated code and clean API (#32)
- [core][fitting] Add Line primitive and LeastSquaresLineFitting (#39)
- [core][fitting] Rename several classes for better name consistency (#42)
- [spatialpartitioning] Remove duplicated code and clean API (#32,#51)
- [spatialpartitioning] Fix a bug in range queries (#46)
- [fitting] Add Line primitive and LeastSquaresLineFitting (#39)
- [fitting] Rename several classes for better name consistency (#42)
- [fitting] Add DryFit: a dummy fit object useful for debugging or monitoring (#52, #53)
- [fitting] Improve convenience functions for basket: add compute(Range) and
computeWithIds, which can be directly interfaced with kdtree queries (#53)
- [fitting] Fix too sensitive AlgebraicSphere comparison (#53)

- Tests
- [spatialpartitioning] Fix wrong test macro in kdtree tests (#46)
- [fitting] Fix bug in basket test (#51)
- [fitting] Disable test on windows when using long doubles (#53)

- Dependencies
- [eigen] Update default version to 3.4 (#53)

- Doc
- Rewrite documentation of the fitting package user manual and its classes. (#42)
- Fix typo in user manual (#34)
- Fix broken speed/quality comparisons for curvature estiators (#53)
- Fix Mathjax configuration (#41)
- Update author list (#42)

Expand Down
14 changes: 7 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,14 @@ endif()
## Dependencies
################################################################################

find_package(Eigen3 QUIET)
find_package(Eigen3 3.4 QUIET)
if( NOT Eigen3_FOUND )
message(WARNING "Cannot find Eigen, use submodule (disable transitive linking)")
message(STATUS "Cannot find Eigen, use submodule (disable transitive linking)")

if( NOT EXISTS ${EIGEN_SUBMODULE_ROOT_PATH}/signature_of_eigen3_matrix_library )
execute_process(COMMAND git submodule update --init -- ${EIGEN_SUBMODULE_ROOT_PATH}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
endif()

get_directory_property(hasParent PARENT_DIRECTORY)
if(hasParent)
Expand All @@ -66,11 +71,6 @@ if( NOT Eigen3_FOUND )
else()
set(EIGEN3_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/external/eigen")
endif()

if( NOT EXISTS ${EIGEN_SUBMODULE_ROOT_PATH}/signature_of_eigen3_matrix_library )
execute_process(COMMAND git submodule update --init -- ${EIGEN_SUBMODULE_ROOT_PATH}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
endif()
include_directories(${EIGEN3_INCLUDE_DIRS})
endif()

Expand Down
9 changes: 6 additions & 3 deletions Ponca/src/Fitting/algebraicSphere.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,12 @@ class AlgebraicSphere : public PrimitiveBase<DataPoint, _WFunctor>
}

PONCA_MULTIARCH inline bool operator==(const AlgebraicSphere<DataPoint, WFunctor, T>& other) const{
return m_uc == other.m_uc &&
m_uq == other.m_uq &&
m_ul == other.m_ul;
PONCA_MULTIARCH_STD_MATH(pow);
const Scalar epsilon = Eigen::NumTraits<Scalar>::dummy_precision();
const Scalar squaredEpsilon = epsilon*epsilon;
return pow(m_uc - other.m_uc, Scalar(2)) < squaredEpsilon &&
pow(m_uq - other.m_uq, Scalar(2)) < squaredEpsilon &&
m_ul.isApprox(other.m_ul);
}

/*! \brief Comparison operator, convenience function */
Expand Down
27 changes: 26 additions & 1 deletion Ponca/src/Fitting/basket.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ namespace internal
*
* Add neighbors stored in a container using STL-like iterators, and
* call finalize at the end.
* The fit is evaluated multiple time if needed (see NEED_OTHER_PASS).
*/
template <typename IteratorBegin, typename IteratorEnd>
PONCA_MULTIARCH inline
Expand All @@ -71,7 +72,31 @@ namespace internal
return res;
}

#ifndef PONCA_CPU_ARCH
/*!
* \brief Convenience function for STL-like iterators
*
* Add neighbors stored in a PointContainer and sampled using
* indices stored in ids.
*
* \tparam IndexRange STL-Like range storing indices of the neighbors
* \tparam PointContainer STL-like container storing the points
*
* \see #compute(const IteratorBegin& begin, const IteratorEnd& end)
*/
template <typename IndexRange, typename PointContainer>
PONCA_MULTIARCH inline
FIT_RESULT computeWithIds(IndexRange ids, const PointContainer& points){
FIT_RESULT res = UNDEFINED;
do {
for (const auto& i : ids){
this->addNeighbor(points[i]);
}
res = this->finalize();
} while ( res == NEED_OTHER_PASS );
return res;
}

#ifdef PONCA_CPU_ARCH
/*!
* \brief Convenience function for STL-like containers
*
Expand Down
3 changes: 2 additions & 1 deletion cmake/PoncaConfigureFitting.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ set(ponca_Fitting_INCLUDE
"${PONCA_src_ROOT}/Ponca/src/Fitting/curvatureEstimation.hpp"
"${PONCA_src_ROOT}/Ponca/src/Fitting/curvature.h"
"${PONCA_src_ROOT}/Ponca/src/Fitting/curvature.hpp"
"${PONCA_src_ROOT}/Ponca/src/Fitting/dryFit.h"
"${PONCA_src_ROOT}/Ponca/src/Fitting/enums.h"
"${PONCA_src_ROOT}/Ponca/src/Fitting/gls.h"
"${PONCA_src_ROOT}/Ponca/src/Fitting/gls.hpp"
Expand Down Expand Up @@ -51,7 +52,7 @@ set_target_properties(Fitting PROPERTIES
)

if(Eigen3_FOUND)
message("Compiling with installed Eigen package, enable transitive linking")
message("Compiling with installed Eigen package, enable transitive linking (Version ${Eigen3_VERSION}, path: ${Eigen3_DIR})")
target_link_libraries(Fitting PUBLIC INTERFACE Eigen3::Eigen)
endif()

Expand Down
22 changes: 15 additions & 7 deletions doc/src/ponca_module_fitting.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,17 @@ namespace Ponca
Once all neighbors have been incorporated, the fit is performed and results stored in the specialized Basket object.
STL-like iterators can be used directly for the fit by calling
\code
fit.compute(vecs.begin(), vecs.end());
fit.compute(vecs);
\endcode

Spatial structures can be used to accelerate spatial queries. Consider for instance using the KdTree class with range queries:
\code
fit.init(p); // Set the evaluation position
fit.setWeightFunc(WeightFunc(t)); // Set a weighting function instance
fit3.computeWithIds( tree.range_neighbors(p, t), vecs );
\endcode
Note: Currently, users need to ensure consistency between the query and the fit location/scale. This is expected to be fixed in the upcoming releases.

Internally, the container is traversed and the method `finalize` is called at the end:
\code
for(auto& it = vecs.begin(); it != vecs.end(); it++)
Expand Down Expand Up @@ -255,12 +263,12 @@ namespace Ponca
Ponca offers several ways to compute curvatures, some of which are reviewed and compared by Lejemble et al. in \cite Lejemble:2021:stable and listed in the table below:
Estimator Name | Estimated quantities | Usage | Speed | Robustness |
-------------------------------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------- | ------ | ----------- |
Distance to PCA plane \cite Digne:2011:scalespacemeshing | Mean curvature | `Basket<P,W,CovariancePlaneFit> // method potential()` | +++ | - - - |
Surface Variation \cite Pauly:2002:PSSimplification | Mean curvature | `Basket<P,W,CovariancePlaneFit> // method surfaceVariation()` | +++ | - - - |
Growing Least Squares \cite Mellado:2012:GLS | Mean curvature | `Basket<P,W,OrientedSphereFit,GLSParam> // method kappa()` | +++ | - - - |
Point Set Surfaces (PSS) \cite Alexa:2001:Pss | Curvature Tensor | `Basket<P,W,CovariancePlaneFit,CovariancePlaneSpaceDer,CurvatureEstimator>` | | |
Algebraic Point Set Surfaces (APSS) \cite Guennebaud:2007:APSS | Curvature Tensor | `Basket<P,W,OrientedSphereFit,OrientedSphereSpaceDer,CurvatureEstimator>` | | |
Algebraic Shape Operator (ASO) \cite Lejemble:2021:stable | Curvature Tensor | `Basket<P,W,OrientedSphereFit,OrientedSphereSpaceDer,MlsSphereFitDer,CurvatureEstimator>` | | |
Distance to PCA plane \cite Digne:2011:scalespacemeshing | Mean curvature | `Basket<P,W,CovariancePlaneFit> // method potential()` | +++ | - |
Surface Variation \cite Pauly:2002:PSSimplification | Mean curvature | `Basket<P,W,CovariancePlaneFit> // method surfaceVariation()` | +++ | - |
Growing Least Squares \cite Mellado:2012:GLS | Mean curvature | `Basket<P,W,OrientedSphereFit,GLSParam> // method kappa()` | ++ | + + |
Point Set Surfaces (PSS) \cite Alexa:2001:Pss | Curvature Tensor | `Basket<P,W,CovariancePlaneFit,CovariancePlaneSpaceDer,CurvatureEstimator>` | +++ | + |
Algebraic Point Set Surfaces (APSS) \cite Guennebaud:2007:APSS | Curvature Tensor | `Basket<P,W,OrientedSphereFit,OrientedSphereSpaceDer,CurvatureEstimator>` | ++ | + + |
Algebraic Shape Operator (ASO) \cite Lejemble:2021:stable | Curvature Tensor | `Basket<P,W,OrientedSphereFit,OrientedSphereSpaceDer,MlsSphereFitDer,CurvatureEstimator>` | + | + + + |


\image html buste.png "Figure 3. Example of mean curvature (GLSParam::kappa) computed at a fine (left) and a coarse (right) scale, and rendered with a simple color map (orange for concavities, blue for convexities)."
Expand Down
2 changes: 1 addition & 1 deletion external/eigen
Submodule eigen updated from 776960 to 314739
16 changes: 8 additions & 8 deletions tests/common/testUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ class PointPositionNormal
public:
enum {Dim = _Dim};
typedef _Scalar Scalar;
typedef Eigen::Matrix<Scalar, Dim, 1, Eigen::DontAlign> VectorType;
typedef Eigen::Matrix<Scalar, Dim+1, 1, Eigen::DontAlign> HVectorType;
typedef Eigen::Matrix<Scalar, Dim, Dim, Eigen::DontAlign> MatrixType;
typedef Eigen::Quaternion<Scalar, Eigen::DontAlign> QuaternionType;
typedef Eigen::Matrix<Scalar, Dim, 1> VectorType;
typedef Eigen::Matrix<Scalar, Dim+1, 1> HVectorType;
typedef Eigen::Matrix<Scalar, Dim, Dim> MatrixType;
typedef Eigen::Quaternion<Scalar> QuaternionType;

PONCA_MULTIARCH inline PointPositionNormal( const VectorType &pos = VectorType::Zero(),
const VectorType& normal = VectorType::Zero()
Expand All @@ -75,10 +75,10 @@ class PointPosition
public:
enum {Dim = _Dim};
typedef _Scalar Scalar;
typedef Eigen::Matrix<Scalar, Dim, 1, Eigen::DontAlign> VectorType;
typedef Eigen::Matrix<Scalar, Dim+1, 1, Eigen::DontAlign> HVectorType;
typedef Eigen::Matrix<Scalar, Dim, Dim, Eigen::DontAlign> MatrixType;
typedef Eigen::Quaternion<Scalar, Eigen::DontAlign> QuaternionType;
typedef Eigen::Matrix<Scalar, Dim, 1> VectorType;
typedef Eigen::Matrix<Scalar, Dim+1, 1> HVectorType;
typedef Eigen::Matrix<Scalar, Dim, Dim> MatrixType;
typedef Eigen::Quaternion<Scalar> QuaternionType;

PONCA_MULTIARCH inline PointPosition( const VectorType &pos = VectorType::Zero() )
: m_pos(pos) {}
Expand Down
2 changes: 1 addition & 1 deletion tests/src/algebraicsphere_primitive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ void testFunction()
fit.setWeightFunc(WeightFunc(analysisScale));

fit.init(vecs[k].pos());
fit.compute(vecs.cbegin(), vecs.cend());
fit.compute(vecs);

if(fit.isStable())
{
Expand Down
27 changes: 25 additions & 2 deletions tests/src/basket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <Ponca/src/Fitting/covariancePlaneFit.h>
#include <Ponca/src/Fitting/weightFunc.h>
#include <Ponca/src/Fitting/weightKernel.h>
#include <Ponca/src/SpatialPartitioning/KdTree/kdTree.h>

#include <vector>

Expand Down Expand Up @@ -48,7 +49,9 @@ void testFunction()
vectorPoints[i] = getPointOnSphere<DataPoint>(radius, center, false, false, false);
}

// Test for each point if the fitted sphere correspond to the theorical sphere
KdTree<DataPoint> tree( vectorPoints );

// Test for each point if the fitted sphere correspond to the theoretical sphere
#pragma omp parallel for
for(int i = 0; i < int(vectorPoints.size()); ++i)
{
Expand All @@ -57,7 +60,7 @@ void testFunction()
// use compute function
fit1.setWeightFunc(WeightFunc(analysisScale));
fit1.init(vectorPoints[i].pos());
fit1.compute(vectorPoints.cbegin(), vectorPoints.cend());
fit1.compute(vectorPoints);

// use addNeighbor
fit2.setWeightFunc(WeightFunc(analysisScale));
Expand All @@ -78,6 +81,20 @@ void testFunction()
VERIFY(! (fit1 != fit1));
VERIFY(! (fit1 != fit2));
VERIFY(! (fit2 != fit2));

// we skip kdtree test for float: using the kdtree changes the order of the neighbors, which in turn changes the
// rounding error accumulations, and thus the final result
if (! std::is_same<Scalar, float>::value)
{

Fit fit3;
fit3.setWeightFunc(WeightFunc(analysisScale));
fit3.init(vectorPoints[i].pos());
fit3.computeWithIds( tree.range_neighbors(vectorPoints[i].pos(), analysisScale), vectorPoints );
VERIFY(fit3 == fit3);
VERIFY(fit1 == fit3);
VERIFY(! (fit1 != fit3));
}
}
}

Expand Down Expand Up @@ -109,12 +126,18 @@ int main(int argc, char** argv)
cout << "Test Basket functions in 3 dimensions..." << endl;
callSubTests<float, 3>();
callSubTests<double, 3>();
// don't know why, but we have problems when using the kdtree with long doubles on windows
#ifndef WIN32
callSubTests<long double, 3>();
#endif
cout << "Ok..." << endl;

cout << "Test Basket functions in 4 dimensions..." << endl;
callSubTests<float, 4>();
callSubTests<double, 4>();
// don't know why, but we have problems when using the kdtree with long doubles on windows
#ifndef WIN32
callSubTests<long double, 4>();
#endif
cout << "Ok..." << endl;
}
2 changes: 1 addition & 1 deletion tests/src/curvature_plane.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ void testFunction(bool _bAddPositionNoise = false, bool _bAddNormalNoise = false
Fit fit;
fit.setWeightFunc(WeightFunc(analysisScale));
fit.init(vectorPoints[i].pos());
fit.compute(vectorPoints.cbegin(), vectorPoints.cend());
fit.compute(vectorPoints);

if( fit.isStable() ){

Expand Down
2 changes: 1 addition & 1 deletion tests/src/curvature_sphere.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ void testFunction(bool _bAddPositionNoise = false, bool _bAddNormalNoise = false
Fit fit;
fit.setWeightFunc(WeightFunc(analysisScale));
fit.init(vectorPoints[i].pos());
fit.compute(vectorPoints.cbegin(), vectorPoints.cend());
fit.compute(vectorPoints);

if( fit.isStable() )
{
Expand Down
2 changes: 1 addition & 1 deletion tests/src/deta_orthogonal_derivatives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ void test_orthoEta()
{
fit.setWeightFunc(WeightFunc(tmax));
fit.init(vecs[k].pos());
fit.compute(vecs.cbegin(), vecs.cend());
fit.compute(vecs);

if(fit.isStable())
{
Expand Down
2 changes: 1 addition & 1 deletion tests/src/dnormal_plane.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ void testFunction(bool _bAddPositionNoise = false, bool /*_bAddNormalNoise */= f
Fit fit;
fit.setWeightFunc(WeightFunc(analysisScale));
fit.init(vectorPoints[i].pos());
fit.compute(vectorPoints.cbegin(), vectorPoints.cend());
fit.compute(vectorPoints);

if(fit.isStable())
{
Expand Down
2 changes: 1 addition & 1 deletion tests/src/dnormal_sphere.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ void testFunction(bool _bAddPositionNoise = false, bool _bAddNormalNoise = false
Fit fit;
fit.setWeightFunc(WeightFunc(analysisScale));
fit.init(vectorPoints[i].pos());
fit.compute(vectorPoints.cbegin(), vectorPoints.cend());
fit.compute(vectorPoints);

if(fit.isStable())
{
Expand Down
2 changes: 1 addition & 1 deletion tests/src/dpotential_plane.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ void testFunction(bool _bAddPositionNoise = false, bool _bAddNormalNoise = false
Fit fit;
fit.setWeightFunc(WeightFunc(analysisScale));
fit.init(vectorPoints[i].pos());
fit.compute(vectorPoints.cbegin(), vectorPoints.cend());
fit.compute(vectorPoints);

if(fit.isStable())
{
Expand Down
2 changes: 1 addition & 1 deletion tests/src/dpotential_sphere.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ void testFunction(bool _bAddPositionNoise = false, bool _bAddNormalNoise = false
Fit fit;
fit.setWeightFunc(WeightFunc(analysisScale));
fit.init(vectorPoints[i].pos());
fit.compute(vectorPoints.cbegin(), vectorPoints.cend());
fit.compute(vectorPoints);

if(fit.isStable())
{
Expand Down
2 changes: 1 addition & 1 deletion tests/src/fit_line.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ void testFunction(bool _bAddPositionNoise = false)
Fit fit;
fit.setWeightFunc(WeightFunc(1));
fit.init(vectorPoints[i].pos());
fit.compute(vectorPoints.cbegin(), vectorPoints.cend());
fit.compute(vectorPoints);

VERIFY( fit.isStable() );

Expand Down
2 changes: 1 addition & 1 deletion tests/src/fit_monge_patch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ void testFunction(bool _bUnoriented = false, bool _bAddPositionNoise = false, bo
fit.setWeightFunc(WeightFunc(analysisScale));
fit.init(queryPos);

fit.compute(vectorPoints.cbegin(), vectorPoints.cend());
fit.compute(vectorPoints);

if( fit.isStable() ){

Expand Down
2 changes: 1 addition & 1 deletion tests/src/fit_plane.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ void testFunction(bool _bUnoriented = false, bool _bAddPositionNoise = false, bo
Fit fit;
fit.setWeightFunc(WeightFunc(analysisScale));
fit.init(vectorPoints[i].pos());
fit.compute(vectorPoints.cbegin(), vectorPoints.cend());
fit.compute(vectorPoints);

if( fit.isStable() ){

Expand Down
2 changes: 1 addition & 1 deletion tests/src/fit_radius_curvature_center.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ void testFunction(bool _bUnoriented = false, bool _bAddPositionNoise = false, bo
Fit fit;
fit.setWeightFunc(WeightFunc(analysisScale));
fit.init(vectorPoints[i].pos());
fit.compute(vectorPoints.cbegin(), vectorPoints.cend());
fit.compute(vectorPoints);

if(fit.isStable())
{
Expand Down
Loading