LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
RStarBoundingBox.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008 Dustin Spicuzza <dustin@virtualroadside.com>
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of version 2 of the GNU General Public License
6  * as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16  */
17 
18 
19 #ifndef RStarBoundingBox_H
20 #define RStarBoundingBox_H
21 
22 #include <limits>
23 #include <utility>
24 #include <cstddef>
25 #include <string>
26 #include <sstream>
27 
28 
29 template <std::size_t dimensions>
31 
32  // edges[x].first is low value, edges[x].second is high value
33  std::pair<double, double> edges[dimensions];
34 
35  // forces all edges to their extremes so we can stretch() it
36  void reset()
37  {
38  for (std::size_t axis = 0; axis < dimensions; axis++)
39  {
40  edges[axis].first = std::numeric_limits<double>::max();
41  edges[axis].second = std::numeric_limits<double>::min();
42  }
43  }
44 
45  // returns a new bounding box that has the maximum boundaries
47  {
49  bound.reset();
50  return bound;
51  }
52 
53 
54  // fits another box inside of this box, returns true if a stretch occured
56  {
57  bool ret = false;
58 
59  for (std::size_t axis = 0; axis < dimensions; axis++)
60  {
61 
62  if (edges[axis].first > bb.edges[axis].first)
63  {
64  edges[axis].first = bb.edges[axis].first;
65  ret = true;
66  }
67 
68  if (edges[axis].second < bb.edges[axis].second)
69  {
70  edges[axis].second = bb.edges[axis].second;
71  ret = true;
72  }
73  }
74 
75  return ret;
76  }
77 
78  // the sum of all deltas between edges
79  inline int edgeDeltas() const
80  {
81  double distance = 0;
82  for (std::size_t axis = 0; axis < dimensions; axis++)
83  distance += edges[axis].second - edges[axis].first;
84 
85  return distance;
86  }
87 
88  // calculates the area of a bounding box
89  inline double area() const
90  {
91  double area = 1;
92  for (std::size_t axis = 0; axis < dimensions; axis++)
93  area *= (double)(edges[axis].second - edges[axis].first);
94 
95  return area;
96  }
97 
98  // this determines if a bounding box is fully contained within this bounding box
99  inline bool encloses(const RStarBoundingBox<dimensions>& bb) const
100  {
101  // if (y1 < x1 || x2 < y2)
102  for (std::size_t axis = 0; axis < dimensions; axis++)
103  if (bb.edges[axis].first < edges[axis].first || edges[axis].second < bb.edges[axis].second)
104  return false;
105 
106  return true;
107  }
108 
109  // a quicker way to determine if two bounding boxes overlap
110  inline bool overlaps(const RStarBoundingBox<dimensions>& bb) const
111  {
112  // do it this way so theres no equal signs (in case of doubles)
113  // if (!(x1 < y2) && !(x2 > y1))
114  for (std::size_t axis = 0; axis < dimensions; axis++)
115  {
116  if (!(edges[axis].first < bb.edges[axis].second) || !(bb.edges[axis].first < edges[axis].second))
117  return false;
118  }
119 
120  return true;
121  }
122 
123  // calculates the total overlapping area of two boxes
124  double overlap(const RStarBoundingBox<dimensions>& bb) const
125  {
126  double area = 1.0;
127  for (std::size_t axis = 0; area && axis < dimensions; axis++)
128  {
129  // this makes it easier to understand
130  const double x1 = edges[axis].first;
131  const double x2 = edges[axis].second;
132  const double y1 = bb.edges[axis].first;
133  const double y2 = bb.edges[axis].second;
134 
135  // left edge outside left edge
136  if (x1 < y1)
137  {
138  // and right edge inside left edge
139  if (y1 < x2)
140  {
141  // right edge outside right edge
142  if (y2 < x2)
143  area *= (double)( y2 - y1 );
144  else
145  area *= (double)( x2 - y1 );
146 
147  continue;
148  }
149  }
150  // right edge inside left edge
151  else if (x1 < y2)
152  {
153  // right edge outside right edge
154  if (x2 < y2)
155  area *= (double)( x2 - x1 );
156  else
157  area *= (double)( y2 - x1 );
158 
159  continue;
160  }
161 
162  // if we get here, there is no overlap
163  return 0.0;
164  }
165 
166  return area;
167  }
168 
169  // sums the total distances from the center of another bounding box
171  {
172  double distance = 0, t;
173  for (std::size_t axis = 0; axis < dimensions; axis++)
174  {
175  t = ((double)edges[axis].first + (double)edges[axis].second +
176  (double)bb.edges[axis].first + (double)bb.edges[axis].second)
177  /2.0;
178  distance += t*t;
179  }
180 
181  return distance;
182  }
183 
184  // determines if two bounding boxes are identical
186  {
187  for (std::size_t axis = 0; axis < dimensions; axis++)
188  if (edges[axis].first != bb.edges[axis].first || edges[axis].second != bb.edges[axis].second)
189  return false;
190 
191  return true;
192  }
193 
194 
195  // very slow, use for debugging only
196  std::string ToString() const
197  {
198  std::stringstream name("");
199  name << "[";
200  for (std::size_t axis = 0; axis < dimensions; axis++)
201  {
202  name << "(" << edges[axis].first << "," << edges[axis].second << ")";
203  if (axis != dimensions -1)
204  name << ",";
205  }
206  name << "]";
207 
208  return name.str();
209  }
210 };
211 
212 
213 
214 template <std::size_t dimensions>
217 
218  BoundingBox bound;
219 };
220 
221 
222 /**********************************************************
223  * Functor used to iterate over a set and stretch a
224  * bounding box
225  **********************************************************/
226 
227 // for_each(items.begin(), items.end(), StretchBoundedItem::BoundingBox(bound));
228 template <typename BoundedItem>
230  public std::unary_function< const BoundedItem * const, void >
231 {
233  explicit StretchBoundingBox(typename BoundedItem::BoundingBox * bound) : m_bound(bound) {}
234 
235  void operator() (const BoundedItem * const item)
236  {
237  m_bound->stretch(item->bound);
238  }
239 };
240 
241 
242 /**********************************************************
243  * R* Tree related functors used for sorting BoundedItems
244  *
245  * TODO: Take advantage of type traits
246  **********************************************************/
247 
248 template <typename BoundedItem>
250  public std::binary_function< const BoundedItem * const, const BoundedItem * const, bool >
251 {
252  const std::size_t m_axis;
253  explicit SortBoundedItemsByFirstEdge (const std::size_t axis) : m_axis(axis) {}
254 
255  bool operator() (const BoundedItem * const bi1, const BoundedItem * const bi2) const
256  {
257  return bi1->bound.edges[m_axis].first < bi2->bound.edges[m_axis].first;
258  }
259 };
260 
261 template <typename BoundedItem>
263  public std::binary_function< const BoundedItem * const, const BoundedItem * const, bool >
264 {
265  const std::size_t m_axis;
266  explicit SortBoundedItemsBySecondEdge (const std::size_t axis) : m_axis(axis) {}
267 
268  bool operator() (const BoundedItem * const bi1, const BoundedItem * const bi2) const
269  {
270  return bi1->bound.edges[m_axis].second < bi2->bound.edges[m_axis].second;
271  }
272 };
273 
274 
275 template <typename BoundedItem>
277  public std::binary_function< const BoundedItem * const, const BoundedItem * const, bool >
278 {
279  const typename BoundedItem::BoundingBox * const m_center;
280  explicit SortBoundedItemsByDistanceFromCenter(const typename BoundedItem::BoundingBox * const center) : m_center(center) {}
281 
282  bool operator() (const BoundedItem * const bi1, const BoundedItem * const bi2) const
283  {
284  return bi1->bound.distanceFromCenter(*m_center) < bi2->bound.distanceFromCenter(*m_center);
285  }
286 };
287 
288 template <typename BoundedItem>
290  public std::binary_function< const BoundedItem * const, const BoundedItem * const, bool >
291 {
292  const double area;
293  explicit SortBoundedItemsByAreaEnlargement(const typename BoundedItem::BoundingBox * center) : area(center->area()) {}
294 
295  bool operator() (const BoundedItem * const bi1, const BoundedItem * const bi2) const
296  {
297  return area - bi1->bound.area() < area - bi2->bound.area();
298  }
299 };
300 
301 template <typename BoundedItem>
303  public std::binary_function< const BoundedItem * const, const BoundedItem * const, bool >
304 {
305  const typename BoundedItem::BoundingBox * const m_center;
306  explicit SortBoundedItemsByOverlapEnlargement(const typename BoundedItem::BoundingBox * const center) : m_center(center) {}
307 
308  bool operator() (const BoundedItem * const bi1, const BoundedItem * const bi2) const
309  {
310  return bi1->bound.overlap(*m_center) < bi2->bound.overlap(*m_center);
311  }
312 };
313 
314 
315 #endif
double distanceFromCenter(const RStarBoundingBox< dimensions > &bb) const
bool operator==(const RStarBoundingBox< dimensions > &bb)
Float_t y1[n_points_granero]
Definition: compare.C:5
Float_t x1[n_points_granero]
Definition: compare.C:5
double overlap(const RStarBoundingBox< dimensions > &bb) const
SortBoundedItemsByDistanceFromCenter(const typename BoundedItem::BoundingBox *const center)
SortBoundedItemsByOverlapEnlargement(const typename BoundedItem::BoundingBox *const center)
SortBoundedItemsByFirstEdge(const std::size_t axis)
double area() const
Float_t y2[n_points_geant4]
Definition: compare.C:26
const BoundedItem::BoundingBox *const m_center
SortBoundedItemsBySecondEdge(const std::size_t axis)
Int_t max
Definition: plot.C:27
int edgeDeltas() const
bool stretch(const RStarBoundingBox< dimensions > &bb)
bool encloses(const RStarBoundingBox< dimensions > &bb) const
BoundedItem::BoundingBox * m_bound
RTree::BoundingBox BoundingBox
Definition: main.cpp:34
StretchBoundingBox(typename BoundedItem::BoundingBox *bound)
std::string ToString() const
Int_t min
Definition: plot.C:26
bool overlaps(const RStarBoundingBox< dimensions > &bb) const
SortBoundedItemsByAreaEnlargement(const typename BoundedItem::BoundingBox *center)
std::pair< double, double > edges[dimensions]
static RStarBoundingBox MaximumBounds()
RStarBoundingBox< dimensions > BoundingBox
Float_t x2[n_points_geant4]
Definition: compare.C:26
const BoundedItem::BoundingBox *const m_center