00001 /* 00002 Estimates the parameters of a circle with center in the origin from a set 00003 of 2D points lying on the circle. 00004 00005 Copyright (C) 2010 - 2014 Fabian Killus, Christoph Haenisch 00006 00007 Chair of Medical Engineering (mediTEC) 00008 RWTH Aachen University 00009 Pauwelsstr. 20 00010 52074 Aachen 00011 Germany 00012 00013 Version 0.2.0 (2012-03-20) 00014 */ 00015 00021 #ifndef FIT_CIRCLE_IN_ORIGIN_HPP_9483758184 00022 #define FIT_CIRCLE_IN_ORIGIN_HPP_9483758184 00023 00024 00025 #include <cmath> 00026 #include <Eigen/Core> 00027 #include <Eigen/Dense> 00028 #include <Eigen/StdVector> 00029 #include <Eigen/SVD> 00030 #include <vector> 00031 00032 #include "ErrorObj.hpp" 00033 #include "Coordinate.hpp" 00034 #include "Fit2D.hpp" 00035 00036 00037 namespace TRTK 00038 { 00039 00040 00104 template <class T> 00105 class FitCircleInOrigin : public Fit2D<T> 00106 { 00107 private: 00108 typedef Fit2D<T> super; 00109 00110 public: 00111 EIGEN_MAKE_ALIGNED_OPERATOR_NEW 00112 00113 typedef T value_type; 00114 typedef typename super::Vector2T Vector2T; 00115 typedef typename super::Vector3T Vector3T; 00116 00117 FitCircleInOrigin(); 00118 FitCircleInOrigin(const std::vector<Coordinate<T> > & points); 00119 FitCircleInOrigin(const std::vector<Vector2T, Eigen::aligned_allocator<Vector2T> > & points); 00120 FitCircleInOrigin(const std::vector<Vector3T> & points); 00121 00122 virtual ~FitCircleInOrigin(); 00123 00124 void compute(); 00125 00126 unsigned getNumberPointsRequired() const; 00127 00128 const Coordinate<T> & getCenterPoint() const; 00129 T getDistanceTo(const Coordinate<T> & point) const; 00130 T getRadius() const; 00131 T getRMS() const; 00132 00133 using super::NOT_ENOUGH_POINTS; 00134 using super::UNKNOWN_ERROR; 00135 using super::WRONG_POINT_SIZE; 00136 00137 private: 00138 Coordinate<T> m_center_point; 00139 T m_radius; 00140 }; 00141 00142 00148 template <class T> 00149 FitCircleInOrigin<T>::FitCircleInOrigin() : 00150 m_center_point(0, 0), 00151 m_radius(0) 00152 { 00153 } 00154 00155 00164 template <class T> 00165 FitCircleInOrigin<T>::FitCircleInOrigin(const std::vector<Coordinate<T> > & points) : 00166 m_center_point(0, 0), 00167 m_radius(0) 00168 { 00169 super::setPoints(points); 00170 } 00171 00172 00180 template <class T> 00181 FitCircleInOrigin<T>::FitCircleInOrigin(const std::vector<Vector2T, Eigen::aligned_allocator<Vector2T> > & points) : 00182 m_center_point(0, 0), 00183 m_radius(0) 00184 { 00185 super::setPoints(points); 00186 } 00187 00188 00198 template <class T> 00199 FitCircleInOrigin<T>::FitCircleInOrigin(const std::vector<Vector3T> & points) : 00200 m_center_point(0, 0), 00201 m_radius(0) 00202 { 00203 super::setPoints(points); 00204 } 00205 00206 00212 template <class T> 00213 FitCircleInOrigin<T>::~FitCircleInOrigin() 00214 { 00215 } 00216 00217 00229 template <class T> 00230 void FitCircleInOrigin<T>::compute() 00231 { 00232 /* 00233 00234 Explanation of the algorithm: 00235 00236 A point (x, y) on the circle with radius R fullfills the following 00237 equation: 00238 00239 R = sqrt(x^2 + y^2) = |(x, y)| = norm((x, y)) 00240 00241 Because there are possibly more than just one known point on the circle, 00242 regard the mean value as the best fit for R. 00243 00244 */ 00245 00246 if (super::m_points.cols() == 0) 00247 { 00248 ErrorObj error; 00249 error.setClassName("FitCircleInOrigin<T>"); 00250 error.setFunctionName("compute"); 00251 error.setErrorMessage("Not enough points to fit the circle."); 00252 error.setErrorCode(NOT_ENOUGH_POINTS); 00253 throw error; 00254 } 00255 00256 00257 // Calculate radius of the circle. 00258 00259 m_radius = super::m_points.colwise().norm().mean(); 00260 } 00261 00262 00268 template <class T> 00269 const Coordinate<T> & FitCircleInOrigin<T>::getCenterPoint() const 00270 { 00271 return m_center_point; 00272 } 00273 00274 00282 template <class T> 00283 T FitCircleInOrigin<T>::getDistanceTo(const Coordinate<T> & point) const 00284 { 00285 assert(point.size() == 2); 00286 00287 using std::abs; 00288 return abs(point.norm() - m_radius); 00289 } 00290 00291 00292 template <class T> 00293 inline unsigned FitCircleInOrigin<T>::getNumberPointsRequired() const 00294 { 00295 return 1; 00296 } 00297 00298 00304 template <class T> 00305 T FitCircleInOrigin<T>::getRadius() const 00306 { 00307 return m_radius; 00308 } 00309 00310 00316 template <class T> 00317 T FitCircleInOrigin<T>::getRMS() const 00318 { 00319 using std::sqrt; 00320 00321 const int number_points = super::m_points.cols(); 00322 00323 T sum_of_squared_errors = 0.0; 00324 00325 for (int i = 0; i < number_points; ++i) 00326 { 00327 T error = m_radius - super::m_points.col(i).norm(); 00328 sum_of_squared_errors += error * error; 00329 } 00330 00331 return sqrt(sum_of_squared_errors / number_points); 00332 } 00333 00334 00335 } // namespace TRTK 00336 00337 00338 #endif // FIT_CIRCLE_IN_ORIGIN_HPP_9483758184
Documentation generated by Doxygen