MeshLib C++ Docs
Loading...
Searching...
No Matches
MRCylinderApproximator.h
Go to the documentation of this file.
1#pragma once
2
3#include "MRMeshFwd.h"
4
5#include "MRPch/MRSuppressWarning.h"
6
7MR_SUPPRESS_WARNING_PUSH
8#if defined( _MSC_VER )
9#pragma warning(disable:5054) //operator '&': deprecated between enumerations of different types
10#pragma warning(disable:4127) //C4127. "Consider using 'if constexpr' statement instead"
11#elif defined( __apple_build_version__ )
12#pragma clang diagnostic ignored "-Wdeprecated-declarations"
13#elif defined( __clang__ )
14#elif defined( __GNUC__ )
15#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
16#endif
17#include <Eigen/Eigenvalues>
18MR_SUPPRESS_WARNING_POP
19
20// https://www.geometrictools.com/Documentation/LeastSquaresFitting.pdf
21
22namespace MR
23{
24
25template <typename T>
27{
28private:
29 enum class CylinderFitterType
30 {
31 // The algorithm implimentation needs an initial approximation to refine the cylinder axis.
32 // In this option, we sort through several possible options distributed over the hemisphere.
34
35 // In this case, we assume that there is an external estimate for the cylinder axis.
36 // Therefore, we specify only the position that is given from the outside
37 SpecificAxisFit
38
39 // TODO for Meshes try to impliment specific algorithm from https://www.geometrictools.com/Documentation/LeastSquaresFitting.pdf
40 // TODO Also, an estimate of the cylinder axis can be obtained by the gravel component method or the like. But this requires additional. experiments.
41 // TODO for future try eigen vector covariance https://www.geometrictools.com/Documentation/RobustEigenSymmetric3x3.pdf
42 };
43
44 CylinderFitterType fitter_ = CylinderFitterType::HemisphereSearchFit;
45
46 // CylinderFitterType::SpecificAxisFit params
47 Eigen::Vector<T, 3> baseCylinderAxis_;
48
49 // CylinderFitterType::HemisphereSearchFit params
50 size_t thetaResolution_ = 0;
51 size_t phiResolution_ = 0;
52 bool isMultithread_ = true;
53
54 //Input data converted to Eigen format and normalized to the avgPoint position of all points in the cloud.
55 std::vector<Eigen::Vector<T, 3>> normalizedPoints_ = {};
56
57 // Precalculated values for speed up.
58 // In https://www.geometrictools.com/Documentation/LeastSquaresFitting.pdf page 35-36:
59 // Text below is a direct copy from pdf file:
60 // The sample application that used equation (94) directly was really slow.
61 // On an Intel CoreTM i7-6700 CPU at 3.40 GHz, the single - threaded version for 10765 points required 129 seconds
62 // and the multithreaded version using 8 hyperthreads required 22 seconds.The evaluation of G using the precomputed summations is much faster.
63 // The single - threaded version required 85 milliseconds and the multithreaded version using 8 hyperthreads required 22 milliseconds.
64
65 Eigen::Vector <T, 6> precomputedMu_ = {};
66 Eigen::Matrix <T, 3, 3> precomputedF0_ = {};
67 Eigen::Matrix <T, 3, 6> precomputedF1_ = {};
68 Eigen::Matrix <T, 6, 6> precomputedF2_ = {};
69
70public:
72
74
75 // Solver for CylinderFitterType::HemisphereSearchFit type
76 // thetaResolution_, phiResolution_ must be positive and as large as it posible. Price is CPU time. (~ 100 gives good results).
77 MRMESH_API T solveGeneral( const std::vector<MR::Vector3<T>>& points, Cylinder3<T>& cylinder, size_t theta = 180, size_t phi = 90, bool isMultithread = true );
78
79 // Solver for CylinderFitterType::SpecificAxisFit type
80 // Simplet way in case of we already know clinder axis
81 MRMESH_API T solveSpecificAxis( const std::vector<MR::Vector3<T>>& points, Cylinder3<T>& cylinder, MR::Vector3<T> const& cylinderAxis );
82
83private:
84 // main solver.
85 T solve( const std::vector<MR::Vector3<T>>& points, Cylinder3<T>& cylinder );
86
87 void updatePrecomputeParams( const std::vector <MR::Vector3<T>>& points, Vector3<T>& average );
88
89 // Core minimization function.
90 // Functional that needs to be minimized to obtain the optimal value of W (i.e. the cylinder axis)
91 // General definition is formula 94, but for speed up we use formula 99.
92 // https://www.geometrictools.com/Documentation/LeastSquaresFitting.pdf
93 T G( const Eigen::Vector<T, 3>& W, Eigen::Vector<T, 3>& PC, T& rsqr ) const;
94
95 T fitCylindeHemisphereSingleThreaded( Eigen::Vector<T, 3>& PC, Eigen::Vector<T, 3>& W, T& resultedRootSquare ) const;
96
97 class BestHemisphereStoredData
98 {
99 public:
100 T error = std::numeric_limits<T>::max();
101 T rootSquare = std::numeric_limits<T>::max();
102 Eigen::Vector<T, 3> W;
103 Eigen::Vector<T, 3> PC;
104 };
105
106 T fitCylindeHemisphereMultiThreaded( Eigen::Vector<T, 3>& PC, Eigen::Vector<T, 3>& W, T& resultedRootSquare ) const;
107
108 T SpecificAxisFit( Eigen::Vector<T, 3>& PC, Eigen::Vector<T, 3>& W, T& resultedRootSquare );
109};
110
111}
#define MRMESH_API
Definition MRMesh/MRMeshFwd.h:80
Definition MRCylinderApproximator.h:27
MRMESH_API T solveSpecificAxis(const std::vector< MR::Vector3< T > > &points, Cylinder3< T > &cylinder, MR::Vector3< T > const &cylinderAxis)
MRMESH_API void reset()
MRMESH_API Cylinder3Approximation()
MRMESH_API T solveGeneral(const std::vector< MR::Vector3< T > > &points, Cylinder3< T > &cylinder, size_t theta=180, size_t phi=90, bool isMultithread=true)
Definition MRCylinder3.h:12
Definition MRCameraOrientationPlugin.h:8
Definition MRMesh/MRVector3.h:28