GteBoxManager.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 <Mathematics/GteEdgeKey.h>
12 #include <algorithm>
13 #include <set>
14 #include <vector>
15 
16 namespace gte
17 {
18 
19 template <typename Real>
21 {
22 public:
23  // Construction.
24  BoxManager(std::vector<AlignedBox3<Real>>& boxes);
25 
26  // No default construction, copy construction, or assignment are allowed.
27  BoxManager() = delete;
28  BoxManager(BoxManager const&) = delete;
29  BoxManager& operator=(BoxManager const&) = delete;
30 
31  // This function is called by the constructor and does the sort-and-sweep
32  // to initialize the update system. However, if you add or remove items
33  // from the array of boxes after the constructor call, you will need
34  // to call this function once before you start the multiple calls of the
35  // update function.
36  void Initialize();
37 
38  // After the system is initialized, you can move the boxes using this
39  // function. It is not enough to modify the input array of boxes
40  // since the endpoint values stored internally by this class must also
41  // change. You can also retrieve the current rectangles information.
42  void SetBox(int i, AlignedBox3<Real> const& box);
43  void GetBox(int i, AlignedBox3<Real>& box) const;
44 
45  // When you are finished moving boxes, call this function to determine
46  // the overlapping boxes. An incremental update is applied to determine
47  // the new set of overlapping boxes.
48  void Update();
49 
50  // If (i,j) is in the overlap set, then box i and box j are
51  // overlapping. The indices are those for the the input array. The
52  // set elements (i,j) are stored so that i < j.
53  std::set<EdgeKey<false>> const& GetOverlap() const;
54 
55 private:
56  class Endpoint
57  {
58  public:
59  Real value; // endpoint value
60  int type; // '0' if interval min, '1' if interval max.
61  int index; // index of interval containing this endpoint
62 
63  // Support for sorting of endpoints.
64  bool operator<(Endpoint const& endpoint) const;
65  };
66 
67  void InsertionSort(std::vector<Endpoint>& endPoint, std::vector<int>& lookup);
68 
69  std::vector<AlignedBox3<Real>>& mBoxes;
70  std::vector<Endpoint> mXEndpoints, mYEndpoints, mZEndpoints;
71  std::set<EdgeKey<false>> mOverlap;
72 
73  // The intervals are indexed 0 <= i < n. The endpoint array has 2*n
74  // entries. The original 2*n interval values are ordered as b[0], e[0],
75  // b[1], e[1], ..., b[n-1], e[n-1]. When the endpoint array is sorted,
76  // the mapping between interval values and endpoints is lost. In order
77  // to modify interval values that are stored in the endpoint array, we
78  // need to maintain the mapping. This is done by the following lookup
79  // table of 2*n entries. The value mLookup[2*i] is the index of b[i]
80  // in the endpoint array. The value mLookup[2*i+1] is the index of
81  // e[i] in the endpoint array.
82  std::vector<int> mXLookup, mYLookup, mZLookup;
83 };
84 
85 template <typename Real>
87  :
88  mBoxes(boxes)
89 {
90  Initialize();
91 }
92 
93 template <typename Real>
95 {
96  // Get the box endpoints.
97  int intrSize = static_cast<int>(mBoxes.size()), endpSize = 2 * intrSize;
98  mXEndpoints.resize(endpSize);
99  mYEndpoints.resize(endpSize);
100  mZEndpoints.resize(endpSize);
101  for (int i = 0, j = 0; i < intrSize; ++i)
102  {
103  mXEndpoints[j].type = 0;
104  mXEndpoints[j].value = mBoxes[i].min[0];
105  mXEndpoints[j].index = i;
106  mYEndpoints[j].type = 0;
107  mYEndpoints[j].value = mBoxes[i].min[1];
108  mYEndpoints[j].index = i;
109  mZEndpoints[j].type = 0;
110  mZEndpoints[j].value = mBoxes[i].min[2];
111  mZEndpoints[j].index = i;
112  ++j;
113 
114  mXEndpoints[j].type = 1;
115  mXEndpoints[j].value = mBoxes[i].max[0];
116  mXEndpoints[j].index = i;
117  mYEndpoints[j].type = 1;
118  mYEndpoints[j].value = mBoxes[i].max[1];
119  mYEndpoints[j].index = i;
120  mZEndpoints[j].type = 1;
121  mZEndpoints[j].value = mBoxes[i].max[2];
122  mZEndpoints[j].index = i;
123  ++j;
124  }
125 
126  // Sort the rectangle endpoints.
127  std::sort(mXEndpoints.begin(), mXEndpoints.end());
128  std::sort(mYEndpoints.begin(), mYEndpoints.end());
129  std::sort(mZEndpoints.begin(), mZEndpoints.end());
130 
131  // Create the interval-to-endpoint lookup tables.
132  mXLookup.resize(endpSize);
133  mYLookup.resize(endpSize);
134  mZLookup.resize(endpSize);
135  for (int j = 0; j < endpSize; ++j)
136  {
137  mXLookup[2 * mXEndpoints[j].index + mXEndpoints[j].type] = j;
138  mYLookup[2 * mYEndpoints[j].index + mYEndpoints[j].type] = j;
139  mZLookup[2 * mZEndpoints[j].index + mZEndpoints[j].type] = j;
140  }
141 
142  // Active set of rectangles (stored by index in array).
143  std::set<int> active;
144 
145  // set of overlapping rectangles (stored by pairs of indices in array)
146  mOverlap.clear();
147 
148  // Sweep through the endpoints to determine overlapping x-intervals.
149  for (int i = 0; i < endpSize; ++i)
150  {
151  Endpoint& endpoint = mXEndpoints[i];
152  int index = endpoint.index;
153  if (endpoint.type == 0) // an interval 'begin' value
154  {
155  // In the 1D problem, the current interval overlaps with all the
156  // active intervals. In 3D we also need to check for y-overlap
157  // and z-overlap.
158  for (auto activeIndex : active)
159  {
160  // Rectangles activeIndex and index overlap in the
161  // x-dimension. Test for overlap in the y-dimension and
162  // z-dimension.
163  AlignedBox3<Real> const& b0 = mBoxes[activeIndex];
164  AlignedBox3<Real> const& b1 = mBoxes[index];
165  if (b0.max[1] >= b1.min[1] && b0.min[1] <= b1.max[1]
166  && b0.max[2] >= b1.min[2] && b0.min[2] <= b1.max[2])
167  {
168  if (activeIndex < index)
169  {
170  mOverlap.insert(EdgeKey<false>(activeIndex, index));
171  }
172  else
173  {
174  mOverlap.insert(EdgeKey<false>(index, activeIndex));
175  }
176  }
177  }
178  active.insert(index);
179  }
180  else // an interval 'end' value
181  {
182  active.erase(index);
183  }
184  }
185 }
186 
187 template <typename Real>
189 {
190  mBoxes[i] = box;
191  mXEndpoints[mXLookup[2 * i]].value = box.min[0];
192  mXEndpoints[mXLookup[2 * i + 1]].value = box.max[0];
193  mYEndpoints[mYLookup[2 * i]].value = box.min[1];
194  mYEndpoints[mYLookup[2 * i + 1]].value = box.max[1];
195  mZEndpoints[mZLookup[2 * i]].value = box.min[2];
196  mZEndpoints[mZLookup[2 * i + 1]].value = box.max[2];
197 }
198 
199 template <typename Real>
201 {
202  box = mBoxes[i];
203 }
204 
205 template <typename Real>
206 void BoxManager<Real>::InsertionSort(std::vector<Endpoint>& endpoint, std::vector<int>& lookup)
207 {
208  // Apply an insertion sort. Under the assumption that the rectangles
209  // have not changed much since the last call, the endpoints are nearly
210  // sorted. The insertion sort should be very fast in this case.
211 
213  int endpSize = static_cast<int>(endpoint.size());
214  for (int j = 1; j < endpSize; ++j)
215  {
216  Endpoint key = endpoint[j];
217  int i = j - 1;
218  while (i >= 0 && key < endpoint[i])
219  {
220  Endpoint e0 = endpoint[i];
221  Endpoint e1 = endpoint[i + 1];
222 
223  // Update the overlap status.
224  if (e0.type == 0)
225  {
226  if (e1.type == 1)
227  {
228  // The 'b' of interval E0.mIndex was smaller than the 'e'
229  // of interval E1.mIndex, and the intervals *might have
230  // been* overlapping. Now 'b' and 'e' are swapped, and
231  // the intervals cannot overlap. Remove the pair from
232  // the overlap set. The removal operation needs to find
233  // the pair and erase it if it exists. Finding the pair
234  // is the expensive part of the operation, so there is no
235  // real time savings in testing for existence first, then
236  // deleting if it does.
237  mOverlap.erase(EdgeKey<false>(e0.index, e1.index));
238  }
239  }
240  else
241  {
242  if (e1.type == 0)
243  {
244  // The 'b' of interval E1.index was larger than the 'e'
245  // of interval E0.index, and the intervals were not
246  // overlapping. Now 'b' and 'e' are swapped, and the
247  // intervals *might be* overlapping. Determine if they
248  // are overlapping and then insert.
249  if (query(mBoxes[e0.index], mBoxes[e1.index]).intersect)
250  {
251  mOverlap.insert(EdgeKey<false>(e0.index, e1.index));
252  }
253  }
254  }
255 
256  // Reorder the items to maintain the sorted list.
257  endpoint[i] = e1;
258  endpoint[i + 1] = e0;
259  lookup[2 * e1.index + e1.type] = i;
260  lookup[2 * e0.index + e0.type] = i + 1;
261  --i;
262  }
263  endpoint[i + 1] = key;
264  lookup[2 * key.index + key.type] = i + 1;
265  }
266 }
267 
268 template <typename Real>
270 {
274 }
275 
276 template <typename Real>
277 const std::set<EdgeKey<false>>& BoxManager<Real>::GetOverlap() const
278 {
279  return mOverlap;
280 }
281 
282 template <typename Real>
284 {
285  if (value < endpoint.value)
286  {
287  return true;
288  }
289  if (value > endpoint.value)
290  {
291  return false;
292  }
293  return type < endpoint.type;
294 }
295 
296 }
std::vector< Endpoint > mXEndpoints
Definition: GteBoxManager.h:70
void SetBox(int i, AlignedBox3< Real > const &box)
Vector< N, Real > max
Definition: GteAlignedBox.h:40
Vector< N, Real > min
Definition: GteAlignedBox.h:40
std::set< EdgeKey< false > > mOverlap
Definition: GteBoxManager.h:71
std::vector< Endpoint > mZEndpoints
Definition: GteBoxManager.h:70
std::set< EdgeKey< false > > const & GetOverlap() const
std::vector< int > mZLookup
Definition: GteBoxManager.h:82
GLsizei const GLfloat * value
Definition: glcorearb.h:819
bool operator<(Endpoint const &endpoint) const
GLuint index
Definition: glcorearb.h:781
void InsertionSort(std::vector< Endpoint > &endPoint, std::vector< int > &lookup)
std::vector< Endpoint > mYEndpoints
Definition: GteBoxManager.h:70
std::vector< int > mXLookup
Definition: GteBoxManager.h:82
void GetBox(int i, AlignedBox3< Real > &box) const
std::vector< int > mYLookup
Definition: GteBoxManager.h:82
BoxManager & operator=(BoxManager const &)=delete
BoxManager()=delete
GLenum query
Definition: glext.h:2716
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:103
std::vector< AlignedBox3< Real > > & mBoxes
Definition: GteBoxManager.h:69


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