GteApprEllipseByArcs.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 #include <vector>
12 
13 namespace gte
14 {
15 
16 // The ellipse is (x/a)^2 + (y/b)^2 = 1, but only the portion in the first
17 // quadrant (x >= 0 and y >= 0) is approximated. Generate numArcs >= 2 arcs
18 // by constructing points corresponding to the weighted averages of the
19 // curvatures at the ellipse points (a,0) and (0,b). The returned input point
20 // array has numArcs+1 elements and the returned input center and radius
21 // arrays each have numArc elements. The arc associated with points[i] and
22 // points[i+1] has center centers[i] and radius radii[i]. The algorithm
23 // is described in
24 // http://www.geometrictools.com/Documentation/ApproximateEllipse.pdf
25 //
26 // The function returns 'true' when the approximation succeeded, in which
27 // case the output arrays are nonempty. If the 'numArcs' is smaller than
28 // 2 or a == b or one of the calls to Circumscribe fails, the function
29 // returns 'false'.
30 
31 template <typename Real>
32 bool ApproximateEllipseByArcs(Real a, Real b, int numArcs,
33  std::vector<Vector2<Real>>& points, std::vector<Vector2<Real>>& centers,
34  std::vector<Real>& radii);
35 
36 
37 template <typename Real>
38 bool ApproximateEllipseByArcs(Real a, Real b, int numArcs,
39  std::vector<Vector2<Real>>& points, std::vector<Vector2<Real>>& centers,
40  std::vector<Real>& radii)
41 {
42  if (numArcs < 2 || a == b)
43  {
44  // At least 2 arcs are required. The ellipse cannot already be a
45  // circle.
46  points.clear();
47  centers.clear();
48  radii.clear();
49  return false;
50  }
51 
52  points.resize(numArcs + 1);
53  centers.resize(numArcs);
54  radii.resize(numArcs);
55 
56  // Compute intermediate ellipse quantities.
57  Real a2 = a * a, b2 = b * b, ab = a * b;
58  Real invB2mA2 = ((Real)1) / (b2 - a2);
59 
60  // Compute the endpoints of the ellipse in the first quadrant. The
61  // points are generated in counterclockwise order.
62  points[0] = { a, (Real)0 };
63  points[numArcs] = { (Real)0, b };
64 
65  // Compute the curvature at the endpoints. These are used when computing
66  // the arcs.
67  Real curv0 = a / b2;
68  Real curv1 = b / a2;
69 
70  // Select the ellipse points based on curvature properties.
71  Real invNumArcs = ((Real)1) / numArcs;
72  for (int i = 1; i < numArcs; ++i)
73  {
74  // The curvature at a new point is a weighted average of curvature
75  // at the endpoints.
76  Real weight1 = static_cast<Real>(i) * invNumArcs;
77  Real weight0 = (Real)1 - weight1;
78  Real curv = weight0 * curv0 + weight1 * curv1;
79 
80  // Compute point having this curvature.
81  Real tmp = pow(ab / curv, (Real)2 / (Real)3);
82  points[i][0] = a * sqrt(fabs((tmp - a2) * invB2mA2));
83  points[i][1] = b * sqrt(fabs((tmp - b2) * invB2mA2));
84  }
85 
86  // Compute the arc at (a,0).
87  Circle2<Real> circle;
88  Vector2<Real> const& p0 = points[0];
89  Vector2<Real> const& p1 = points[1];
90  if (!Circumscribe(Vector2<Real>{ p1[0], -p1[1] }, p0, p1, circle))
91  {
92  // This should not happen for the arc-fitting algorithm.
93  points.clear();
94  centers.clear();
95  radii.clear();
96  return false;
97  }
98  centers[0] = circle.center;
99  radii[0] = circle.radius;
100 
101  // Compute arc at (0,b).
102  int last = numArcs - 1;
103  Vector2<Real> const& pNm1 = points[last];
104  Vector2<Real> const& pN = points[numArcs];
105  if (!Circumscribe(Vector2<Real>{ -pNm1[0], pNm1[1] }, pN, pNm1, circle))
106  {
107  // This should not happen for the arc-fitting algorithm.
108  points.clear();
109  centers.clear();
110  radii.clear();
111  return false;
112  }
113 
114  centers[last] = circle.center;
115  radii[last] = circle.radius;
116 
117  // Compute arcs at intermediate points between (a,0) and (0,b).
118  for (int iM = 0, i = 1, iP = 2; i < last; ++iM, ++i, ++iP)
119  {
120  Circumscribe(points[iM], points[i], points[iP], circle);
121  centers[i] = circle.center;
122  radii[i] = circle.radius;
123  }
124  return true;
125 }
126 
127 }
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1217
GLfixed GLfixed GLint GLint GLfixed points
Definition: glext.h:4927
bool ApproximateEllipseByArcs(Real a, Real b, int numArcs, std::vector< Vector2< Real >> &points, std::vector< Vector2< Real >> &centers, std::vector< Real > &radii)
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1217
bool Circumscribe(Vector2< Real > const &v0, Vector2< Real > const &v1, Vector2< Real > const &v2, Circle2< Real > &circle)
Vector< N, Real > center


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