GteContOrientedBox2.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 namespace gte
13 {
14 
15 // Compute an oriented bounding box of the points. The box center is the
16 // average of the points. The box axes are the eigenvectors of the covariance
17 // matrix.
18 template <typename Real>
19 bool GetContainer(int numPoints, Vector2<Real> const* points,
20  OrientedBox2<Real>& box);
21 
22 // Test for containment. Let X = C + y0*U0 + y1*U1 where C is the box center
23 // and U0 and U1 are the orthonormal axes of the box. X is in the box when
24 // |y_i| <= E_i for all i, where E_i are the extents of the box.
25 template <typename Real>
26 bool InContainer(Vector2<Real> const& point, OrientedBox2<Real> const& box);
27 
28 // Construct an oriented box that contains two other oriented boxes. The
29 // result is not guaranteed to be the minimum area box containing the input
30 // boxes.
31 template <typename Real>
32 bool MergeContainers(OrientedBox2<Real> const& box0,
33  OrientedBox2<Real> const& box1, OrientedBox2<Real>& merge);
34 
35 
36 template <typename Real>
37 bool GetContainer(int numPoints, Vector2<Real> const* points,
38  OrientedBox2<Real>& box)
39 {
40  // Fit the points with a Gaussian distribution.
41  ApprGaussian2<Real> fitter;
42  if (fitter.Fit(numPoints, points))
43  {
44  box = fitter.GetParameters();
45 
46  // Let C be the box center and let U0 and U1 be the box axes. Each
47  // input point is of the form X = C + y0*U0 + y1*U1. The following
48  // code computes min(y0), max(y0), min(y1), and max(y1). The box
49  // center is then adjusted to be
50  // C' = C + 0.5*(min(y0)+max(y0))*U0 + 0.5*(min(y1)+max(y1))*U1
51 
52  Vector2<Real> diff = points[0] - box.center;
53  Vector2<Real> pmin{ Dot(diff, box.axis[0]), Dot(diff, box.axis[1]) };
54  Vector2<Real> pmax = pmin;
55  for (int i = 1; i < numPoints; ++i)
56  {
57  diff = points[i] - box.center;
58  for (int j = 0; j < 2; ++j)
59  {
60  Real dot = Dot(diff, box.axis[j]);
61  if (dot < pmin[j])
62  {
63  pmin[j] = dot;
64  }
65  else if (dot > pmax[j])
66  {
67  pmax[j] = dot;
68  }
69  }
70  }
71 
72  for (int j = 0; j < 2; ++j)
73  {
74  box.center += (((Real)0.5)*(pmin[j] + pmax[j]))*box.axis[j];
75  box.extent[j] = ((Real)0.5)*(pmax[j] - pmin[j]);
76  }
77  return true;
78  }
79 
80  return false;
81 }
82 
83 template <typename Real>
84 bool InContainer(Vector2<Real> const& point, OrientedBox2<Real> const& box)
85 {
86  Vector2<Real> diff = point - box.center;
87  for (int i = 0; i < 2; ++i)
88  {
89  Real coeff = Dot(diff, box.axis[i]);
90  if (std::abs(coeff) > box.extent[i])
91  {
92  return false;
93  }
94  }
95  return true;
96 }
97 
98 template <typename Real>
100  OrientedBox2<Real> const& box1, OrientedBox2<Real>& merge)
101 {
102  // The first guess at the box center. This value will be updated later
103  // after the input box vertices are projected onto axes determined by an
104  // average of box axes.
105  merge.center = ((Real)0.5)*(box0.center + box1.center);
106 
107  // The merged box axes are the averages of the input box axes. The axes
108  // of the second box are negated, if necessary, so they form acute angles
109  // with the axes of the first box.
110  if (Dot(box0.axis[0], box1.axis[0]) >= (Real)0)
111  {
112  merge.axis[0] = ((Real)0.5)*(box0.axis[0] + box1.axis[0]);
113  }
114  else
115  {
116  merge.axis[0] = ((Real)0.5)*(box0.axis[0] - box1.axis[0]);
117  }
118  Normalize(merge.axis[0]);
119  merge.axis[1] = -Perp(merge.axis[0]);
120 
121  // Project the input box vertices onto the merged-box axes. Each axis
122  // D[i] containing the current center C has a minimum projected value
123  // min[i] and a maximum projected value max[i]. The corresponding
124  // endpoints on the axes are C+min[i]*D[i] and C+max[i]*D[i]. The point
125  // C is not necessarily the midpoint for any of the intervals. The actual
126  // box center will be adjusted from C to a point C' that is the midpoint
127  // of each interval,
128  // C' = C + sum_{i=0}^1 0.5*(min[i]+max[i])*D[i]
129  // The box extents are
130  // e[i] = 0.5*(max[i]-min[i])
131 
132  std::array<Vector2<Real>, 4> vertex;
133  Vector2<Real> pmin{ (Real)0, (Real)0 };
134  Vector2<Real> pmax{ (Real)0, (Real)0 };
135 
136  box0.GetVertices(vertex);
137  for (int i = 0; i < 4; ++i)
138  {
139  Vector2<Real> diff = vertex[i] - merge.center;
140  for (int j = 0; j < 2; ++j)
141  {
142  Real dot = Dot(diff, merge.axis[j]);
143  if (dot > pmax[j])
144  {
145  pmax[j] = dot;
146  }
147  else if (dot < pmin[j])
148  {
149  pmin[j] = dot;
150  }
151  }
152  }
153 
154  box1.GetVertices(vertex);
155  for (int i = 0; i < 4; ++i)
156  {
157  Vector2<Real> diff = vertex[i] - merge.center;
158  for (int j = 0; j < 2; ++j)
159  {
160  Real dot = Dot(diff, merge.axis[j]);
161  if (dot > pmax[j])
162  {
163  pmax[j] = dot;
164  }
165  else if (dot < pmin[j])
166  {
167  pmin[j] = dot;
168  }
169  }
170  }
171 
172  // [min,max] is the axis-aligned box in the coordinate system of the
173  // merged box axes. Update the current box center to be the center of
174  // the new box. Compute the extents based on the new center.
175  Real const half = (Real)0.5;
176  for (int j = 0; j < 2; ++j)
177  {
178  merge.center += half*(pmax[j] + pmin[j])*merge.axis[j];
179  merge.extent[j] = half*(pmax[j] - pmin[j]);
180  }
181 
182  return true;
183 }
184 
185 
186 }
std::array< Vector< N, Real >, N > axis
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
Definition: GteBSNumber.h:966
bool GetContainer(int numPoints, Vector3< Real > const *points, Capsule3< Real > &capsule)
bool Fit(int numPoints, Vector2< Real > const *points)
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)
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
Vector< N, Real > center
void GetVertices(std::array< Vector< N, Real >,(1<< N)> &vertex) const


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