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#include <MRPch/MREigenCore.h>
5
6// https://www.geometrictools.com/Documentation/LeastSquaresFitting.pdf
7
8namespace MR
9{
10
11template <typename T>
13{
14private:
15 enum class CylinderFitterType
16 {
17 // The algorithm implementation needs an initial approximation to refine the cylinder axis.
18 // In this option, we sort through several possible options distributed over the hemisphere.
20
21 // In this case, we assume that there is an external estimate for the cylinder axis.
22 // Therefore, we specify only the position that is given from the outside
23 SpecificAxisFit
24
25 // TODO for Meshes try to implement specific algorithm from https://www.geometrictools.com/Documentation/LeastSquaresFitting.pdf
26 // TODO Also, an estimate of the cylinder axis can be obtained by the gravel component method or the like. But this requires additional. experiments.
27 // TODO for future try eigen vector covariance https://www.geometrictools.com/Documentation/RobustEigenSymmetric3x3.pdf
28 };
29
30 CylinderFitterType fitter_ = CylinderFitterType::HemisphereSearchFit;
31
32 // CylinderFitterType::SpecificAxisFit params
33 Eigen::Vector<T, 3> baseCylinderAxis_;
34
35 // CylinderFitterType::HemisphereSearchFit params
36 size_t thetaResolution_ = 0;
37 size_t phiResolution_ = 0;
38 bool isMultithread_ = true;
39
40 //Input data converted to Eigen format and normalized to the avgPoint position of all points in the cloud.
41 std::vector<Eigen::Vector<T, 3>> normalizedPoints_ = {};
42
43 // Precalculated values for speed up.
44 // In https://www.geometrictools.com/Documentation/LeastSquaresFitting.pdf page 35-36:
45 // Text below is a direct copy from pdf file:
46 // The sample application that used equation (94) directly was really slow.
47 // On an Intel CoreTM i7-6700 CPU at 3.40 GHz, the single - threaded version for 10765 points required 129 seconds
48 // and the multithreaded version using 8 hyperthreads required 22 seconds.The evaluation of G using the precomputed summations is much faster.
49 // The single - threaded version required 85 milliseconds and the multithreaded version using 8 hyperthreads required 22 milliseconds.
50
51 Eigen::Vector <T, 6> precomputedMu_ = {};
52 Eigen::Matrix <T, 3, 3> precomputedF0_ = {};
53 Eigen::Matrix <T, 3, 6> precomputedF1_ = {};
54 Eigen::Matrix <T, 6, 6> precomputedF2_ = {};
55
56public:
58
60
61 // Solver for CylinderFitterType::HemisphereSearchFit type
62 // thetaResolution_, phiResolution_ must be positive and as large as it posible. Price is CPU time. (~ 100 gives good results).
63 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 );
64
65 // Solver for CylinderFitterType::SpecificAxisFit type
66 // Simplet way in case of we already know clinder axis
67 MRMESH_API T solveSpecificAxis( const std::vector<MR::Vector3<T>>& points, Cylinder3<T>& cylinder, MR::Vector3<T> const& cylinderAxis );
68
69private:
70 // main solver.
71 T solve( const std::vector<MR::Vector3<T>>& points, Cylinder3<T>& cylinder );
72
73 void updatePrecomputeParams( const std::vector <MR::Vector3<T>>& points, Vector3<T>& average );
74
75 // Core minimization function.
76 // Functional that needs to be minimized to obtain the optimal value of W (i.e. the cylinder axis)
77 // General definition is formula 94, but for speed up we use formula 99.
78 // https://www.geometrictools.com/Documentation/LeastSquaresFitting.pdf
79 T G( const Eigen::Vector<T, 3>& W, Eigen::Vector<T, 3>& PC, T& rsqr ) const;
80
81 T fitCylindeHemisphereSingleThreaded( Eigen::Vector<T, 3>& PC, Eigen::Vector<T, 3>& W, T& resultedRootSquare ) const;
82
83 class BestHemisphereStoredData
84 {
85 public:
86 T error = std::numeric_limits<T>::max();
87 T rootSquare = std::numeric_limits<T>::max();
88 Eigen::Vector<T, 3> W;
89 Eigen::Vector<T, 3> PC;
90 };
91
92 T fitCylindeHemisphereMultiThreaded( Eigen::Vector<T, 3>& PC, Eigen::Vector<T, 3>& W, T& resultedRootSquare ) const;
93
94 T SpecificAxisFit( Eigen::Vector<T, 3>& PC, Eigen::Vector<T, 3>& W, T& resultedRootSquare );
95};
96
97}
#define MRMESH_API
Definition MRMesh/MRMeshFwd.h:80
Definition MRCylinderApproximator.h:13
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:29