vgl_fit_sphere_3d.h
Go to the documentation of this file.
1 // This is core/vgl/algo/vgl_fit_sphere_3d.h
2 #ifndef vgl_fit_sphere_3d_h_
3 #define vgl_fit_sphere_3d_h_
4 //:
5 // \file
6 // \brief Fits a sphere to a set of 3D points
7 // \author Joseph L. Mundy
8 // \date June 8, 2015
9 //
10 // Solve linear system as an initial condition for non-linear Levenberg Marquadt
11 // Parameters are radius and center
12 // Initial experiments (see test case) indicate that there isn't much
13 // difference between the linear algorithm and the non-linear Levenberg Marquardt
14 // algorithm. Both options are available to suit specific applications. The
15 // non-linear algorithm first does a linear fit to obtain and inital guess.
16 //
17 // \verbatim
18 // Modifications
19 // none
20 // \endverbatim
21 
22 // The linear algorithm seeks to minimize the error e = Sum|ri^2 - r^2|
23 // expanding (xi-x0)^2 + (yi-y0)^2 + (zi-z0)^2 - r^2
24 // = rho - 2(xix0 + yiy0 + ziz0) + (xi^2 + yi^2 + zi^2)
25 // where rho = (x0^2 + y0^2 + z0^2) - r^2
26 // form three matrices
27 // [ ... ] [ ... ] [x0 ]
28 // Anx4 = [ -2xix0 -2yiy0 -2ziz0 1], Bnx1 = [ -xi^2 -yi^2 -zi^2 ], P4x1 = [y0 ]
29 // [ ... ] [ ... ] [z0 ]
30 // [rho]
31 // Then solve the linear system, AP - B = 0, using SVD.
32 //
33 // For the non-linear algorithm, the residuals are ei = ri - r;
34 // The Jacobian matrix is given by,
35 //
36 // [ ... ]
37 // Jnx4 = -[(xi-x0)/ri (yi-y0)/ri (zi-z0)/ri 1]
38 // [ ... ]
39 //
40 #include <vector>
41 #include <iosfwd>
42 #include <vgl/vgl_point_3d.h>
43 #include <vgl/vgl_homg_point_3d.h>
44 #include <vgl/vgl_sphere_3d.h>
45 #ifdef _MSC_VER
46 # include <vcl_msvc_warnings.h>
47 #endif
48 
49 template <class T>
51 {
52  // Data Members--------------------------------------------------------------
53  protected:
54  std::vector<vgl_homg_point_3d<T> > points_;
57 
58  public:
59 
60  // Constructors/Initializers/Destructors-------------------------------------
61 
62  vgl_fit_sphere_3d() = default;
63 
64  vgl_fit_sphere_3d(std::vector<vgl_point_3d<T> > points);
65 
66  ~vgl_fit_sphere_3d() = default;
67 
68  // Operations---------------------------------------------------------------
69 
70  //: add a point to point set
71  void add_point(vgl_point_3d<T> const &p);
72  void add_point(const T x, const T y, const T z);
73 
74  //: clear internal data
75  void clear();
76 
77  //: fit a sphere to the stored points using a linear method
78  // returns the average distance from the points to the sphere
79  // used as an initial condition for Levenberg Marquardt
80  // error conditions are reported on outstream
81  T fit_linear(std::ostream* outstream=nullptr);
82 
83  //:fits a sphere to the stored points using a linear method
84  bool fit_linear(const T error_marg, std::ostream* outstream=nullptr);
85 
86  //:fits a sphere nonlinearly to the stored points using Levenberg Marquardt
87  // returns the average distance from the points to the sphere
88  T fit(std::ostream* outstream=nullptr, bool verbose = false);
89 
90  //:fits a sphere nonlinearly to the stored points using Levenberg Marquardt
91  bool fit(const T error_marg, std::ostream* outstream=nullptr, bool verbose = false);
92 
93 // Data Access---------------------------------------------------------------
94 
95  std::vector<vgl_point_3d<T> > get_points() const;
96 
97  //: appropriate fit function should be called first to get the sphere corresponding to the points
100 };
101 
102 #define VGL_FIT_SPHERE_3D_INSTANTIATE(T) extern "please include vgl/algo/vgl_fit_sphere_3d.hxx first"
103 
104 #endif // vgl_fit_sphere_3d_h_
point in projective 3D space
vgl_sphere_3d< T > sphere_non_lin_
T fit_linear(std::ostream *outstream=nullptr)
fit a sphere to the stored points using a linear method.
vgl_sphere_3d< T > & get_sphere_linear_fit()
appropriate fit function should be called first to get the sphere corresponding to the points.
vgl_sphere_3d< T > sphere_lin_
std::vector< vgl_point_3d< T > > get_points() const
~vgl_fit_sphere_3d()=default
vgl_fit_sphere_3d()=default
void add_point(vgl_point_3d< T > const &p)
add a point to point set.
a point in 3D nonhomogeneous space
a sphere in 3D nonhomogeneous space
T fit(std::ostream *outstream=nullptr, bool verbose=false)
fits a sphere nonlinearly to the stored points using Levenberg Marquardt.
vgl_sphere_3d< T > & get_sphere_nonlinear_fit()
std::vector< vgl_homg_point_3d< T > > points_
void clear()
clear internal data.