GteApprCircle2.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
11 
12 // Least-squares fit of a circle to a set of points. A successful fit is
13 // indicated by the return value of 'true'. The return value is the number
14 // of iterations used. If the number is the maximum, you can either accept
15 // the result or try increasing the maximum number and calling the function
16 // again. TODO: Currently, the test for terminating the algorithm is exact
17 // (diff == (0,0)). Expose an epsilon for this?
18 //
19 // If initialCenterIsAverage is set to 'true', the initial guess for the
20 // circle center is the average of the data points. If the data points are
21 // clustered along a small arc, ApprCircle2 is very slow to converge. If
22 // initialCenterIsAverage is set to 'false', the initial guess for the
23 // circle center is computed using a least-squares estimate of the
24 // coefficients for a quadratic equation that represents a circle. This
25 // approach tends to converge rapidly.
26 
27 namespace gte
28 {
29 
30 template <typename Real>
32 {
33 public:
34  unsigned int operator()(int numPoints, Vector2<Real> const* points,
35  unsigned int maxIterations, bool initialCenterIsAverage,
36  Circle2<Real>& circle);
37 };
38 
39 
40 template <typename Real>
41 unsigned int ApprCircle2<Real>::operator()(int numPoints,
42  Vector2<Real> const* points, unsigned int maxIterations,
43  bool initialCenterIsAverage, Circle2<Real>& circle)
44 {
45  // Compute the average of the data points.
46  Vector2<Real> average = points[0];
47  for (int i = 1; i < numPoints; ++i)
48  {
49  average += points[i];
50  }
51  Real invNumPoints = ((Real)1) / static_cast<Real>(numPoints);
52  average *= invNumPoints;
53 
54  // The initial guess for the center.
55  if (initialCenterIsAverage)
56  {
57  circle.center = average;
58  }
59  else
60  {
61  ApprQuadraticCircle2<Real>()(numPoints, points, circle);
62  }
63 
64  unsigned int iteration;
65  for (iteration = 0; iteration < maxIterations; ++iteration)
66  {
67  // Update the iterates.
68  Vector2<Real> current = circle.center;
69 
70  // Compute average L, dL/da, dL/db.
71  Real lenAverage = (Real)0;
72  Vector2<Real> derLenAverage = Vector2<Real>::Zero();
73  for (int i = 0; i < numPoints; ++i)
74  {
75  Vector2<Real> diff = points[i] - circle.center;
76  Real length = Length(diff);
77  if (length >(Real)0)
78  {
79  lenAverage += length;
80  Real invLength = ((Real)1) / length;
81  derLenAverage -= invLength * diff;
82  }
83  }
84  lenAverage *= invNumPoints;
85  derLenAverage *= invNumPoints;
86 
87  circle.center = average + lenAverage * derLenAverage;
88  circle.radius = lenAverage;
89 
90  Vector2<Real> diff = circle.center - current;
91  if (diff == Vector2<Real>::Zero())
92  {
93  break;
94  }
95  }
96 
97  return ++iteration;
98 }
99 
100 
101 }
GLfixed GLfixed GLint GLint GLfixed points
Definition: glext.h:4927
static Vector Zero()
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:790
DualQuaternion< Real > Length(DualQuaternion< Real > const &d, bool robust=false)
Vector< N, Real > center
unsigned int operator()(int numPoints, Vector2< Real > const *points, unsigned int maxIterations, bool initialCenterIsAverage, Circle2< Real > &circle)


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 03:59:58