OpenVDB  1.2.0
ValueAccessor.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2013 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
30 //
57 
58 #ifndef OPENVDB_TREE_VALUEACCESSOR_HAS_BEEN_INCLUDED
59 #define OPENVDB_TREE_VALUEACCESSOR_HAS_BEEN_INCLUDED
60 
61 #include <boost/mpl/front.hpp>
62 #include <boost/mpl/pop_front.hpp>
63 #include <boost/mpl/push_back.hpp>
64 #include <boost/mpl/size.hpp>
65 #include <boost/mpl/at.hpp>
66 #include <boost/mpl/equal_to.hpp>
67 #include <boost/mpl/comparison.hpp>
68 #include <boost/mpl/vector.hpp>
69 #include <boost/mpl/assert.hpp>
70 #include <boost/mpl/erase.hpp>
71 #include <boost/mpl/find.hpp>
72 #include <boost/static_assert.hpp>
73 #include <boost/type_traits/is_const.hpp>
74 #include <tbb/null_mutex.h>
75 #include <tbb/spin_mutex.h>
76 #include <openvdb/version.h>
77 #include <openvdb/Types.h>
78 
79 namespace openvdb {
81 namespace OPENVDB_VERSION_NAME {
82 namespace tree {
83 
84 // Forward declarations of local classes that are not intended for general use
85 template<typename TreeType> class ValueAccessor0;
86 template<typename TreeType, Index L0 = 0> class ValueAccessor1;
87 template<typename TreeType, Index L0 = 0, Index L1 = 1> class ValueAccessor2;
88 template<typename TreeType, Index L0 = 0, Index L1 = 1, Index L2 = 2> class ValueAccessor3;
89 template<typename HeadT, int HeadLevel> struct InvertedTree;
90 template<typename TreeCacheT, typename NodeVecT, bool AtRoot> class CacheItem;
91 
92 
102 template<typename TreeType>
104 {
105 public:
106  static const bool IsConstTree = boost::is_const<TreeType>::value;
107 
108  ValueAccessorBase(TreeType& tree): mTree(&tree) { tree.attachAccessor(*this); }
109 
110  virtual ~ValueAccessorBase() { if (mTree) mTree->releaseAccessor(*this); }
111 
117  TreeType* getTree() const { return mTree; }
119  TreeType& tree() const { assert(mTree); return *mTree; }
120 
121  ValueAccessorBase(const ValueAccessorBase& other): mTree(other.mTree)
122  {
123  if (mTree) mTree->attachAccessor(*this);
124  }
125 
127  {
128  if (&other != this) {
129  if (mTree) mTree->releaseAccessor(*this);
130  mTree = other.mTree;
131  if (mTree) mTree->attachAccessor(*this);
132  }
133  return *this;
134  }
135 
136  virtual void clear() = 0;
137 
138 protected:
139  // Allow trees to deregister themselves.
140  template<typename> friend class Tree;
141 
142  virtual void release() { mTree = NULL; }
143 
144  TreeType* mTree;
145 }; // class ValueAccessorBase
146 
147 
149 
150 
178 template<typename _TreeType,
179  Index CacheLevels = _TreeType::DEPTH-1,
180  typename MutexType = tbb::null_mutex>
181 class ValueAccessor: public ValueAccessorBase<_TreeType>
182 {
183 public:
184  BOOST_STATIC_ASSERT(CacheLevels <= _TreeType::DEPTH-1);
185  typedef _TreeType TreeType;
186  typedef typename TreeType::RootNodeType RootNodeT;
187  typedef typename TreeType::LeafNodeType LeafNodeT;
188  typedef typename RootNodeT::ValueType ValueType;
190  typedef typename MutexType::scoped_lock LockT;
191  using BaseT::IsConstTree;
192 
193  ValueAccessor(TreeType& tree): BaseT(tree), mCache(*this)
194  {
195  mCache.insert(Coord(), &tree.root());
196  }
197 
198  ValueAccessor(const ValueAccessor& other): BaseT(other), mCache(*this, other.mCache) {}
199 
201  {
202  if (&other != this) {
203  this->BaseT::operator=(other);
204  mCache.copy(*this, other.mCache);
205  }
206  return *this;
207  }
208  virtual ~ValueAccessor() {}
209 
211  static Index numCacheLevels() { return CacheLevels; }
212 
214  bool isCached(const Coord& xyz) const { LockT lock(mMutex); return mCache.isCached(xyz); }
215 
217  const ValueType& getValue(const Coord& xyz) const
218  {
219  LockT lock(mMutex);
220  return mCache.getValue(xyz);
221  }
222 
224  bool isValueOn(const Coord& xyz) const { LockT lock(mMutex); return mCache.isValueOn(xyz); }
225 
227  bool probeValue(const Coord& xyz, ValueType& value) const
228  {
229  LockT lock(mMutex);
230  return mCache.probeValue(xyz,value);
231  }
232 
236  int getValueDepth(const Coord& xyz) const
237  {
238  LockT lock(mMutex);
239  return mCache.getValueDepth(xyz);
240  }
241 
244  bool isVoxel(const Coord& xyz) const { LockT lock(mMutex); return mCache.isVoxel(xyz); }
245 
247  void setValue(const Coord& xyz, const ValueType& value)
249  {
250  LockT lock(mMutex);
251  mCache.setValue(xyz, value);
252  }
253  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
255 
257  void setValueOnly(const Coord& xyz, const ValueType& value)
258  {
259  LockT lock(mMutex);
260  mCache.setValueOnly(xyz, value);
261  }
262 
265  void newSetValue(const Coord& xyz, const ValueType& value)
266  {
267  LockT lock(mMutex);
268  mCache.newSetValue(xyz, value);
269  }
270 
272  void setValueOff(const Coord& xyz, const ValueType& value)
273  {
274  LockT lock(mMutex);
275  mCache.setValueOff(xyz, value);
276  }
277 
280  void setValueOnSum(const Coord& xyz, const ValueType& value)
281  {
282  LockT lock(mMutex);
283  mCache.setValueOnSum(xyz, value);
284  }
285 
287  void setActiveState(const Coord& xyz, bool on = true)
288  {
289  LockT lock(mMutex);
290  mCache.setActiveState(xyz, on);
291  }
293  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
295  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
296 
298  template<typename NodeType>
299  NodeType* getNode()
300  {
301  LockT lock(mMutex);
302  NodeType* node = NULL;
303  mCache.getNode(node);
304  return node;
305  }
306 
309  template<typename NodeType>
310  void insertNode(const Coord& xyz, NodeType& node)
311  {
312  LockT lock(mMutex);
313  mCache.insert(xyz, &node);
314  }
315 
319  template<typename NodeType>
320  void eraseNode() { LockT lock(mMutex); NodeType* node = NULL; mCache.erase(node); }
321 
324  void addLeaf(LeafNodeT* leaf)
325  {
326  LockT lock(mMutex);
327  mCache.addLeaf(leaf);
328  }
329 
333  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
334  {
335  LockT lock(mMutex);
336  mCache.addTile(level, xyz, value, state);
337  }
338 
345  LeafNodeT* touchLeaf(const Coord& xyz)
346  {
347  LockT lock(mMutex);
348  return mCache.touchLeaf(xyz);
349  }
350 
353  LeafNodeT* probeLeaf(const Coord& xyz)
354  {
355  LockT lock(mMutex);
356  return mCache.probeLeaf(xyz);
357  }
358 
361  const LeafNodeT* probeConstLeaf(const Coord& xyz) const
362  {
363  LockT lock(mMutex);
364  return mCache.probeConstLeaf(xyz);
365  }
366  const LeafNodeT* probeLeaf(const Coord& xyz) const
367  {
368  return this->probeConstLeaf(xyz);
369  }
370 
372  virtual void clear()
373  {
374  LockT lock(mMutex);
375  mCache.clear();
376  if (this->mTree) mCache.insert(Coord(), &(this->mTree->root()));
377  }
378 
379 private:
380  // Allow nodes to insert themselves into the cache.
381  template<typename> friend class RootNode;
382  template<typename, Index> friend class InternalNode;
383  template<typename, Index> friend class LeafNode;
384  // Allow trees to deregister themselves.
385  template<typename> friend class Tree;
386 
389  virtual void release()
390  {
391  LockT lock(mMutex);
392  this->BaseT::release();
393  mCache.clear();
394  }
399  template<typename NodeType>
400  void insert(const Coord& xyz, NodeType* node) { mCache.insert(xyz, node); }
401 
402  // Define a list of all tree node types from LeafNode to RootNode
403  typedef typename InvertedTree<RootNodeT, RootNodeT::LEVEL>::Type InvTreeT;
404  // Remove all tree node types that are excluded from the cache
405  typedef typename boost::mpl::begin<InvTreeT>::type BeginT;
406  typedef typename boost::mpl::advance<BeginT,boost::mpl::int_<CacheLevels> >::type FirstT;
407  typedef typename boost::mpl::find<InvTreeT, RootNodeT>::type LastT;
408  typedef typename boost::mpl::erase<InvTreeT,FirstT,LastT>::type SubtreeT;
409  typedef CacheItem<ValueAccessor, SubtreeT, boost::mpl::size<SubtreeT>::value==1> CacheItemT;
410 
411  // Private member data
412  mutable CacheItemT mCache;
413  mutable MutexType mMutex;
414 
415 }; // class ValueAccessor
416 
417 
422 template<typename TreeType>
423 struct ValueAccessor<TreeType, 0, tbb::null_mutex>: public ValueAccessor0<TreeType>
424 {
427  virtual ~ValueAccessor() {}
428 };
429 
430 
432 template<typename TreeType>
433 struct ValueAccessor<TreeType, 1, tbb::null_mutex>: public ValueAccessor1<TreeType>
434 {
437  virtual ~ValueAccessor() {}
438 };
439 
440 
442 template<typename TreeType>
443 struct ValueAccessor<TreeType, 2, tbb::null_mutex>: public ValueAccessor2<TreeType>
444 {
447  virtual ~ValueAccessor() {}
448 };
449 
450 
452 template<typename TreeType>
453 struct ValueAccessor<TreeType, 3, tbb::null_mutex>: public ValueAccessor3<TreeType>
454 {
457  virtual ~ValueAccessor() {}
458 };
459 
460 
462 
463 
468 template<typename TreeType>
469 struct ValueAccessorRW: public ValueAccessor<TreeType, TreeType::DEPTH-1, tbb::spin_mutex>
470 {
472  : ValueAccessor<TreeType, TreeType::DEPTH-1, tbb::spin_mutex>(tree)
473  {
474  }
475 };
476 
477 
479 
480 
484 
494 template<typename HeadT, int HeadLevel>
495 struct InvertedTree {
496  typedef typename InvertedTree<typename HeadT::ChildNodeType, HeadLevel-1>::Type SubtreeT;
497  typedef typename boost::mpl::push_back<SubtreeT, HeadT>::type Type;
498 };
502 template<typename HeadT>
503 struct InvertedTree<HeadT, /*HeadLevel=*/1> {
504  typedef typename boost::mpl::vector<typename HeadT::ChildNodeType, HeadT>::type Type;
505 };
506 
507 
508 // An element of a compile-time linked list of node pointers, ordered from LeafNode to RootNode
509 template<typename TreeCacheT, typename NodeVecT, bool AtRoot>
510 class CacheItem
511 {
512 public:
513  typedef typename boost::mpl::front<NodeVecT>::type NodeType;
514  typedef typename NodeType::ValueType ValueType;
515  typedef typename NodeType::LeafNodeType LeafNodeType;
516  typedef std::numeric_limits<Int32> CoordLimits;
517 
518  CacheItem(TreeCacheT& parent):
519  mParent(&parent),
520  mHash(CoordLimits::max()),
521  mNode(NULL),
522  mNext(parent)
523  {
524  }
525 
527  CacheItem(TreeCacheT& parent, const CacheItem& other):
529  mParent(&parent),
530  mHash(other.mHash),
531  mNode(other.mNode),
532  mNext(parent, other.mNext)
533  {
534  }
535 
536  CacheItem& copy(TreeCacheT& parent, const CacheItem& other)
537  {
538  mParent = &parent;
539  mHash = other.mHash;
540  mNode = other.mNode;
541  mNext.copy(parent, other.mNext);
542  return *this;
543  }
545 
546  bool isCached(const Coord& xyz) const
547  {
548  return (this->isHashed(xyz) || mNext.isCached(xyz));
549  }
550 
552  void insert(const Coord& xyz, const NodeType* node)
553  {
554  mHash = (node != NULL) ? xyz & ~(NodeType::DIM-1) : Coord::max();
555  mNode = node;
556  }
558  template<typename OtherNodeType>
559  void insert(const Coord& xyz, const OtherNodeType* node) { mNext.insert(xyz, node); }
560 
562  void erase(const NodeType*) { mHash = Coord::max(); mNode = NULL; }
564  template<typename OtherNodeType>
565  void erase(const OtherNodeType* node) { mNext.erase(node); }
566 
568  void clear() { mHash = Coord::max(); mNode = NULL; mNext.clear(); }
569 
571  void getNode(const NodeType*& node) const { node = mNode; }
572  void getNode(const NodeType*& node) { node = mNode; }
573  void getNode(NodeType*& node)
574  {
575  // This combination of a static assertion and a const_cast might not be elegant,
576  // but it is a lot simpler than specializing TreeCache for const Trees.
577  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
578  node = const_cast<NodeType*>(mNode);
579  }
581  template<typename OtherNodeType>
582  void getNode(OtherNodeType*& node) { mNext.getNode(node); }
583 
585  const ValueType& getValue(const Coord& xyz)
586  {
587  if (this->isHashed(xyz)) {
588  assert(mNode);
589  return mNode->getValueAndCache(xyz, *mParent);
590  }
591  return mNext.getValue(xyz);
592  }
593 
594  void addLeaf(LeafNodeType* leaf)
595  {
596  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
597  if (NodeType::LEVEL == 0) return;
598  if (this->isHashed(leaf->origin())) {
599  assert(mNode);
600  return const_cast<NodeType*>(mNode)->addLeafAndCache(leaf, *mParent);
601  }
602  mNext.addLeaf(leaf);
603  }
604 
605  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
606  {
607  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
608  if (NodeType::LEVEL < level) return;
609  if (this->isHashed(xyz)) {
610  assert(mNode);
611  return const_cast<NodeType*>(mNode)->addTileAndCache(level, xyz, value, state, *mParent);
612  }
613  mNext.addTile(level, xyz, value, state);
614  }
615 
617  {
618  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
619  if (this->isHashed(xyz)) {
620  assert(mNode);
621  return const_cast<NodeType*>(mNode)->touchLeafAndCache(xyz, *mParent);
622  }
623  return mNext.touchLeaf(xyz);
624  }
625 
627  {
628  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
629  if (this->isHashed(xyz)) {
630  assert(mNode);
631  return const_cast<NodeType*>(mNode)->probeLeafAndCache(xyz, *mParent);
632  }
633  return mNext.probeLeaf(xyz);
634  }
635 
636  const LeafNodeType* probeConstLeaf(const Coord& xyz)
637  {
638  if (this->isHashed(xyz)) {
639  assert(mNode);
640  return mNode->probeConstLeafAndCache(xyz, *mParent);
641  }
642  return mNext.probeConstLeaf(xyz);
643  }
644 
646  bool isValueOn(const Coord& xyz)
647  {
648  if (this->isHashed(xyz)) {
649  assert(mNode);
650  return mNode->isValueOnAndCache(xyz, *mParent);
651  }
652  return mNext.isValueOn(xyz);
653  }
654 
656  bool probeValue(const Coord& xyz, ValueType& value)
657  {
658  if (this->isHashed(xyz)) {
659  assert(mNode);
660  return mNode->probeValueAndCache(xyz, value, *mParent);
661  }
662  return mNext.probeValue(xyz, value);
663  }
664 
665  int getValueDepth(const Coord& xyz)
666  {
667  if (this->isHashed(xyz)) {
668  assert(mNode);
669  return static_cast<int>(TreeCacheT::RootNodeT::LEVEL) -
670  static_cast<int>(mNode->getValueLevelAndCache(xyz, *mParent));
671  } else {
672  return mNext.getValueDepth(xyz);
673  }
674  }
675 
676  bool isVoxel(const Coord& xyz)
677  {
678  if (this->isHashed(xyz)) {
679  assert(mNode);
680  return mNode->getValueLevelAndCache(xyz, *mParent)==0;
681  } else {
682  return mNext.isVoxel(xyz);
683  }
684  }
685 
687  void setValue(const Coord& xyz, const ValueType& value)
688  {
689  if (this->isHashed(xyz)) {
690  assert(mNode);
691  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
692  const_cast<NodeType*>(mNode)->setValueAndCache(xyz, value, *mParent);
693  } else {
694  mNext.setValue(xyz, value);
695  }
696  }
697  void setValueOnly(const Coord& xyz, const ValueType& value)
698  {
699  if (this->isHashed(xyz)) {
700  assert(mNode);
701  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
702  const_cast<NodeType*>(mNode)->setValueOnlyAndCache(xyz, value, *mParent);
703  } else {
704  mNext.setValueOnly(xyz, value);
705  }
706  }
707  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
708 
711  void setValueOnSum(const Coord& xyz, const ValueType& value)
712  {
713  if (this->isHashed(xyz)) {
714  assert(mNode);
715  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
716  const_cast<NodeType*>(mNode)->setValueOnSumAndCache(xyz, value, *mParent);
717  } else {
718  mNext.setValueOnSum(xyz, value);
719  }
720  }
721 
723  void setValueOff(const Coord& xyz, const ValueType& value)
724  {
725  if (this->isHashed(xyz)) {
726  assert(mNode);
727  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
728  const_cast<NodeType*>(mNode)->setValueOffAndCache(xyz, value, *mParent);
729  } else {
730  mNext.setValueOff(xyz, value);
731  }
732  }
733 
735  void setActiveState(const Coord& xyz, bool on)
736  {
737  if (this->isHashed(xyz)) {
738  assert(mNode);
739  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
740  const_cast<NodeType*>(mNode)->setActiveStateAndCache(xyz, on, *mParent);
741  } else {
742  mNext.setActiveState(xyz, on);
743  }
744  }
745 
746 private:
747  CacheItem(const CacheItem&);
748  CacheItem& operator=(const CacheItem&);
749 
750  bool isHashed(const Coord& xyz) const
751  {
752  return (xyz[0] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[0]
753  && (xyz[1] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[1]
754  && (xyz[2] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[2];
755  }
756 
757  TreeCacheT* mParent;
758  Coord mHash;
759  const NodeType* mNode;
760  typedef typename boost::mpl::pop_front<NodeVecT>::type RestT; // NodeVecT minus its first item
761  CacheItem<TreeCacheT, RestT, /*AtRoot=*/boost::mpl::size<RestT>::value == 1> mNext;
762 };// end of CacheItem
763 
764 
766 template<typename TreeCacheT, typename NodeVecT>
767 class CacheItem<TreeCacheT, NodeVecT, /*AtRoot=*/true>
768 {
769 public:
770  typedef typename boost::mpl::front<NodeVecT>::type RootNodeType;
771  typedef typename RootNodeType::ValueType ValueType;
772  typedef typename RootNodeType::LeafNodeType LeafNodeType;
773 
774  CacheItem(TreeCacheT& parent): mParent(&parent), mRoot(NULL) {}
775  CacheItem(TreeCacheT& parent, const CacheItem& other): mParent(&parent), mRoot(other.mRoot) {}
776 
777  CacheItem& copy(TreeCacheT& parent, const CacheItem& other)
778  {
779  mParent = &parent;
780  mRoot = other.mRoot;
781  return *this;
782  }
783 
784  bool isCached(const Coord& xyz) const { return this->isHashed(xyz); }
785 
786  void insert(const Coord&, const RootNodeType* root) { mRoot = root; }
787 
788  // Needed for node types that are not cached
789  template <typename OtherNodeType>
790  void insert(const Coord&, const OtherNodeType*) {}
791 
792  void erase(const RootNodeType*) { mRoot = NULL; }
793 
794  void clear() { mRoot = NULL; }
795 
796  void getNode(RootNodeType*& node)
797  {
798  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
799  node = const_cast<RootNodeType*>(mRoot);
800  }
801  void getNode(const RootNodeType*& node) const { node = mRoot; }
802 
803  void addLeaf(LeafNodeType* leaf)
804  {
805  assert(mRoot);
806  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
807  const_cast<RootNodeType*>(mRoot)->addLeafAndCache(leaf, *mParent);
808  }
809 
810  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
811  {
812  assert(mRoot);
813  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
814  const_cast<RootNodeType*>(mRoot)->addTileAndCache(level, xyz, value, state, *mParent);
815  }
816 
818  {
819  assert(mRoot);
820  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
821  return const_cast<RootNodeType*>(mRoot)->touchLeafAndCache(xyz, *mParent);
822  }
823 
825  {
826  assert(mRoot);
827  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
828  return const_cast<RootNodeType*>(mRoot)->probeLeafAndCache(xyz, *mParent);
829  }
830 
831  const LeafNodeType* probeConstLeaf(const Coord& xyz)
832  {
833  assert(mRoot);
834  return mRoot->probeConstLeafAndCache(xyz, *mParent);
835  }
836 
837  int getValueDepth(const Coord& xyz)
838  {
839  assert(mRoot);
840  return mRoot->getValueDepthAndCache(xyz, *mParent);
841  }
842  bool isValueOn(const Coord& xyz)
843  {
844  assert(mRoot);
845  return mRoot->isValueOnAndCache(xyz, *mParent);
846  }
847 
848  bool probeValue(const Coord& xyz, ValueType& value)
849  {
850  assert(mRoot);
851  return mRoot->probeValueAndCache(xyz, value, *mParent);
852  }
853  bool isVoxel(const Coord& xyz)
854  {
855  assert(mRoot);
856  return mRoot->getValueDepthAndCache(xyz, *mParent) ==
857  static_cast<int>(RootNodeType::LEVEL);
858  }
859  const ValueType& getValue(const Coord& xyz)
860  {
861  assert(mRoot);
862  return mRoot->getValueAndCache(xyz, *mParent);
863  }
864 
865  void setValue(const Coord& xyz, const ValueType& value)
866  {
867  assert(mRoot);
868  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
869  const_cast<RootNodeType*>(mRoot)->setValueAndCache(xyz, value, *mParent);
870  }
871  void setValueOnly(const Coord& xyz, const ValueType& value)
872  {
873  assert(mRoot);
874  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
875  const_cast<RootNodeType*>(mRoot)->setValueOnlyAndCache(xyz, value, *mParent);
876  }
877  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
878 
879  void setValueOnSum(const Coord& xyz, const ValueType& value)
880  {
881  assert(mRoot);
882  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
883  const_cast<RootNodeType*>(mRoot)->setValueOnSumAndCache(xyz, value, *mParent);
884  }
885 
886  void setValueOff(const Coord& xyz, const ValueType& value)
887  {
888  assert(mRoot);
889  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
890  const_cast<RootNodeType*>(mRoot)->setValueOffAndCache(xyz, value, *mParent);
891  }
892 
893  void setActiveState(const Coord& xyz, bool on)
894  {
895  assert(mRoot);
896  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
897  const_cast<RootNodeType*>(mRoot)->setActiveStateAndCache(xyz, on, *mParent);
898  }
899 
900 private:
901  CacheItem(const CacheItem&);
902  CacheItem& operator=(const CacheItem&);
903 
904  bool isHashed(const Coord&) const { return false; }
905 
906  TreeCacheT* mParent;
907  const RootNodeType* mRoot;
908 };// end of CacheItem specialized for RootNode
909 
910 
912 
913 
918 template<typename _TreeType>
919 class ValueAccessor0 : public ValueAccessorBase<_TreeType>
920 {
921 public:
922  typedef _TreeType TreeType;
923  typedef typename TreeType::ValueType ValueType;
924  typedef typename TreeType::RootNodeType RootNodeT;
925  typedef typename TreeType::LeafNodeType LeafNodeT;
927 
928  ValueAccessor0(TreeType& tree) : BaseT(tree) {}
929 
930  ValueAccessor0(const ValueAccessor0& other) : BaseT(other) {}
931 
933  static Index numCacheLevels() { return 0; }
934 
936  {
937  if (&other != this) this->BaseT::operator=(other);
938  return *this;
939  }
940 
941  virtual ~ValueAccessor0() {}
942 
944  bool isCached(const Coord&) const { return false; }
945 
947  const ValueType& getValue(const Coord& xyz) const
948  {
949  assert(BaseT::mTree);
950  return BaseT::mTree->getValue(xyz);
951  }
952 
954  bool isValueOn(const Coord& xyz) const
955  {
956  assert(BaseT::mTree);
957  return BaseT::mTree->isValueOn(xyz);
958  }
959 
961  bool probeValue(const Coord& xyz, ValueType& value) const
962  {
963  assert(BaseT::mTree);
964  return BaseT::mTree->probeValue(xyz, value);
965  }
966 
970  int getValueDepth(const Coord& xyz) const
971  {
972  assert(BaseT::mTree);
973  return BaseT::mTree->getValueDepth(xyz);
974  }
975 
978  bool isVoxel(const Coord& xyz) const
979  {
980  assert(BaseT::mTree);
981  return BaseT::mTree->getValueDepth(xyz) == static_cast<int>(RootNodeT::LEVEL);
982  }
983 
985  void setValue(const Coord& xyz, const ValueType& value)
987  {
988  assert(BaseT::mTree);
989  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
990  BaseT::mTree->setValue(xyz, value);
991  }
992  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
994 
996  void setValueOnly(const Coord& xyz, const ValueType& value)
997  {
998  assert(BaseT::mTree);
999  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1000  BaseT::mTree->setValueOnly(xyz, value);
1001  }
1002 
1004  void setValueOff(const Coord& xyz, const ValueType& value)
1005  {
1006  assert(BaseT::mTree);
1007  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1008  BaseT::mTree->root().setValueOff(xyz, value);
1009  }
1010 
1013  void setValueOnSum(const Coord& xyz, const ValueType& value)
1014  {
1015  assert(BaseT::mTree);
1016  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1017  BaseT::mTree->setValueOnSum(xyz, value);
1018  }
1019 
1021  void setActiveState(const Coord& xyz, bool on = true)
1022  {
1023  assert(BaseT::mTree);
1024  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1025  BaseT::mTree->setActiveState(xyz, on);
1026  }
1028  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
1030  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
1031 
1033  template<typename NodeT> NodeT* getNode() { return NULL; }
1034 
1037  template<typename NodeT> void insertNode(const Coord&, NodeT&) {}
1038 
1041  void addLeaf(LeafNodeT* leaf)
1042  {
1043  assert(BaseT::mTree);
1044  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1045  BaseT::mTree->root().addLeaf(leaf);
1046  }
1047 
1051  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
1052  {
1053  assert(BaseT::mTree);
1054  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1055  BaseT::mTree->root().addTile(level, xyz, value, state);
1056  }
1057 
1061  template<typename NodeT> void eraseNode() {}
1062 
1064  {
1065  assert(BaseT::mTree);
1066  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1067  return BaseT::mTree->touchLeaf(xyz);
1068  }
1069 
1070  template <typename NodeT>
1071  NodeT* probeNode(const Coord& xyz)
1072  {
1073  assert(BaseT::mTree);
1074  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1075  return BaseT::mTree->template probeNode<NodeT>(xyz);
1076  }
1077 
1078  template <typename NodeT>
1079  const NodeT* probeConstNode(const Coord& xyz) const
1080  {
1081  assert(BaseT::mTree);
1082  return BaseT::mTree->template probeConstNode<NodeT>(xyz);
1083  }
1084 
1086  {
1087  return this->template probeNode<LeafNodeT>(xyz);
1088  }
1089 
1090  const LeafNodeT* probeConstLeaf(const Coord& xyz) const
1091  {
1092  return this->template probeConstNode<LeafNodeT>(xyz);
1093  }
1094 
1095  const LeafNodeT* probeLeaf(const Coord& xyz) const
1096  {
1097  return this->probeConstLeaf(xyz);
1098  }
1099 
1101  virtual void clear() {}
1102 
1103 private:
1104  // Allow trees to deregister themselves.
1105  template<typename> friend class Tree;
1106 
1109  virtual void release() { this->BaseT::release(); }
1110 
1111 }; // ValueAccessor0
1112 
1113 
1120 template<typename _TreeType, Index L0>
1121 class ValueAccessor1 : public ValueAccessorBase<_TreeType>
1122 {
1123 public:
1124  BOOST_STATIC_ASSERT(_TreeType::DEPTH >= 2);
1125  BOOST_STATIC_ASSERT( L0 < _TreeType::RootNodeType::LEVEL );
1126  typedef _TreeType TreeType;
1127  typedef typename TreeType::ValueType ValueType;
1128  typedef typename TreeType::RootNodeType RootNodeT;
1129  typedef typename TreeType::LeafNodeType LeafNodeT;
1132  typedef typename boost::mpl::at<InvTreeT, boost::mpl::int_<L0> >::type NodeT0;
1133 
1135  ValueAccessor1(TreeType& tree) : BaseT(tree), mKey0(Coord::max()), mNode0(NULL)
1136  {
1137  }
1138 
1140  ValueAccessor1(const ValueAccessor1& other) : BaseT(other) { this->copy(other); }
1141 
1143  static Index numCacheLevels() { return 1; }
1144 
1147  {
1148  if (&other != this) {
1149  this->BaseT::operator=(other);
1150  this->copy(other);
1151  }
1152  return *this;
1153  }
1154 
1156  virtual ~ValueAccessor1() {}
1157 
1160  bool isCached(const Coord& xyz) const
1161  {
1162  assert(BaseT::mTree);
1163  return this->isHashed(xyz);
1164  }
1165 
1167  const ValueType& getValue(const Coord& xyz) const
1168  {
1169  assert(BaseT::mTree);
1170  if (this->isHashed(xyz)) {
1171  assert(mNode0);
1172  return mNode0->getValueAndCache(xyz, this->self());
1173  }
1174  return BaseT::mTree->root().getValueAndCache(xyz, this->self());
1175  }
1176 
1178  bool isValueOn(const Coord& xyz) const
1179  {
1180  assert(BaseT::mTree);
1181  if (this->isHashed(xyz)) {
1182  assert(mNode0);
1183  return mNode0->isValueOnAndCache(xyz, this->self());
1184  }
1185  return BaseT::mTree->root().isValueOnAndCache(xyz, this->self());
1186  }
1187 
1189  bool probeValue(const Coord& xyz, ValueType& value) const
1190  {
1191  assert(BaseT::mTree);
1192  if (this->isHashed(xyz)) {
1193  assert(mNode0);
1194  return mNode0->probeValueAndCache(xyz, value, this->self());
1195  }
1196  return BaseT::mTree->root().probeValueAndCache(xyz, value, this->self());
1197  }
1198 
1202  int getValueDepth(const Coord& xyz) const
1203  {
1204  assert(BaseT::mTree);
1205  if (this->isHashed(xyz)) {
1206  assert(mNode0);
1207  return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->self());
1208  }
1209  return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self());
1210  }
1211 
1214  bool isVoxel(const Coord& xyz) const
1215  {
1216  assert(BaseT::mTree);
1217  if (this->isHashed(xyz)) {
1218  assert(mNode0);
1219  return mNode0->getValueLevelAndCache(xyz, this->self()) == 0;
1220  }
1221  return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self()) ==
1222  static_cast<int>(RootNodeT::LEVEL);
1223  }
1224 
1226  void setValue(const Coord& xyz, const ValueType& value)
1228  {
1229  assert(BaseT::mTree);
1230  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1231  if (this->isHashed(xyz)) {
1232  assert(mNode0);
1233  const_cast<NodeT0*>(mNode0)->setValueAndCache(xyz, value, *this);
1234  } else {
1235  BaseT::mTree->root().setValueAndCache(xyz, value, *this);
1236  }
1237  }
1238  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
1240 
1242  void setValueOnly(const Coord& xyz, const ValueType& value)
1243  {
1244  assert(BaseT::mTree);
1245  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1246  if (this->isHashed(xyz)) {
1247  assert(mNode0);
1248  const_cast<NodeT0*>(mNode0)->setValueOnlyAndCache(xyz, value, *this);
1249  } else {
1250  BaseT::mTree->root().setValueOnlyAndCache(xyz, value, *this);
1251  }
1252  }
1253 
1255  void setValueOff(const Coord& xyz, const ValueType& value)
1256  {
1257  assert(BaseT::mTree);
1258  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1259  if (this->isHashed(xyz)) {
1260  assert(mNode0);
1261  const_cast<NodeT0*>(mNode0)->setValueOffAndCache(xyz, value, *this);
1262  } else {
1263  BaseT::mTree->root().setValueOffAndCache(xyz, value, *this);
1264  }
1265  }
1266 
1269  void setValueOnSum(const Coord& xyz, const ValueType& value)
1270  {
1271  assert(BaseT::mTree);
1272  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1273  if (this->isHashed(xyz)) {
1274  assert(mNode0);
1275  const_cast<NodeT0*>(mNode0)->setValueOnSumAndCache(xyz, value, *this);
1276  } else {
1277  BaseT::mTree->root().setValueOnSumAndCache(xyz, value, *this);
1278  }
1279  }
1280 
1282  void setActiveState(const Coord& xyz, bool on = true)
1283  {
1284  assert(BaseT::mTree);
1285  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1286  if (this->isHashed(xyz)) {
1287  assert(mNode0);
1288  const_cast<NodeT0*>(mNode0)->setActiveStateAndCache(xyz, on, *this);
1289  } else {
1290  BaseT::mTree->root().setActiveStateAndCache(xyz, on, *this);
1291  }
1292  }
1294  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
1296  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
1297 
1299  template<typename NodeT>
1300  NodeT* getNode()
1301  {
1302  const NodeT* node = NULL;
1303  this->getNode(node);
1304  return const_cast<NodeT*>(node);
1305  }
1306 
1309  template<typename NodeT>
1310  void insertNode(const Coord& xyz, NodeT& node) { this->insert(xyz, &node); }
1311 
1315  template<typename NodeT>
1316  void eraseNode()
1317  {
1318  const NodeT* node = NULL;
1319  this->eraseNode(node);
1320  }
1321 
1324  void addLeaf(LeafNodeT* leaf)
1325  {
1326  assert(BaseT::mTree);
1327  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1328  BaseT::mTree->root().addLeaf(leaf);
1329  }
1330 
1334  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
1335  {
1336  assert(BaseT::mTree);
1337  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1338  BaseT::mTree->root().addTile(level, xyz, value, state);
1339  }
1340 
1347  LeafNodeT* touchLeaf(const Coord& xyz)
1348  {
1349  assert(BaseT::mTree);
1350  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1351  if (this->isHashed(xyz)) {
1352  assert(mNode0);
1353  return const_cast<NodeT0*>(mNode0)->touchLeafAndCache(xyz, *this);
1354  }
1355  return BaseT::mTree->root().touchLeafAndCache(xyz, *this);
1356  }
1357 
1360  template <typename NodeT>
1361  NodeT* probeNode(const Coord& xyz)
1362  {
1363  assert(BaseT::mTree);
1364  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1366  if ((boost::is_same<NodeT, NodeT0>::value)) {
1367  if (this->isHashed(xyz)) {
1368  assert(mNode0);
1369  return reinterpret_cast<NodeT*>(const_cast<NodeT0*>(mNode0));
1370  }
1371  return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
1372  }
1373  return NULL;
1375  }
1376  LeafNodeT* probeLeaf(const Coord& xyz)
1377  {
1378  return this->template probeNode<LeafNodeT>(xyz);
1379  }
1380 
1383  template <typename NodeT>
1384  const NodeT* probeConstNode(const Coord& xyz) const
1385  {
1386  assert(BaseT::mTree);
1388  if ((boost::is_same<NodeT, NodeT0>::value)) {
1389  if (this->isHashed(xyz)) {
1390  assert(mNode0);
1391  return reinterpret_cast<const NodeT*>(mNode0);
1392  }
1393  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
1394  }
1395  return NULL;
1397  }
1398  const LeafNodeT* probeConstLeaf(const Coord& xyz) const
1399  {
1400  return this->template probeConstNode<LeafNodeT>(xyz);
1401  }
1402  const LeafNodeT* probeLeaf(const Coord& xyz) const { return this->probeConstLeaf(xyz); }
1403 
1405  virtual void clear()
1406  {
1407  mKey0 = Coord::max();
1408  mNode0 = NULL;
1409  }
1410 
1411 private:
1412  // Allow nodes to insert themselves into the cache.
1413  template<typename> friend class RootNode;
1414  template<typename, Index> friend class InternalNode;
1415  template<typename, Index> friend class LeafNode;
1416  // Allow trees to deregister themselves.
1417  template<typename> friend class Tree;
1418 
1419  // This private method is merely for convenience.
1420  inline ValueAccessor1& self() const { return const_cast<ValueAccessor1&>(*this); }
1421 
1422  void getNode(const NodeT0*& node) { node = mNode0; }
1423  void getNode(const RootNodeT*& node)
1424  {
1425  node = (BaseT::mTree ? &BaseT::mTree->root() : NULL);
1426  }
1427  template <typename OtherNodeType> void getNode(const OtherNodeType*& node) { node = NULL; }
1428  void eraseNode(const NodeT0*) { mKey0 = Coord::max(); mNode0 = NULL; }
1429  template <typename OtherNodeType> void eraseNode(const OtherNodeType*) {}
1430 
1432  inline void copy(const ValueAccessor1& other)
1433  {
1434  mKey0 = other.mKey0;
1435  mNode0 = other.mNode0;
1436  }
1437 
1440  virtual void release()
1441  {
1442  this->BaseT::release();
1443  this->clear();
1444  }
1449  inline void insert(const Coord& xyz, const NodeT0* node)
1450  {
1451  assert(node);
1452  mKey0 = xyz & ~(NodeT0::DIM-1);
1453  mNode0 = node;
1454  }
1455 
1458  template<typename OtherNodeType> inline void insert(const Coord&, const OtherNodeType*) {}
1459 
1460  inline bool isHashed(const Coord& xyz) const
1461  {
1462  return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
1463  && (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
1464  && (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
1465  }
1466  mutable Coord mKey0;
1467  mutable const NodeT0* mNode0;
1468 }; // ValueAccessor1
1469 
1470 
1478 template<typename _TreeType, Index L0, Index L1>
1479 class ValueAccessor2 : public ValueAccessorBase<_TreeType>
1480 {
1481 public:
1482  BOOST_STATIC_ASSERT(_TreeType::DEPTH >= 3);
1483  BOOST_STATIC_ASSERT( L0 < L1 && L1 < _TreeType::RootNodeType::LEVEL );
1484  typedef _TreeType TreeType;
1485  typedef typename TreeType::ValueType ValueType;
1486  typedef typename TreeType::RootNodeType RootNodeT;
1487  typedef typename TreeType::LeafNodeType LeafNodeT;
1490  typedef typename boost::mpl::at<InvTreeT, boost::mpl::int_<L0> >::type NodeT0;
1491  typedef typename boost::mpl::at<InvTreeT, boost::mpl::int_<L1> >::type NodeT1;
1492 
1494  ValueAccessor2(TreeType& tree) : BaseT(tree),
1495  mKey0(Coord::max()), mNode0(NULL),
1496  mKey1(Coord::max()), mNode1(NULL) {}
1497 
1499  ValueAccessor2(const ValueAccessor2& other) : BaseT(other) { this->copy(other); }
1500 
1502  static Index numCacheLevels() { return 2; }
1503 
1506  {
1507  if (&other != this) {
1508  this->BaseT::operator=(other);
1509  this->copy(other);
1510  }
1511  return *this;
1512  }
1513 
1515  virtual ~ValueAccessor2() {}
1516 
1519  bool isCached(const Coord& xyz) const
1520  {
1521  assert(BaseT::mTree);
1522  return this->isHashed1(xyz) || this->isHashed0(xyz);
1523  }
1524 
1526  const ValueType& getValue(const Coord& xyz) const
1527  {
1528  assert(BaseT::mTree);
1529  if (this->isHashed0(xyz)) {
1530  assert(mNode0);
1531  return mNode0->getValueAndCache(xyz, this->self());
1532  } else if (this->isHashed1(xyz)) {
1533  assert(mNode1);
1534  return mNode1->getValueAndCache(xyz, this->self());
1535  }
1536  return BaseT::mTree->root().getValueAndCache(xyz, this->self());
1537  }
1538 
1540  bool isValueOn(const Coord& xyz) const
1541  {
1542  assert(BaseT::mTree);
1543  if (this->isHashed0(xyz)) {
1544  assert(mNode0);
1545  return mNode0->isValueOnAndCache(xyz, this->self());
1546  } else if (this->isHashed1(xyz)) {
1547  assert(mNode1);
1548  return mNode1->isValueOnAndCache(xyz, this->self());
1549  }
1550  return BaseT::mTree->root().isValueOnAndCache(xyz, this->self());
1551  }
1552 
1554  bool probeValue(const Coord& xyz, ValueType& value) const
1555  {
1556  assert(BaseT::mTree);
1557  if (this->isHashed0(xyz)) {
1558  assert(mNode0);
1559  return mNode0->probeValueAndCache(xyz, value, this->self());
1560  } else if (this->isHashed1(xyz)) {
1561  assert(mNode1);
1562  return mNode1->probeValueAndCache(xyz, value, this->self());
1563  }
1564  return BaseT::mTree->root().probeValueAndCache(xyz, value, this->self());
1565  }
1566 
1570  int getValueDepth(const Coord& xyz) const
1571  {
1572  assert(BaseT::mTree);
1573  if (this->isHashed0(xyz)) {
1574  assert(mNode0);
1575  return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->self());
1576  } else if (this->isHashed1(xyz)) {
1577  assert(mNode1);
1578  return RootNodeT::LEVEL - mNode1->getValueLevelAndCache(xyz, this->self());
1579  }
1580  return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self());
1581  }
1582 
1585  bool isVoxel(const Coord& xyz) const
1586  {
1587  assert(BaseT::mTree);
1588  if (this->isHashed0(xyz)) {
1589  assert(mNode0);
1590  return mNode0->getValueLevelAndCache(xyz, this->self())==0;
1591  } else if (this->isHashed1(xyz)) {
1592  assert(mNode1);
1593  return mNode1->getValueLevelAndCache(xyz, this->self())==0;
1594  }
1595  return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self()) ==
1596  static_cast<int>(RootNodeT::LEVEL);
1597  }
1598 
1600  void setValue(const Coord& xyz, const ValueType& value)
1602  {
1603  assert(BaseT::mTree);
1604  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1605  if (this->isHashed0(xyz)) {
1606  assert(mNode0);
1607  const_cast<NodeT0*>(mNode0)->setValueAndCache(xyz, value, *this);
1608  } else if (this->isHashed1(xyz)) {
1609  assert(mNode1);
1610  const_cast<NodeT1*>(mNode1)->setValueAndCache(xyz, value, *this);
1611  } else {
1612  BaseT::mTree->root().setValueAndCache(xyz, value, *this);
1613  }
1614  }
1615  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
1617 
1619  void setValueOnly(const Coord& xyz, const ValueType& value)
1620  {
1621  assert(BaseT::mTree);
1622  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1623  if (this->isHashed0(xyz)) {
1624  assert(mNode0);
1625  const_cast<NodeT0*>(mNode0)->setValueOnlyAndCache(xyz, value, *this);
1626  } else if (this->isHashed1(xyz)) {
1627  assert(mNode1);
1628  const_cast<NodeT1*>(mNode1)->setValueOnlyAndCache(xyz, value, *this);
1629  } else {
1630  BaseT::mTree->root().setValueOnlyAndCache(xyz, value, *this);
1631  }
1632  }
1633 
1635  void setValueOff(const Coord& xyz, const ValueType& value)
1636  {
1637  assert(BaseT::mTree);
1638  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1639  if (this->isHashed0(xyz)) {
1640  assert(mNode0);
1641  const_cast<NodeT0*>(mNode0)->setValueOffAndCache(xyz, value, *this);
1642  } else if (this->isHashed1(xyz)) {
1643  assert(mNode1);
1644  const_cast<NodeT1*>(mNode1)->setValueOffAndCache(xyz, value, *this);
1645  } else {
1646  BaseT::mTree->root().setValueOffAndCache(xyz, value, *this);
1647  }
1648  }
1649 
1652  void setValueOnSum(const Coord& xyz, const ValueType& value)
1653  {
1654  assert(BaseT::mTree);
1655  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1656  if (this->isHashed0(xyz)) {
1657  assert(mNode0);
1658  const_cast<NodeT0*>(mNode0)->setValueOnSumAndCache(xyz, value, *this);
1659  } else if (this->isHashed1(xyz)) {
1660  assert(mNode1);
1661  const_cast<NodeT1*>(mNode1)->setValueOnSumAndCache(xyz, value, *this);
1662  } else {
1663  BaseT::mTree->root().setValueOnSumAndCache(xyz, value, *this);
1664  }
1665  }
1666 
1668  void setActiveState(const Coord& xyz, bool on = true)
1669  {
1670  assert(BaseT::mTree);
1671  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1672  if (this->isHashed0(xyz)) {
1673  assert(mNode0);
1674  const_cast<NodeT0*>(mNode0)->setActiveStateAndCache(xyz, on, *this);
1675  } else if (this->isHashed1(xyz)) {
1676  assert(mNode1);
1677  const_cast<NodeT1*>(mNode1)->setActiveStateAndCache(xyz, on, *this);
1678  } else {
1679  BaseT::mTree->root().setActiveStateAndCache(xyz, on, *this);
1680  }
1681  }
1683  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
1685  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
1686 
1688  template<typename NodeT>
1689  NodeT* getNode()
1690  {
1691  const NodeT* node = NULL;
1692  this->getNode(node);
1693  return const_cast<NodeT*>(node);
1694  }
1695 
1698  template<typename NodeT>
1699  void insertNode(const Coord& xyz, NodeT& node) { this->insert(xyz, &node); }
1700 
1704  template<typename NodeT>
1705  void eraseNode()
1706  {
1707  const NodeT* node = NULL;
1708  this->eraseNode(node);
1709  }
1710 
1713  void addLeaf(LeafNodeT* leaf)
1714  {
1715  assert(BaseT::mTree);
1716  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1717  if (this->isHashed1(leaf->origin())) {
1718  assert(mNode1);
1719  return const_cast<NodeT1*>(mNode1)->addLeafAndCache(leaf, *this);
1720  }
1721  BaseT::mTree->root().addLeafAndCache(leaf, *this);
1722  }
1723 
1727  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
1728  {
1729  assert(BaseT::mTree);
1730  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1731  if (this->isHashed1(xyz)) {
1732  assert(mNode1);
1733  return const_cast<NodeT1*>(mNode1)->addTileAndCache(level, xyz, value, state, *this);
1734  }
1735  BaseT::mTree->root().addTileAndCache(level, xyz, value, state, *this);
1736  }
1737 
1744  LeafNodeT* touchLeaf(const Coord& xyz)
1745  {
1746  assert(BaseT::mTree);
1747  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1748  if (this->isHashed0(xyz)) {
1749  assert(mNode0);
1750  return const_cast<NodeT0*>(mNode0)->touchLeafAndCache(xyz, *this);
1751  } else if (this->isHashed1(xyz)) {
1752  assert(mNode1);
1753  return const_cast<NodeT1*>(mNode1)->touchLeafAndCache(xyz, *this);
1754  }
1755  return BaseT::mTree->root().touchLeafAndCache(xyz, *this);
1756  }
1759  template <typename NodeT>
1760  NodeT* probeNode(const Coord& xyz)
1761  {
1762  assert(BaseT::mTree);
1763  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1765  if ((boost::is_same<NodeT, NodeT0>::value)) {
1766  if (this->isHashed0(xyz)) {
1767  assert(mNode0);
1768  return reinterpret_cast<NodeT*>(const_cast<NodeT0*>(mNode0));
1769  } else if (this->isHashed1(xyz)) {
1770  assert(mNode1);
1771  return const_cast<NodeT1*>(mNode1)->template probeNodeAndCache<NodeT>(xyz, *this);
1772  }
1773  return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
1774  } else if ((boost::is_same<NodeT, NodeT1>::value)) {
1775  if (this->isHashed1(xyz)) {
1776  assert(mNode1);
1777  return reinterpret_cast<NodeT*>(const_cast<NodeT1*>(mNode1));
1778  }
1779  return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
1780  }
1781  return NULL;
1783  }
1786  LeafNodeT* probeLeaf(const Coord& xyz) { return this->template probeNode<LeafNodeT>(xyz); }
1787 
1790  template <typename NodeT>
1791  const NodeT* probeConstLeaf(const Coord& xyz) const
1792  {
1794  if ((boost::is_same<NodeT, NodeT0>::value)) {
1795  if (this->isHashed0(xyz)) {
1796  assert(mNode0);
1797  return reinterpret_cast<const NodeT*>(mNode0);
1798  } else if (this->isHashed1(xyz)) {
1799  assert(mNode1);
1800  return mNode1->template probeConstNodeAndCache<NodeT>(xyz, this->self());
1801  }
1802  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
1803  } else if ((boost::is_same<NodeT, NodeT1>::value)) {
1804  if (this->isHashed1(xyz)) {
1805  assert(mNode1);
1806  return reinterpret_cast<const NodeT*>(mNode1);
1807  }
1808  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
1809  }
1810  return NULL;
1812  }
1815  const LeafNodeT* probeConstLeaf(const Coord& xyz) const
1816  {
1817  return this->template probeConstNode<LeafNodeT>(xyz);
1818  }
1819  const LeafNodeT* probeLeaf(const Coord& xyz) const { return this->probeConstLeaf(xyz); }
1820 
1822  virtual void clear()
1823  {
1824  mKey0 = Coord::max();
1825  mNode0 = NULL;
1826  mKey1 = Coord::max();
1827  mNode1 = NULL;
1828  }
1829 
1830 private:
1831  // Allow nodes to insert themselves into the cache.
1832  template<typename> friend class RootNode;
1833  template<typename, Index> friend class InternalNode;
1834  template<typename, Index> friend class LeafNode;
1835  // Allow trees to deregister themselves.
1836  template<typename> friend class Tree;
1837 
1838  // This private method is merely for convenience.
1839  inline ValueAccessor2& self() const { return const_cast<ValueAccessor2&>(*this); }
1840 
1841  void getNode(const NodeT0*& node) { node = mNode0; }
1842  void getNode(const NodeT1*& node) { node = mNode1; }
1843  void getNode(const RootNodeT*& node)
1844  {
1845  node = (BaseT::mTree ? &BaseT::mTree->root() : NULL);
1846  }
1847  template <typename OtherNodeType> void getNode(const OtherNodeType*& node) { node = NULL; }
1848 
1849  void eraseNode(const NodeT0*) { mKey0 = Coord::max(); mNode0 = NULL; }
1850  void eraseNode(const NodeT1*) { mKey1 = Coord::max(); mNode1 = NULL; }
1851  template <typename OtherNodeType> void eraseNode(const OtherNodeType*) {}
1852 
1854  inline void copy(const ValueAccessor2& other)
1855  {
1856  mKey0 = other.mKey0;
1857  mNode0 = other.mNode0;
1858  mKey1 = other.mKey1;
1859  mNode1 = other.mNode1;
1860  }
1861 
1864  virtual void release()
1865  {
1866  this->BaseT::release();
1867  this->clear();
1868  }
1869 
1874  inline void insert(const Coord& xyz, const NodeT0* node)
1875  {
1876  assert(node);
1877  mKey0 = xyz & ~(NodeT0::DIM-1);
1878  mNode0 = node;
1879  }
1880  inline void insert(const Coord& xyz, const NodeT1* node)
1881  {
1882  assert(node);
1883  mKey1 = xyz & ~(NodeT1::DIM-1);
1884  mNode1 = node;
1885  }
1888  template<typename NodeT> inline void insert(const Coord&, const NodeT*) {}
1889 
1890  inline bool isHashed0(const Coord& xyz) const
1891  {
1892  return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
1893  && (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
1894  && (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
1895  }
1896  inline bool isHashed1(const Coord& xyz) const
1897  {
1898  return (xyz[0] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[0]
1899  && (xyz[1] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[1]
1900  && (xyz[2] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[2];
1901  }
1902  mutable Coord mKey0;
1903  mutable const NodeT0* mNode0;
1904  mutable Coord mKey1;
1905  mutable const NodeT1* mNode1;
1906 }; // ValueAccessor2
1907 
1908 
1919 template<typename _TreeType, Index L0, Index L1, Index L2>
1920 class ValueAccessor3 : public ValueAccessorBase<_TreeType>
1921 {
1922 public:
1923  BOOST_STATIC_ASSERT(_TreeType::DEPTH >= 4);
1924  BOOST_STATIC_ASSERT(L0 < L1 && L1 < L2 && L2 < _TreeType::RootNodeType::LEVEL);
1925  typedef _TreeType TreeType;
1926  typedef typename TreeType::ValueType ValueType;
1927  typedef typename TreeType::RootNodeType RootNodeT;
1928  typedef typename TreeType::LeafNodeType LeafNodeT;
1931  typedef typename boost::mpl::at<InvTreeT, boost::mpl::int_<L0> >::type NodeT0;
1932  typedef typename boost::mpl::at<InvTreeT, boost::mpl::int_<L1> >::type NodeT1;
1933  typedef typename boost::mpl::at<InvTreeT, boost::mpl::int_<L2> >::type NodeT2;
1934 
1936  ValueAccessor3(TreeType& tree) : BaseT(tree),
1937  mKey0(Coord::max()), mNode0(NULL),
1938  mKey1(Coord::max()), mNode1(NULL),
1939  mKey2(Coord::max()), mNode2(NULL) {}
1940 
1942  ValueAccessor3(const ValueAccessor3& other) : BaseT(other) { this->copy(other); }
1943 
1946  {
1947  if (&other != this) {
1948  this->BaseT::operator=(other);
1949  this->copy(other);
1950  }
1951  return *this;
1952  }
1953 
1955  static Index numCacheLevels() { return 3; }
1956 
1958  virtual ~ValueAccessor3() {}
1959 
1962  bool isCached(const Coord& xyz) const
1963  {
1964  assert(BaseT::mTree);
1965  return this->isHashed2(xyz) || this->isHashed1(xyz) || this->isHashed0(xyz);
1966  }
1967 
1969  const ValueType& getValue(const Coord& xyz) const
1970  {
1971  assert(BaseT::mTree);
1972  if (this->isHashed0(xyz)) {
1973  assert(mNode0);
1974  return mNode0->getValueAndCache(xyz, this->self());
1975  } else if (this->isHashed1(xyz)) {
1976  assert(mNode1);
1977  return mNode1->getValueAndCache(xyz, this->self());
1978  } else if (this->isHashed2(xyz)) {
1979  assert(mNode2);
1980  return mNode2->getValueAndCache(xyz, this->self());
1981  }
1982  return BaseT::mTree->root().getValueAndCache(xyz, this->self());
1983  }
1984 
1986  bool isValueOn(const Coord& xyz) const
1987  {
1988  assert(BaseT::mTree);
1989  if (this->isHashed0(xyz)) {
1990  assert(mNode0);
1991  return mNode0->isValueOnAndCache(xyz, this->self());
1992  } else if (this->isHashed1(xyz)) {
1993  assert(mNode1);
1994  return mNode1->isValueOnAndCache(xyz, this->self());
1995  } else if (this->isHashed2(xyz)) {
1996  assert(mNode2);
1997  return mNode2->isValueOnAndCache(xyz, this->self());
1998  }
1999  return BaseT::mTree->root().isValueOnAndCache(xyz, this->self());
2000  }
2001 
2003  bool probeValue(const Coord& xyz, ValueType& value) const
2004  {
2005  assert(BaseT::mTree);
2006  if (this->isHashed0(xyz)) {
2007  assert(mNode0);
2008  return mNode0->probeValueAndCache(xyz, value, this->self());
2009  } else if (this->isHashed1(xyz)) {
2010  assert(mNode1);
2011  return mNode1->probeValueAndCache(xyz, value, this->self());
2012  } else if (this->isHashed2(xyz)) {
2013  assert(mNode2);
2014  return mNode2->probeValueAndCache(xyz, value, this->self());
2015  }
2016  return BaseT::mTree->root().probeValueAndCache(xyz, value, this->self());
2017  }
2018 
2022  int getValueDepth(const Coord& xyz) const
2023  {
2024  assert(BaseT::mTree);
2025  if (this->isHashed0(xyz)) {
2026  assert(mNode0);
2027  return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->self());
2028  } else if (this->isHashed1(xyz)) {
2029  assert(mNode1);
2030  return RootNodeT::LEVEL - mNode1->getValueLevelAndCache(xyz, this->self());
2031  } else if (this->isHashed2(xyz)) {
2032  assert(mNode2);
2033  return RootNodeT::LEVEL - mNode2->getValueLevelAndCache(xyz, this->self());
2034  }
2035  return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self());
2036  }
2037 
2040  bool isVoxel(const Coord& xyz) const
2041  {
2042  assert(BaseT::mTree);
2043  if (this->isHashed0(xyz)) {
2044  assert(mNode0);
2045  return mNode0->getValueLevelAndCache(xyz, this->self())==0;
2046  } else if (this->isHashed1(xyz)) {
2047  assert(mNode1);
2048  return mNode1->getValueLevelAndCache(xyz, this->self())==0;
2049  } else if (this->isHashed2(xyz)) {
2050  assert(mNode2);
2051  return mNode2->getValueLevelAndCache(xyz, this->self())==0;
2052  }
2053  return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self()) ==
2054  static_cast<int>(RootNodeT::LEVEL);
2055  }
2056 
2058  void setValue(const Coord& xyz, const ValueType& value)
2060  {
2061  assert(BaseT::mTree);
2062  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
2063  if (this->isHashed0(xyz)) {
2064  assert(mNode0);
2065  const_cast<NodeT0*>(mNode0)->setValueAndCache(xyz, value, *this);
2066  } else if (this->isHashed1(xyz)) {
2067  assert(mNode1);
2068  const_cast<NodeT1*>(mNode1)->setValueAndCache(xyz, value, *this);
2069  } else if (this->isHashed2(xyz)) {
2070  assert(mNode2);
2071  const_cast<NodeT2*>(mNode2)->setValueAndCache(xyz, value, *this);
2072  } else {
2073  BaseT::mTree->root().setValueAndCache(xyz, value, *this);
2074  }
2075  }
2076  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
2078 
2080  void setValueOnly(const Coord& xyz, const ValueType& value)
2081  {
2082  assert(BaseT::mTree);
2083  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
2084  if (this->isHashed0(xyz)) {
2085  assert(mNode0);
2086  const_cast<NodeT0*>(mNode0)->setValueOnlyAndCache(xyz, value, *this);
2087  } else if (this->isHashed1(xyz)) {
2088  assert(mNode1);
2089  const_cast<NodeT1*>(mNode1)->setValueOnlyAndCache(xyz, value, *this);
2090  } else if (this->isHashed2(xyz)) {
2091  assert(mNode2);
2092  const_cast<NodeT2*>(mNode2)->setValueOnlyAndCache(xyz, value, *this);
2093  } else {
2094  BaseT::mTree->root().setValueOnlyAndCache(xyz, value, *this);
2095  }
2096  }
2097 
2099  void setValueOff(const Coord& xyz, const ValueType& value)
2100  {
2101  assert(BaseT::mTree);
2102  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
2103  if (this->isHashed0(xyz)) {
2104  assert(mNode0);
2105  const_cast<NodeT0*>(mNode0)->setValueOffAndCache(xyz, value, *this);
2106  } else if (this->isHashed1(xyz)) {
2107  assert(mNode1);
2108  const_cast<NodeT1*>(mNode1)->setValueOffAndCache(xyz, value, *this);
2109  } else if (this->isHashed2(xyz)) {
2110  assert(mNode2);
2111  const_cast<NodeT2*>(mNode2)->setValueOffAndCache(xyz, value, *this);
2112  } else {
2113  BaseT::mTree->root().setValueOffAndCache(xyz, value, *this);
2114  }
2115  }
2116 
2119  void setValueOnSum(const Coord& xyz, const ValueType& value)
2120  {
2121  assert(BaseT::mTree);
2122  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
2123  if (this->isHashed0(xyz)) {
2124  assert(mNode0);
2125  const_cast<NodeT0*>(mNode0)->setValueOnSumAndCache(xyz, value, *this);
2126  } else if (this->isHashed1(xyz)) {
2127  assert(mNode1);
2128  const_cast<NodeT1*>(mNode1)->setValueOnSumAndCache(xyz, value, *this);
2129  } else if (this->isHashed2(xyz)) {
2130  assert(mNode2);
2131  const_cast<NodeT2*>(mNode2)->setValueOnSumAndCache(xyz, value, *this);
2132  } else {
2133  BaseT::mTree->root().setValueOnSumAndCache(xyz, value, *this);
2134  }
2135  }
2136 
2138  void setActiveState(const Coord& xyz, bool on = true)
2139  {
2140  assert(BaseT::mTree);
2141  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
2142  if (this->isHashed0(xyz)) {
2143  assert(mNode0);
2144  const_cast<NodeT0*>(mNode0)->setActiveStateAndCache(xyz, on, *this);
2145  } else if (this->isHashed1(xyz)) {
2146  assert(mNode1);
2147  const_cast<NodeT1*>(mNode1)->setActiveStateAndCache(xyz, on, *this);
2148  } else if (this->isHashed2(xyz)) {
2149  assert(mNode2);
2150  const_cast<NodeT2*>(mNode2)->setActiveStateAndCache(xyz, on, *this);
2151  } else {
2152  BaseT::mTree->root().setActiveStateAndCache(xyz, on, *this);
2153  }
2154  }
2156  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
2158  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
2159 
2161  template<typename NodeT>
2162  NodeT* getNode()
2163  {
2164  const NodeT* node = NULL;
2165  this->getNode(node);
2166  return const_cast<NodeT*>(node);
2167  }
2168 
2171  template<typename NodeT>
2172  void insertNode(const Coord& xyz, NodeT& node) { this->insert(xyz, &node); }
2173 
2177  template<typename NodeT>
2178  void eraseNode()
2179  {
2180  const NodeT* node = NULL;
2181  this->eraseNode(node);
2182  }
2183 
2186  void addLeaf(LeafNodeT* leaf)
2187  {
2188  assert(BaseT::mTree);
2189  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
2190  if (this->isHashed1(leaf->origin())) {
2191  assert(mNode1);
2192  return const_cast<NodeT1*>(mNode1)->addLeafAndCache(leaf, *this);
2193  } else if (this->isHashed2(leaf->origin())) {
2194  assert(mNode2);
2195  return const_cast<NodeT2*>(mNode2)->addLeafAndCache(leaf, *this);
2196  }
2197  BaseT::mTree->root().addLeafAndCache(leaf, *this);
2198  }
2199 
2203  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
2204  {
2205  assert(BaseT::mTree);
2206  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
2207  if (this->isHashed1(xyz)) {
2208  assert(mNode1);
2209  return const_cast<NodeT1*>(mNode1)->addTileAndCache(level, xyz, value, state, *this);
2210  } if (this->isHashed2(xyz)) {
2211  assert(mNode2);
2212  return const_cast<NodeT2*>(mNode2)->addTileAndCache(level, xyz, value, state, *this);
2213  }
2214  BaseT::mTree->root().addTileAndCache(level, xyz, value, state, *this);
2215  }
2216 
2223  LeafNodeT* touchLeaf(const Coord& xyz)
2224  {
2225  assert(BaseT::mTree);
2226  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
2227  if (this->isHashed0(xyz)) {
2228  assert(mNode0);
2229  return const_cast<NodeT0*>(mNode0);
2230  } else if (this->isHashed1(xyz)) {
2231  assert(mNode1);
2232  return const_cast<NodeT1*>(mNode1)->touchLeafAndCache(xyz, *this);
2233  } else if (this->isHashed2(xyz)) {
2234  assert(mNode2);
2235  return const_cast<NodeT2*>(mNode2)->touchLeafAndCache(xyz, *this);
2236  }
2237  return BaseT::mTree->root().touchLeafAndCache(xyz, *this);
2238  }
2241  template <typename NodeT>
2242  NodeT* probeNode(const Coord& xyz)
2243  {
2244  assert(BaseT::mTree);
2245  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
2247  if ((boost::is_same<NodeT, NodeT0>::value)) {
2248  if (this->isHashed0(xyz)) {
2249  assert(mNode0);
2250  return reinterpret_cast<NodeT*>(const_cast<NodeT0*>(mNode0));
2251  } else if (this->isHashed1(xyz)) {
2252  assert(mNode1);
2253  return const_cast<NodeT1*>(mNode1)->template probeNodeAndCache<NodeT>(xyz, *this);
2254  } else if (this->isHashed2(xyz)) {
2255  assert(mNode2);
2256  return const_cast<NodeT2*>(mNode2)->template probeNodeAndCache<NodeT>(xyz, *this);
2257  }
2258  return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
2259  } else if ((boost::is_same<NodeT, NodeT1>::value)) {
2260  if (this->isHashed1(xyz)) {
2261  assert(mNode1);
2262  return reinterpret_cast<NodeT*>(const_cast<NodeT1*>(mNode1));
2263  } else if (this->isHashed2(xyz)) {
2264  assert(mNode2);
2265  return const_cast<NodeT2*>(mNode2)->template probeNodeAndCache<NodeT>(xyz, *this);
2266  }
2267  return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
2268  } else if ((boost::is_same<NodeT, NodeT2>::value)) {
2269  if (this->isHashed2(xyz)) {
2270  assert(mNode2);
2271  return reinterpret_cast<NodeT*>(const_cast<NodeT2*>(mNode2));
2272  }
2273  return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
2274  }
2275  return NULL;
2277  }
2280  LeafNodeT* probeLeaf(const Coord& xyz) { return this->template probeNode<LeafNodeT>(xyz); }
2281 
2284  template <typename NodeT>
2285  const NodeT* probeConstNode(const Coord& xyz) const
2286  {
2287  assert(BaseT::mTree);
2289  if ((boost::is_same<NodeT, NodeT0>::value)) {
2290  if (this->isHashed0(xyz)) {
2291  assert(mNode0);
2292  return reinterpret_cast<const NodeT*>(mNode0);
2293  } else if (this->isHashed1(xyz)) {
2294  assert(mNode1);
2295  return mNode1->template probeConstNodeAndCache<NodeT>(xyz, this->self());
2296  } else if (this->isHashed2(xyz)) {
2297  assert(mNode2);
2298  return mNode2->template probeConstNodeAndCache<NodeT>(xyz, this->self());
2299  }
2300  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
2301  } else if ((boost::is_same<NodeT, NodeT1>::value)) {
2302  if (this->isHashed1(xyz)) {
2303  assert(mNode1);
2304  return reinterpret_cast<const NodeT*>(mNode1);
2305  } else if (this->isHashed2(xyz)) {
2306  assert(mNode2);
2307  return mNode2->template probeConstNodeAndCache<NodeT>(xyz, this->self());
2308  }
2309  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
2310  } else if ((boost::is_same<NodeT, NodeT2>::value)) {
2311  if (this->isHashed2(xyz)) {
2312  assert(mNode2);
2313  return reinterpret_cast<const NodeT*>(mNode2);
2314  }
2315  return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
2316  }
2317  return NULL;
2319  }
2322  const LeafNodeT* probeConstLeaf(const Coord& xyz) const
2323  {
2324  return this->template probeConstNode<LeafNodeT>(xyz);
2325  }
2326  const LeafNodeT* probeLeaf(const Coord& xyz) const { return this->probeConstLeaf(xyz); }
2327 
2329  virtual void clear()
2330  {
2331  mKey0 = Coord::max();
2332  mNode0 = NULL;
2333  mKey1 = Coord::max();
2334  mNode1 = NULL;
2335  mKey2 = Coord::max();
2336  mNode2 = NULL;
2337  }
2338 
2339 private:
2340  // Allow nodes to insert themselves into the cache.
2341  template<typename> friend class RootNode;
2342  template<typename, Index> friend class InternalNode;
2343  template<typename, Index> friend class LeafNode;
2344  // Allow trees to deregister themselves.
2345  template<typename> friend class Tree;
2346 
2347  // This private method is merely for convenience.
2348  inline ValueAccessor3& self() const { return const_cast<ValueAccessor3&>(*this); }
2349 
2351  inline void copy(const ValueAccessor3& other)
2352  {
2353  mKey0 = other.mKey0;
2354  mNode0 = other.mNode0;
2355  mKey1 = other.mKey1;
2356  mNode1 = other.mNode1;
2357  mKey2 = other.mKey2;
2358  mNode2 = other.mNode2;
2359  }
2360 
2363  virtual void release()
2364  {
2365  this->BaseT::release();
2366  this->clear();
2367  }
2368  void getNode(const NodeT0*& node) { node = mNode0; }
2369  void getNode(const NodeT1*& node) { node = mNode1; }
2370  void getNode(const NodeT2*& node) { node = mNode2; }
2371  void getNode(const RootNodeT*& node)
2372  {
2373  node = (BaseT::mTree ? &BaseT::mTree->root() : NULL);
2374  }
2375  template <typename OtherNodeType> void getNode(const OtherNodeType*& node) { node = NULL; }
2376 
2377  void eraseNode(const NodeT0*) { mKey0 = Coord::max(); mNode0 = NULL; }
2378  void eraseNode(const NodeT1*) { mKey1 = Coord::max(); mNode1 = NULL; }
2379  void eraseNode(const NodeT2*) { mKey2 = Coord::max(); mNode2 = NULL; }
2380  template <typename OtherNodeType> void eraseNode(const OtherNodeType*) {}
2381 
2386  inline void insert(const Coord& xyz, const NodeT0* node)
2387  {
2388  assert(node);
2389  mKey0 = xyz & ~(NodeT0::DIM-1);
2390  mNode0 = node;
2391  }
2392  inline void insert(const Coord& xyz, const NodeT1* node)
2393  {
2394  assert(node);
2395  mKey1 = xyz & ~(NodeT1::DIM-1);
2396  mNode1 = node;
2397  }
2398  inline void insert(const Coord& xyz, const NodeT2* node)
2399  {
2400  assert(node);
2401  mKey2 = xyz & ~(NodeT2::DIM-1);
2402  mNode2 = node;
2403  }
2406  template<typename OtherNodeType>
2407  inline void insert(const Coord&, const OtherNodeType*)
2408  {
2409  }
2410  inline bool isHashed0(const Coord& xyz) const
2411  {
2412  return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
2413  && (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
2414  && (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
2415  }
2416  inline bool isHashed1(const Coord& xyz) const
2417  {
2418  return (xyz[0] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[0]
2419  && (xyz[1] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[1]
2420  && (xyz[2] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[2];
2421  }
2422  inline bool isHashed2(const Coord& xyz) const
2423  {
2424  return (xyz[0] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[0]
2425  && (xyz[1] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[1]
2426  && (xyz[2] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[2];
2427  }
2428  mutable Coord mKey0;
2429  mutable const NodeT0* mNode0;
2430  mutable Coord mKey1;
2431  mutable const NodeT1* mNode1;
2432  mutable Coord mKey2;
2433  mutable const NodeT2* mNode2;
2434 }; // ValueAccessor3
2435 
2436 } // namespace tree
2437 } // namespace OPENVDB_VERSION_NAME
2438 } // namespace openvdb
2439 
2440 #endif // OPENVDB_TREE_VALUEACCESSOR_HAS_BEEN_INCLUDED
2441 
2442 // Copyright (c) 2012-2013 DreamWorks Animation LLC
2443 // All rights reserved. This software is distributed under the
2444 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )