GteContEllipse2.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 
13 
14 namespace gte
15 {
16 
17 // The input points are fit with a Gaussian distribution. The center C of the
18 // ellipsoid is chosen to be the mean of the distribution. The axes of the
19 // ellipsoid are chosen to be the eigenvectors of the covariance matrix M.
20 // The shape of the ellipsoid is determined by the absolute values of the
21 // eigenvalues. NOTE: The construction is ill-conditioned if the points are
22 // (nearly) collinear. In this case M has a (nearly) zero eigenvalue, so
23 // inverting M can be a problem numerically.
24 template <typename Real>
25 bool GetContainer(int numPoints, Vector2<Real> const* points,
26  Ellipse2<Real>& ellipse);
27 
28 // Test for containment of a point inside an ellipse.
29 template <typename Real>
30 bool InContainer(Vector2<Real> const& point, Ellipse2<Real> const& ellipse);
31 
32 // Construct a bounding ellipse for the two input ellipses. The result is
33 // not necessarily the minimum-area ellipse containing the two ellipses.
34 template <typename Real>
35 bool MergeContainers(Ellipse2<Real> const& ellipse0,
36  Ellipse2<Real> const& ellipse1, Ellipse2<Real>& merge);
37 
38 
39 template <typename Real>
40 bool GetContainer(int numPoints, Vector2<Real> const* points,
41  Ellipse2<Real>& ellipse)
42 {
43  // Fit the points with a Gaussian distribution. The covariance matrix
44  // is M = sum_j D[j]*U[j]*U[j]^T, where D[j] are the eigenvalues and U[j]
45  // are corresponding unit-length eigenvectors.
46  ApprGaussian2<Real> fitter;
47  if (fitter.Fit(numPoints, points))
48  {
49  OrientedBox2<Real> box = fitter.GetParameters();
50 
51  // If either eigenvalue is nonpositive, adjust the D[] values so that
52  // we actually build an ellipse.
53  for (int j = 0; j < 2; ++j)
54  {
55  if (box.extent[j] < (Real)0)
56  {
57  box.extent[j] = -box.extent[j];
58  }
59  }
60 
61  // Grow the ellipse, while retaining its shape determined by the
62  // covariance matrix, to enclose all the input points. The quadratic
63  // form that is used for the ellipse construction is
64  // Q(X) = (X-C)^T*M*(X-C)
65  // = (X-C)^T*(sum_j D[j]*U[j]*U[j]^T)*(X-C)
66  // = sum_j D[j]*Dot(U[j],X-C)^2
67  // If the maximum value of Q(X[i]) for all input points is V^2, then a
68  // bounding ellipse is Q(X) = V^2, because Q(X[i]) <= V^2 for all i.
69 
70  Real maxValue = (Real)0;
71  for (int i = 0; i < numPoints; ++i)
72  {
73  Vector2<Real> diff = points[i] - box.center;
74  Real dot[2] =
75  {
76  Dot(box.axis[0], diff),
77  Dot(box.axis[1], diff)
78  };
79 
80  Real value =
81  box.extent[0] * dot[0] * dot[0] +
82  box.extent[1] * dot[1] * dot[1];
83 
84  if (value > maxValue)
85  {
86  maxValue = value;
87  }
88  }
89 
90  // Arrange for the quadratic to satisfy Q(X) <= 1.
91  ellipse.center = box.center;
92  for (int j = 0; j < 2; ++j)
93  {
94  ellipse.axis[j] = box.axis[j];
95  ellipse.extent[j] = sqrt(maxValue / box.extent[j]);
96  }
97  return true;
98 
99  }
100 
101  return false;
102 }
103 
104 template <typename Real>
105 bool InContainer(Vector2<Real> const& point, Ellipse2<Real> const& ellipse)
106 {
107  Vector2<Real> diff = point - ellipse.center;
108  Vector2<Real> standardized{
109  Dot(diff, ellipse.axis[0]) / ellipse.extent[0],
110  Dot(diff, ellipse.axis[1]) / ellipse.extent[1] };
111  return Length(standardized) <= (Real)1;
112 }
113 
114 template <typename Real>
115 bool MergeContainers(Ellipse2<Real> const& ellipse0,
116  Ellipse2<Real> const& ellipse1, Ellipse2<Real>& merge)
117 {
118  // Compute the average of the input centers.
119  merge.center = ((Real)0.5)*(ellipse0.center + ellipse1.center);
120 
121  // The bounding ellipse orientation is the average of the input
122  // orientations.
123  if (Dot(ellipse0.axis[0], ellipse1.axis[0]) >= (Real)0)
124  {
125  merge.axis[0] = ((Real)0.5)*(ellipse0.axis[0] + ellipse1.axis[0]);
126  }
127  else
128  {
129  merge.axis[0] = ((Real)0.5)*(ellipse0.axis[0] - ellipse1.axis[0]);
130  }
131  Normalize(merge.axis[0]);
132  merge.axis[1] = -Perp(merge.axis[0]);
133 
134  // Project the input ellipses onto the axes obtained by the average of the
135  // orientations and that go through the center obtained by the average of
136  // the centers.
137  for (int j = 0; j < 2; ++j)
138  {
139  // Projection axis.
140  Line2<Real> line(merge.center, merge.axis[j]);
141 
142  // Project ellipsoids onto the axis.
143  Real min0, max0, min1, max1;
144  Project(ellipse0, line, min0, max0);
145  Project(ellipse1, line, min1, max1);
146 
147  // Determine the smallest interval containing the projected
148  // intervals.
149  Real maxIntr = (max0 >= max1 ? max0 : max1);
150  Real minIntr = (min0 <= min1 ? min0 : min1);
151 
152  // Update the average center to be the center of the bounding box
153  // defined by the projected intervals.
154  merge.center += line.direction*(((Real)0.5)*(minIntr + maxIntr));
155 
156  // Compute the extents of the box based on the new center.
157  merge.extent[j] = ((Real)0.5)*(maxIntr - minIntr);
158  }
159 
160  return true;
161 }
162 
163 
164 }
std::array< Vector< N, Real >, N > axis
GVector< Real > Project(GVector< Real > const &v, int reject)
Definition: GteGVector.h:625
bool GetContainer(int numPoints, Vector3< Real > const *points, Capsule3< Real > &capsule)
bool Fit(int numPoints, Vector2< Real > const *points)
Vector< N, Real > extent
OrientedBox2< Real > const & GetParameters() const
bool MergeContainers(Capsule3< Real > const &capsule0, Capsule3< Real > const &capsule1, Capsule3< Real > &merge)
bool InContainer(Vector3< Real > const &point, Capsule3< Real > const &capsule)
GLsizei const GLfloat * value
Definition: glcorearb.h:819
Vector< N, Real > direction
Definition: GteLine.h:29
Vector< N, Real > extent
GLfixed GLfixed GLint GLint GLfixed points
Definition: glext.h:4927
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
Real Normalize(GVector< Real > &v, bool robust=false)
Definition: GteGVector.h:454
Vector2< Real > Perp(Vector2< Real > const &v)
Definition: GteVector2.h:103
DualQuaternion< Real > Length(DualQuaternion< Real > const &d, bool robust=false)
Vector< N, Real > center
Vector< N, Real > center
std::array< Vector< N, Real >, N > axis


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