VR-Forces 5.0.3 Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
DtNTree.h
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright (c) 2019 MAK Technologies, Inc.
3 ** All rights reserved.
4 ******************************************************************************/
5 #pragma once
6 
10 
11 #include <boost/shared_ptr.hpp>
12 #include <boost/weak_ptr.hpp>
13 #include <boost/enable_shared_from_this.hpp>
14 
15 #include <cassert>
16 
17 namespace makVrv
18 {
22  {
23  public:
25  {
26  public:
27  explicit scoped_lock(DtNTreeNullMutexPolicy&, bool=true) { }
28 
29  bool upgrade_to_writer() { return true; }
31  void release() { }
32  };
33  };
34 
36  template <typename Tree>
38  {
39  typedef boost::shared_ptr<Tree> Ptr;
40  typedef boost::weak_ptr<Tree> ParentPtr;
41  };
42 
44  template <typename Tree>
46  {
47  typedef boost::weak_ptr<Tree> Ptr;
48  typedef boost::shared_ptr<Tree> ParentPtr;
49  };
50 
66  template <
67  typename T,
68  unsigned int Dimensions = 3,
69  typename Mutex = DtNTreeNullMutexPolicy,
70  template <typename> class SubcellTraits = DtNTreeSharedPointerTraits,
71  typename BoundsType = double
72  >
73  class DtNTree
74  : public boost::enable_shared_from_this< DtNTree<T,Dimensions,Mutex,SubcellTraits,BoundsType> >
75  {
77 
78  template <unsigned int A, unsigned int B>
79  struct Power
80  {
81  static const unsigned int value = A * Power<A, B - 1>::value;
82  };
83  template <unsigned int A>
84  struct Power<A, 0>
85  {
86  static const unsigned int value = 1;
87  };
89 
92 
93  template <typename Z>
94  static boost::shared_ptr<Z> Get(const boost::shared_ptr<Z>& p) { return p ;}
95 
96  template <typename Z>
97  static boost::shared_ptr<Z> Get(const boost::weak_ptr<Z>& p) { return p.lock(); }
98 
99  template <typename Z>
100  static void Set(boost::shared_ptr<Z>& p, const boost::shared_ptr<Z>& to) { p = to; }
101 
102  template <typename Z>
103  static void Set(boost::shared_ptr<Z>& p, const boost::weak_ptr<Z>& to) { p = to.lock(); }
104 
105  template <typename Z>
106  static void Set(boost::weak_ptr<Z>& p, const boost::shared_ptr<Z>& to) { p = to; }
107 
108  template <typename Z>
109  static void Set(boost::weak_ptr<Z>& p, const boost::weak_ptr<Z>& to) { p = to; }
111 
112  typedef typename SubcellTraits<DtNTree>::Ptr Ptr;
113  typedef typename SubcellTraits<DtNTree>::ParentPtr ParentPtr;
114 
115  public:
116  class Query;
117  friend class Query;
118 
120  static const unsigned int NumberOfIndices = Power<2, Dimensions>::value;
121 
123  struct Range
124  {
127  : minimum(std::numeric_limits<BoundsType>::min())
128  , maximum(std::numeric_limits<BoundsType>::max()) { }
129 
131  Range(BoundsType min, BoundsType max)
132  : minimum(min), maximum(max) { }
133 
135  double size() const
136  {
137  return maximum - minimum;
138  }
139 
141  bool intersects(const Range& other) const
142  {
143  if (maximum < other.minimum) return false;
144 
145  if (other.maximum < minimum) return false;
146 
147  return true;
148  }
149 
150  BoundsType minimum, maximum;
151  };
152 
154  class Bounds
155  {
156  public:
158  Bounds makeSubBounds(unsigned int index) const
159  {
160  Bounds newBounds(*this);
161 
162  for (unsigned int bit=1, d=0; d < Dimensions; ++d, bit=bit<<1)
163  {
164  // compute center point of range for this dimension
165  Range r = range(d);
166  BoundsType middle = ((r.maximum - r.minimum)/2) + r.minimum;
167 
168  // if the bit for this dimension is 1 then it will be from
169  // the center to the max, otherwise from the min to the center
170  // min and max are set when myRanges is initialized
171  if (index & bit)
172  {
173  newBounds.range(d).minimum = middle;
174  }
175  else
176  {
177  newBounds.range(d).maximum = middle;
178  }
179  }
180 
181  return newBounds;
182  }
183 
185  double size() const
186  {
187  double value = 1;
188 
189  for (unsigned int d=0; d < Dimensions; ++d)
190  {
191  value *= range(d).size();
192  }
193 
194  return value;
195  }
196 
198  bool intersects(const Bounds& other) const
199  {
200  for (unsigned int d=0; d < Dimensions; ++d)
201  {
202  // if any of the dimensions don't overlap then the entire thing doesn't
203  if (!range(d).intersects(other.range(d)))
204  {
205  return false;
206  }
207  }
208 
209  return true;
210  }
211 
213 
214  Range& range(unsigned int i) { assert(i < Dimensions); return myRanges[i]; }
215  const Range& range(unsigned int i) const { assert(i < Dimensions); return myRanges[i]; }
217 
218  private:
219  Range myRanges[Dimensions];
220  };
221 
223  class Subcell
224  {
225  public:
227  const Bounds& bounds() const { return myBounds; }
228 
230  boost::shared_ptr<DtNTree> getPtr(DtNTree& tree, Query& query)
231  {
232  boost::shared_ptr<DtNTree> child;
233 
234  // see if there's already a child there
235  typename Mutex::scoped_lock lock(myMutex, false);
236  Set(child, myTree);
237 
238  // if not then we'll see if we need to create it
239  if (!child)
240  {
241  // if we're not going to create a subcell then return null
242  // the caller will have to deal with this case
243  if (!query.shouldCreateSubcell(*this))
244  {
245  return boost::shared_ptr<DtNTree>();
246  }
247 
248  // if this returns false then another lock got the write lock and might
249  // have created the child, have to check again
250  if (!lock.upgrade_to_writer())
251  {
252  Set(child, myTree);
253  }
254 
255  // now we have the write lock and we know there's no child
256  // create it and store it
257  // we have a shared pointer to it on the stack, don't need the mutex anymore
258  if (!child)
259  {
260  child = query.createSubcell(tree, *this);
261  Set(myTree, child);
262  }
263  }
264 
265  return child;
266  }
267 
268  private:
269  friend class DtNTree;
270 
272  void init(const Bounds& b) { myBounds = b; }
273 
276 
278  mutable Mutex myMutex;
279 
282  };
283 
285  static boost::shared_ptr<DtNTree> Create(const Bounds& bounds)
286  {
287  return boost::shared_ptr<DtNTree>(new DtNTree(bounds, 0));
288  }
289 
291  int getLevel() const { return myLevel; }
292 
294  const Bounds& getBounds() const { return myBounds; }
295 
297  boost::shared_ptr<DtNTree> getParent() const { return Get(myParent); }
298 
300 
301  T& getData() { return myData; }
302  const T& getData() const { return myData; }
304 
305  protected:
309  explicit DtNTree(DtNTree& parent, const Bounds& bounds)
310  : myParent(parent.shared_from_this())
311  , myLevel(parent.myLevel + 1)
312  , myBounds(bounds)
313  {
314  for (unsigned int i=0; i < NumberOfIndices; ++i)
315  {
316  mySubcells[i].init(bounds.makeSubBounds(i));
317  }
318  }
319 
321  explicit DtNTree(const Bounds& bounds, unsigned int level)
322  : myParent()
323  , myLevel(level)
324  , myBounds(bounds)
325  {
326  for (unsigned int i=0; i < NumberOfIndices; ++i)
327  {
328  mySubcells[i].init(bounds.makeSubBounds(i));
329  }
330  }
331 
334  virtual boost::shared_ptr<DtNTree> createSubcell(Subcell& cell)
335  {
336  return boost::shared_ptr<DtNTree>(new DtNTree(*this, cell.bounds()));
337  }
338 
340  virtual void visit(Query& query)
341  {
342  // search is split up into two phases so that the match function can see
343  // the entire set of subareas before any recursing is done
344 
345  // holds the results of the intersection checks
346  bool intersected[NumberOfIndices];
347 
348  // iterate over each subarea and check for matching
349  for (unsigned int i=0; i < NumberOfIndices; ++i)
350  {
351  intersected[i] = query.matches(mySubcells[i]);
352  }
353 
354  // iterate again over the subcells that were matched
355  for (unsigned int i=0; i < NumberOfIndices; ++i)
356  {
357  // skip any cells that didn't match
358  if (!intersected[i])
359  {
360  continue;
361  }
362 
363  // shared pointer to child on the stack guarantees it stays alive
364  boost::shared_ptr<DtNTree> child = mySubcells[i].getPtr(*this, query);
365 
366  // if we got through all the at and actually have a child, time to recurse
367  if (child)
368  {
369  query.visit(*child);
370  }
371  }
372  }
373 
376 
378  const int myLevel;
379 
382 
385 
388  };
389 
397  template <
398  typename T,
399  unsigned int Dimensions,
400  typename Mutex,
401  template <typename> class SubcellPolicy,
402  typename BoundsType
403  >
404  class DtNTree<T,Dimensions,Mutex,SubcellPolicy,BoundsType>::Query
405  {
406  public:
408  virtual ~Query() { }
409 
414  virtual bool matches(const Subcell& cell) = 0;
415 
419  virtual bool shouldCreateSubcell(const Subcell& cell) = 0;
420 
423  virtual boost::shared_ptr<DtNTree> createSubcell(DtNTree& tree, Subcell& cell)
424  {
425  return tree.createSubcell(cell);
426  }
427 
429  virtual void visit(DtNTree& tree)
430  {
431  tree.visit(*this);
432  }
433 
434  protected:
436  Subcell& getSubcell(DtNTree& tree, unsigned int i)
437  {
438  assert(i < sizeof(tree.mySubcells));
439  return tree.mySubcells[i];
440  }
441  };
442 }
Represents the subcell in the parent cell.
Definition: DtNTree.h:223
virtual boost::shared_ptr< DtNTree > createSubcell(DtNTree &tree, Subcell &cell)
Factory function for creating subcells. Reimplement this function to have this query create your own ...
Definition: DtNTree.h:423
Range()
Default constructor.
Definition: DtNTree.h:126
virtual bool matches(const Subcell &cell)=0
Search will ignore cells which return false. For a given tree, matches will be called on ALL the subc...
boost::weak_ptr< Tree > Ptr
Definition: DtNTree.h:47
Query interface. Queries are templates of a general search on the tree. Users implement various parts...
Definition: DtNTree.h:404
virtual void visit(DtNTree &tree)
Entry point for search.
Definition: DtNTree.h:429
Generate NTree (binary tree, quadtree, octree, etc.) class. This consists of the tree itself and a qu...
Definition: DtNTree.h:73
virtual bool shouldCreateSubcell(const Subcell &cell)=0
Determine if an empty subcell should be created. This function will be called when the query is has d...
bool intersects(const Bounds &other) const
Returns true if the two bounds intersect each other.
Definition: DtNTree.h:198
const T & getData() const
Accessors for user data.
Definition: DtNTree.h:302
DT_DLL_VRVCORE DtTaitBryan level(const DtCoordinateSystem &cs, const DtVector &localOrigin, double topoHeading)
Returns a level orientation with the topographic heading.
static const unsigned int value
Definition: DtNTree.h:81
virtual void visit(Query &query)
Default implementation of query visit.
Definition: DtNTree.h:340
T & getData()
Accessors for user data.
Definition: DtNTree.h:301
boost::shared_ptr< DtNTree > getPtr(DtNTree &tree, Query &query)
Get or create the tree for this subcell.
Definition: DtNTree.h:230
static void Set(boost::weak_ptr< Z > &p, const boost::shared_ptr< Z > &to)
These functions allow shared and weak pointers to be treated the same. Weak pointers cannot be direct...
Definition: DtNTree.h:106
Range(BoundsType min, BoundsType max)
Create from bounds of range.
Definition: DtNTree.h:131
boost::shared_ptr< DtNTree > getParent() const
Return the parent of this tree, if it exists.
Definition: DtNTree.h:297
Weak pointer policy.
Definition: DtNTree.h:45
static void Set(boost::weak_ptr< Z > &p, const boost::weak_ptr< Z > &to)
These functions allow shared and weak pointers to be treated the same. Weak pointers cannot be direct...
Definition: DtNTree.h:109
Set of ranges, one for each dimension.
Definition: DtNTree.h:154
bool upgrade_to_writer()
Definition: DtNTree.h:29
const Bounds & getBounds() const
Return the bounds of this tree.
Definition: DtNTree.h:294
T myData
User data stored in this tree.
Definition: DtNTree.h:387
SubcellTraits< DtNTree >::Ptr Ptr
Definition: DtNTree.h:112
const int myLevel
Level of this cell.
Definition: DtNTree.h:378
virtual ~Query()
Virtual destructor.
Definition: DtNTree.h:408
BoundsType maximum
Definition: DtNTree.h:150
virtual boost::shared_ptr< DtNTree > createSubcell(Subcell &cell)
Default implementation of query createSubcell.
Definition: DtNTree.h:334
static boost::shared_ptr< Z > Get(const boost::shared_ptr< Z > &p)
These functions allow shared and weak pointers to be treated the same. Weak pointers cannot be direct...
Definition: DtNTree.h:94
DtNTree(DtNTree &parent, const Bounds &bounds)
Constructor for creating children trees.
Definition: DtNTree.h:309
void downgrade_to_reader()
Definition: DtNTree.h:30
double size() const
Compute the size (area, volume, etc. depending on number of dimensions).
Definition: DtNTree.h:185
static const unsigned int NumberOfIndices
Number of subcells.
Definition: DtNTree.h:120
boost::weak_ptr< Tree > ParentPtr
Definition: DtNTree.h:40
Range & range(unsigned int i)
accessors
Definition: DtNTree.h:214
OpenThreads::Mutex Mutex
Definition: DtOsgThreadingUtils.h:12
Bounds makeSubBounds(unsigned int index) const
Compute the bounds of a subcell at a given index.
Definition: DtNTree.h:158
boost::shared_ptr< Tree > Ptr
Definition: DtNTree.h:39
void init(const Bounds &b)
This class is created in an array so parameters are initialized after the constructor.
Definition: DtNTree.h:272
Null mutex default policy. Using this policy will result in no locking (i.e. tree is not threadsafe)...
Definition: DtNTree.h:21
Subcell & getSubcell(DtNTree &tree, unsigned int i)
Interface for subclasses to get at subcell objects.
Definition: DtNTree.h:436
const Range & range(unsigned int i) const
accessors
Definition: DtNTree.h:215
double size() const
Compute the length of the range.
Definition: DtNTree.h:135
int getLevel() const
Return level of this tree.
Definition: DtNTree.h:291
Subcell mySubcells[NumberOfIndices]
Subcells.
Definition: DtNTree.h:384
const Bounds & bounds() const
Accessor for bounds of this cell.
Definition: DtNTree.h:227
static boost::shared_ptr< DtNTree > Create(const Bounds &bounds)
Factory, create a top level root cell.
Definition: DtNTree.h:285
void release()
Definition: DtNTree.h:31
scoped_lock(DtNTreeNullMutexPolicy &, bool=true)
Definition: DtNTree.h:27
static void Set(boost::shared_ptr< Z > &p, const boost::weak_ptr< Z > &to)
These functions allow shared and weak pointers to be treated the same. Weak pointers cannot be direct...
Definition: DtNTree.h:103
Bounds myBounds
Bounds of this subcell.
Definition: DtNTree.h:275
static void Set(boost::shared_ptr< Z > &p, const boost::shared_ptr< Z > &to)
These functions allow shared and weak pointers to be treated the same. Weak pointers cannot be direct...
Definition: DtNTree.h:100
boost::shared_ptr< Tree > ParentPtr
Definition: DtNTree.h:48
One dimensional range (i.e. min/max).
Definition: DtNTree.h:123
Shared pointer policy.
Definition: DtNTree.h:37
SubcellTraits< DtNTree >::ParentPtr ParentPtr
Definition: DtNTree.h:113
bool intersects(const Range &other) const
Returns true of these two ranges intersect.
Definition: DtNTree.h:141
const ParentPtr myParent
Pointer to parent node if it exists.
Definition: DtNTree.h:375
DtNTree(const Bounds &bounds, unsigned int level)
Constructor for creating root tree.
Definition: DtNTree.h:321
Compute exponents at compile time (for array length).
Definition: DtNTree.h:79
Ptr myTree
Pointer to child tree.
Definition: DtNTree.h:281
const Bounds myBounds
Bounds of this cell.
Definition: DtNTree.h:381
static boost::shared_ptr< Z > Get(const boost::weak_ptr< Z > &p)
These functions allow shared and weak pointers to be treated the same. Weak pointers cannot be direct...
Definition: DtNTree.h:97
Mutex myMutex
Mutex which synchronizes only the pointer, not the object pointed to.
Definition: DtNTree.h:278
BoundsType minimum
Definition: DtNTree.h:150
Range myRanges[Dimensions]
Definition: DtNTree.h:219

Document ID: Generated on Thu Jun 1 17:58:13 EDT 2023 from SVN revision 255404
Copyright © 2005-2021 MAK Technologies. All Rights Reserved (www.mak.com)