OpenVDB  1.1.0
ValueAccessor.h
Go to the documentation of this file.
1 
2 //
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 
113  TreeType* getTree() const { return mTree; }
114 
115  ValueAccessorBase(const ValueAccessorBase& other): mTree(other.mTree)
116  {
117  if (mTree) mTree->attachAccessor(*this);
118  }
119 
120  ValueAccessorBase& operator=(const ValueAccessorBase& other)
121  {
122  if (&other != this) {
123  if (mTree) mTree->releaseAccessor(*this);
124  mTree = other.mTree;
125  if (mTree) mTree->attachAccessor(*this);
126  }
127  return *this;
128  }
129 
130  virtual void clear() = 0;
131 
132 protected:
133  // Allow trees to deregister themselves.
134  template<typename> friend class Tree;
135 
136  virtual void release() { mTree = NULL; }
137 
138  TreeType* mTree;
139 }; // class ValueAccessorBase
140 
141 
143 
144 
172 template<typename _TreeType,
173  Index CacheLevels = _TreeType::DEPTH-1,
174  typename MutexType = tbb::null_mutex>
175 class ValueAccessor: public ValueAccessorBase<_TreeType>
176 {
177 public:
178  BOOST_STATIC_ASSERT(CacheLevels <= _TreeType::DEPTH-1);
179  typedef _TreeType TreeType;
180  typedef typename TreeType::RootNodeType RootNodeT;
181  typedef typename TreeType::LeafNodeType LeafNodeT;
182  typedef typename RootNodeT::ValueType ValueType;
184  typedef typename MutexType::scoped_lock LockT;
185  using BaseT::IsConstTree;
186 
187  ValueAccessor(TreeType& tree): BaseT(tree), mCache(*this)
188  {
189  mCache.insert(Coord(), &tree.getRootNode());
190  }
191 
192  ValueAccessor(const ValueAccessor& other): BaseT(other), mCache(*this, other.mCache) {}
193 
194  ValueAccessor& operator=(const ValueAccessor& other)
195  {
196  if (&other != this) {
197  this->BaseT::operator=(other);
198  mCache.copy(*this, other.mCache);
199  }
200  return *this;
201  }
202  virtual ~ValueAccessor() {}
203 
205  static Index numCacheLevels() { return CacheLevels; }
206 
208  bool isCached(const Coord& xyz) const { LockT lock(mMutex); return mCache.isCached(xyz); }
209 
211  const ValueType& getValue(const Coord& xyz) const
212  {
213  LockT lock(mMutex);
214  return mCache.getValue(xyz);
215  }
216 
218  bool isValueOn(const Coord& xyz) const { LockT lock(mMutex); return mCache.isValueOn(xyz); }
219 
221  bool probeValue(const Coord& xyz, ValueType& value) const
222  {
223  LockT lock(mMutex);
224  return mCache.probeValue(xyz,value);
225  }
226 
230  int getValueDepth(const Coord& xyz) const
231  {
232  LockT lock(mMutex);
233  return mCache.getValueDepth(xyz);
234  }
235 
238  bool isVoxel(const Coord& xyz) const { LockT lock(mMutex); return mCache.isVoxel(xyz); }
239 
241 
242  void setValue(const Coord& xyz, const ValueType& value)
243  {
244  LockT lock(mMutex);
245  mCache.setValue(xyz, value);
246  }
247  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
249 
251  void setValueOnly(const Coord& xyz, const ValueType& value)
252  {
253  LockT lock(mMutex);
254  mCache.setValueOnly(xyz, value);
255  }
256 
259  void newSetValue(const Coord& xyz, const ValueType& value)
260  {
261  LockT lock(mMutex);
262  mCache.newSetValue(xyz, value);
263  }
264 
266  void setValueOff(const Coord& xyz, const ValueType& value)
267  {
268  LockT lock(mMutex);
269  mCache.setValueOff(xyz, value);
270  }
271 
274  void setValueOnSum(const Coord& xyz, const ValueType& value)
275  {
276  LockT lock(mMutex);
277  mCache.setValueOnSum(xyz, value);
278  }
279 
281  void setActiveState(const Coord& xyz, bool on = true)
282  {
283  LockT lock(mMutex);
284  mCache.setActiveState(xyz, on);
285  }
287  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
289  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
290 
292  template<typename NodeType>
293  NodeType* getNode()
294  {
295  LockT lock(mMutex);
296  NodeType* node = NULL;
297  mCache.getNode(node);
298  return node;
299  }
300 
303  template<typename NodeType>
304  void insertNode(const Coord& xyz, NodeType& node)
305  {
306  LockT lock(mMutex);
307  mCache.insert(xyz, &node);
308  }
309 
313  template<typename NodeType>
314  void eraseNode() { LockT lock(mMutex); NodeType* node = NULL; mCache.erase(node); }
315 
322  LeafNodeT* touchLeaf(const Coord& xyz)
323  {
324  LockT lock(mMutex);
325  return mCache.touchLeaf(xyz);
326  }
327 
330  LeafNodeT* probeLeaf(const Coord& xyz)
331  {
332  LockT lock(mMutex);
333  return mCache.probeLeaf(xyz);
334  }
335 
338  const LeafNodeT* probeConstLeaf(const Coord& xyz)
339  {
340  LockT lock(mMutex);
341  return mCache.probeConstLeaf(xyz);
342  }
343 
345  virtual void clear()
346  {
347  LockT lock(mMutex);
348  mCache.clear();
349  if (this->mTree) mCache.insert(Coord(), &(this->mTree->getRootNode()));
350  }
351 
352 private:
353  // Allow nodes to insert themselves into the cache.
354  template<typename> friend class RootNode;
355  template<typename, Index> friend class InternalNode;
356  template<typename, Index> friend class LeafNode;
357  // Allow trees to deregister themselves.
358  template<typename> friend class Tree;
359 
362  virtual void release()
363  {
364  LockT lock(mMutex);
365  this->BaseT::release();
366  mCache.clear();
367  }
372  template<typename NodeType>
373  void insert(const Coord& xyz, NodeType* node) { mCache.insert(xyz, node); }
374 
375  // Define a list of all tree node types from LeafNode to RootNode
376  typedef typename InvertedTree<RootNodeT, RootNodeT::LEVEL>::Type InvTreeT;
377  // Remove all tree node types that are excluded from the cache
378  typedef typename boost::mpl::begin<InvTreeT>::type BeginT;
379  typedef typename boost::mpl::advance<BeginT,boost::mpl::int_<CacheLevels> >::type FirstT;
380  typedef typename boost::mpl::find<InvTreeT, RootNodeT>::type LastT;
381  typedef typename boost::mpl::erase<InvTreeT,FirstT,LastT>::type SubtreeT;
382  typedef CacheItem<ValueAccessor, SubtreeT, boost::mpl::size<SubtreeT>::value==1> CacheItemT;
383 
384  // Private member data
385  mutable CacheItemT mCache;
386  mutable MutexType mMutex;
387 
388 }; // class ValueAccessor
389 
390 
395 template<typename TreeType>
396 struct ValueAccessor<TreeType, 0, tbb::null_mutex>: public ValueAccessor0<TreeType>
397 {
400  virtual ~ValueAccessor() {}
401 };
402 
403 
405 template<typename TreeType>
406 struct ValueAccessor<TreeType, 1, tbb::null_mutex>: public ValueAccessor1<TreeType>
407 {
410  virtual ~ValueAccessor() {}
411 };
412 
413 
415 template<typename TreeType>
416 struct ValueAccessor<TreeType, 2, tbb::null_mutex>: public ValueAccessor2<TreeType>
417 {
420  virtual ~ValueAccessor() {}
421 };
422 
423 
425 template<typename TreeType>
426 struct ValueAccessor<TreeType, 3, tbb::null_mutex>: public ValueAccessor3<TreeType>
427 {
430  virtual ~ValueAccessor() {}
431 };
432 
433 
435 
436 
441 template<typename TreeType>
442 struct ValueAccessorRW: public ValueAccessor<TreeType, TreeType::DEPTH-1, tbb::spin_mutex>
443 {
445  : ValueAccessor<TreeType, TreeType::DEPTH-1, tbb::spin_mutex>(tree)
446  {
447  }
448 };
449 
450 
452 
453 
457 
467 template<typename HeadT, int HeadLevel>
468 struct InvertedTree {
469  typedef typename InvertedTree<typename HeadT::ChildNodeType, HeadLevel-1>::Type SubtreeT;
470  typedef typename boost::mpl::push_back<SubtreeT, HeadT>::type Type;
471 };
475 template<typename HeadT>
476 struct InvertedTree<HeadT, /*HeadLevel=*/1> {
477  typedef typename boost::mpl::vector<typename HeadT::ChildNodeType, HeadT>::type Type;
478 };
479 
480 
481 // An element of a compile-time linked list of node pointers, ordered from LeafNode to RootNode
482 template<typename TreeCacheT, typename NodeVecT, bool AtRoot>
484 {
485 public:
486  typedef typename boost::mpl::front<NodeVecT>::type NodeType;
487  typedef typename NodeType::ValueType ValueType;
488  typedef typename NodeType::LeafNodeType LeafNodeType;
489  typedef std::numeric_limits<Int32> CoordLimits;
490 
491  CacheItem(TreeCacheT& parent):
492  mParent(&parent),
493  mHash(CoordLimits::max()),
494  mNode(NULL),
495  mNext(parent)
496  {
497  }
498 
500 
501  CacheItem(TreeCacheT& parent, const CacheItem& other):
502  mParent(&parent),
503  mHash(other.mHash),
504  mNode(other.mNode),
505  mNext(parent, other.mNext)
506  {
507  }
508 
509  CacheItem& copy(TreeCacheT& parent, const CacheItem& other)
510  {
511  mParent = &parent;
512  mHash = other.mHash;
513  mNode = other.mNode;
514  mNext.copy(parent, other.mNext);
515  return *this;
516  }
518 
519  bool isCached(const Coord& xyz) const
520  {
521  return (this->isHashed(xyz) || mNext.isCached(xyz));
522  }
523 
525  void insert(const Coord& xyz, const NodeType* node)
526  {
527  mHash = (node != NULL) ? xyz & ~(NodeType::DIM-1) : Coord::max();
528  mNode = node;
529  }
531  template<typename OtherNodeType>
532  void insert(const Coord& xyz, const OtherNodeType* node) { mNext.insert(xyz, node); }
533 
535  void erase(const NodeType*) { mHash = Coord::max(); mNode = NULL; }
537  template<typename OtherNodeType>
538  void erase(const OtherNodeType* node) { mNext.erase(node); }
539 
541  void clear() { mHash = Coord::max(); mNode = NULL; mNext.clear(); }
542 
544  void getNode(const NodeType*& node) const { node = mNode; }
545  void getNode(const NodeType*& node) { node = mNode; }
546  void getNode(NodeType*& node)
547  {
548  // This combination of a static assertion and a const_cast might not be elegant,
549  // but it is a lot simpler than specializing TreeCache for const Trees.
550  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
551  node = const_cast<NodeType*>(mNode);
552  }
554  template<typename OtherNodeType>
555  void getNode(OtherNodeType*& node) { mNext.getNode(node); }
556 
558  const ValueType& getValue(const Coord& xyz)
559  {
560  if (this->isHashed(xyz)) {
561  assert(mNode);
562  return mNode->getValueAndCache(xyz, *mParent);
563  }
564  return mNext.getValue(xyz);
565  }
566 
567  LeafNodeType* touchLeaf(const Coord& xyz)
568  {
569  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
570  if (this->isHashed(xyz)) {
571  assert(mNode);
572  return const_cast<NodeType*>(mNode)->touchLeafAndCache(xyz, *mParent);
573  }
574  return mNext.touchLeaf(xyz);
575  }
576 
577  LeafNodeType* probeLeaf(const Coord& xyz)
578  {
579  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
580  if (this->isHashed(xyz)) {
581  assert(mNode);
582  return const_cast<NodeType*>(mNode)->probeLeafAndCache(xyz, *mParent);
583  }
584  return mNext.probeLeaf(xyz);
585  }
586 
587  const LeafNodeType* probeConstLeaf(const Coord& xyz)
588  {
589  if (this->isHashed(xyz)) {
590  assert(mNode);
591  return mNode->probeConstLeafAndCache(xyz, *mParent);
592  }
593  return mNext.probeConstLeaf(xyz);
594  }
595 
597  bool isValueOn(const Coord& xyz)
598  {
599  if (this->isHashed(xyz)) {
600  assert(mNode);
601  return mNode->isValueOnAndCache(xyz, *mParent);
602  }
603  return mNext.isValueOn(xyz);
604  }
605 
607  bool probeValue(const Coord& xyz, ValueType& value)
608  {
609  if (this->isHashed(xyz)) {
610  assert(mNode);
611  return mNode->probeValueAndCache(xyz, value, *mParent);
612  }
613  return mNext.probeValue(xyz, value);
614  }
615 
616  int getValueDepth(const Coord& xyz)
617  {
618  if (this->isHashed(xyz)) {
619  assert(mNode);
620  return static_cast<int>(TreeCacheT::RootNodeT::LEVEL) -
621  static_cast<int>(mNode->getValueLevelAndCache(xyz, *mParent));
622  } else {
623  return mNext.getValueDepth(xyz);
624  }
625  }
626 
627  bool isVoxel(const Coord& xyz)
628  {
629  if (this->isHashed(xyz)) {
630  assert(mNode);
631  return mNode->getValueLevelAndCache(xyz, *mParent)==0;
632  } else {
633  return mNext.isVoxel(xyz);
634  }
635  }
636 
638  void setValue(const Coord& xyz, const ValueType& value)
639  {
640  if (this->isHashed(xyz)) {
641  assert(mNode);
642  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
643  const_cast<NodeType*>(mNode)->setValueAndCache(xyz, value, *mParent);
644  } else {
645  mNext.setValue(xyz, value);
646  }
647  }
648  void setValueOnly(const Coord& xyz, const ValueType& value)
649  {
650  if (this->isHashed(xyz)) {
651  assert(mNode);
652  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
653  const_cast<NodeType*>(mNode)->setValueOnlyAndCache(xyz, value, *mParent);
654  } else {
655  mNext.setValueOnly(xyz, value);
656  }
657  }
658  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
659 
662  void setValueOnSum(const Coord& xyz, const ValueType& value)
663  {
664  if (this->isHashed(xyz)) {
665  assert(mNode);
666  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
667  const_cast<NodeType*>(mNode)->setValueOnSumAndCache(xyz, value, *mParent);
668  } else {
669  mNext.setValueOnSum(xyz, value);
670  }
671  }
672 
674  void setValueOff(const Coord& xyz, const ValueType& value)
675  {
676  if (this->isHashed(xyz)) {
677  assert(mNode);
678  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
679  const_cast<NodeType*>(mNode)->setValueOffAndCache(xyz, value, *mParent);
680  } else {
681  mNext.setValueOff(xyz, value);
682  }
683  }
684 
686  void setActiveState(const Coord& xyz, bool on)
687  {
688  if (this->isHashed(xyz)) {
689  assert(mNode);
690  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
691  const_cast<NodeType*>(mNode)->setActiveStateAndCache(xyz, on, *mParent);
692  } else {
693  mNext.setActiveState(xyz, on);
694  }
695  }
696 
697 private:
698  CacheItem(const CacheItem&);
699  CacheItem& operator=(const CacheItem&);
700 
701  bool isHashed(const Coord& xyz) const
702  {
703  return (xyz[0] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[0]
704  && (xyz[1] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[1]
705  && (xyz[2] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[2];
706  }
707 
708  TreeCacheT* mParent;
709  Coord mHash;
710  const NodeType* mNode;
711  typedef typename boost::mpl::pop_front<NodeVecT>::type RestT; // NodeVecT minus its first item
712  CacheItem<TreeCacheT, RestT, /*AtRoot=*/boost::mpl::size<RestT>::value == 1> mNext;
713 };// end of CacheItem
714 
715 
717 template<typename TreeCacheT, typename NodeVecT>
718 class CacheItem<TreeCacheT, NodeVecT, /*AtRoot=*/true>
719 {
720 public:
721  typedef typename boost::mpl::front<NodeVecT>::type RootNodeType;
722  typedef typename RootNodeType::ValueType ValueType;
723  typedef typename RootNodeType::LeafNodeType LeafNodeType;
724 
725  CacheItem(TreeCacheT& parent): mParent(&parent), mRoot(NULL) {}
726  CacheItem(TreeCacheT& parent, const CacheItem& other): mParent(&parent), mRoot(other.mRoot) {}
727 
728  CacheItem& copy(TreeCacheT& parent, const CacheItem& other)
729  {
730  mParent = &parent;
731  mRoot = other.mRoot;
732  return *this;
733  }
734 
735  bool isCached(const Coord& xyz) const { return this->isHashed(xyz); }
736 
737  void insert(const Coord&, const RootNodeType* root) { mRoot = root; }
738 
739  // Needed for node types that are not cached
740  template <typename OtherNodeType>
741  void insert(const Coord&, const OtherNodeType*) {}
742 
743  void erase(const RootNodeType*) { mRoot = NULL; }
744 
745  void clear() { mRoot = NULL; }
746 
747  void getNode(RootNodeType*& node)
748  {
749  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
750  node = const_cast<RootNodeType*>(mRoot);
751  }
752  void getNode(const RootNodeType*& node) const { node = mRoot; }
753 
754  LeafNodeType* touchLeaf(const Coord& xyz)
755  {
756  assert(mRoot);
757  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
758  return const_cast<RootNodeType*>(mRoot)->touchLeafAndCache(xyz, *mParent);
759  }
760 
761  LeafNodeType* probeLeaf(const Coord& xyz)
762  {
763  assert(mRoot);
764  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
765  return const_cast<RootNodeType*>(mRoot)->probeLeafAndCache(xyz, *mParent);
766  }
767 
768  const LeafNodeType* probeConstLeaf(const Coord& xyz)
769  {
770  assert(mRoot);
771  return mRoot->probeConstLeafAndCache(xyz, *mParent);
772  }
773 
774  int getValueDepth(const Coord& xyz)
775  {
776  assert(mRoot);
777  return mRoot->getValueDepthAndCache(xyz, *mParent);
778  }
779  bool isValueOn(const Coord& xyz)
780  {
781  assert(mRoot);
782  return mRoot->isValueOnAndCache(xyz, *mParent);
783  }
784 
785  bool probeValue(const Coord& xyz, ValueType& value)
786  {
787  assert(mRoot);
788  return mRoot->probeValueAndCache(xyz, value, *mParent);
789  }
790  bool isVoxel(const Coord& xyz)
791  {
792  assert(mRoot);
793  return mRoot->getValueDepthAndCache(xyz, *mParent) ==
794  static_cast<int>(RootNodeType::LEVEL);
795  }
796  const ValueType& getValue(const Coord& xyz)
797  {
798  assert(mRoot);
799  return mRoot->getValueAndCache(xyz, *mParent);
800  }
801 
802  void setValue(const Coord& xyz, const ValueType& value)
803  {
804  assert(mRoot);
805  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
806  const_cast<RootNodeType*>(mRoot)->setValueAndCache(xyz, value, *mParent);
807  }
808  void setValueOnly(const Coord& xyz, const ValueType& value)
809  {
810  assert(mRoot);
811  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
812  const_cast<RootNodeType*>(mRoot)->setValueOnlyAndCache(xyz, value, *mParent);
813  }
814  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
815 
816  void setValueOnSum(const Coord& xyz, const ValueType& value)
817  {
818  assert(mRoot);
819  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
820  const_cast<RootNodeType*>(mRoot)->setValueOnSumAndCache(xyz, value, *mParent);
821  }
822 
823  void setValueOff(const Coord& xyz, const ValueType& value)
824  {
825  assert(mRoot);
826  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
827  const_cast<RootNodeType*>(mRoot)->setValueOffAndCache(xyz, value, *mParent);
828  }
829 
830  void setActiveState(const Coord& xyz, bool on)
831  {
832  assert(mRoot);
833  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
834  const_cast<RootNodeType*>(mRoot)->setActiveStateAndCache(xyz, on, *mParent);
835  }
836 
837 private:
838  CacheItem(const CacheItem&);
839  CacheItem& operator=(const CacheItem&);
840 
841  bool isHashed(const Coord&) const { return false; }
842 
843  TreeCacheT* mParent;
844  const RootNodeType* mRoot;
845 };// end of CacheItem specialized for RootNode
846 
847 
849 
850 
855 template<typename _TreeType>
856 class ValueAccessor0 : public ValueAccessorBase<_TreeType>
857 {
858 public:
859  typedef _TreeType TreeType;
860  typedef typename TreeType::ValueType ValueType;
861  typedef typename TreeType::RootNodeType RootNodeT;
862  typedef typename TreeType::LeafNodeType LeafNodeT;
864 
865  ValueAccessor0(TreeType& tree) : BaseT(tree) {}
866 
867  ValueAccessor0(const ValueAccessor0& other) : BaseT(other) {}
868 
870  static Index numCacheLevels() { return 0; }
871 
872  ValueAccessor0& operator=(const ValueAccessor0& other)
873  {
874  if (&other != this) this->BaseT::operator=(other);
875  return *this;
876  }
877 
878  virtual ~ValueAccessor0() {}
879 
881  bool isCached(const Coord&) const { return false; }
882 
884  const ValueType& getValue(const Coord& xyz) const
885  {
886  assert(BaseT::mTree);
887  return BaseT::mTree->getValue(xyz);
888  }
889 
891  bool isValueOn(const Coord& xyz) const
892  {
893  assert(BaseT::mTree);
894  return BaseT::mTree->isValueOn(xyz);
895  }
896 
898  bool probeValue(const Coord& xyz, ValueType& value) const
899  {
900  assert(BaseT::mTree);
901  return BaseT::mTree->probeValue(xyz, value);
902  }
903 
907  int getValueDepth(const Coord& xyz) const
908  {
909  assert(BaseT::mTree);
910  return BaseT::mTree->getValueDepth(xyz);
911  }
912 
915  bool isVoxel(const Coord& xyz) const
916  {
917  assert(BaseT::mTree);
918  return BaseT::mTree->getValueDepth(xyz) == static_cast<int>(RootNodeT::LEVEL);
919  }
920 
922 
923  void setValue(const Coord& xyz, const ValueType& value)
924  {
925  assert(BaseT::mTree);
926  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
927  BaseT::mTree->setValue(xyz, value);
928  }
929  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
931 
933  void setValueOnly(const Coord& xyz, const ValueType& value)
934  {
935  assert(BaseT::mTree);
936  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
937  BaseT::mTree->setValueOnly(xyz, value);
938  }
939 
941  void setValueOff(const Coord& xyz, const ValueType& value)
942  {
943  assert(BaseT::mTree);
944  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
945  BaseT::mTree->getRootNode().setValueOff(xyz, value);
946  }
947 
950  void setValueOnSum(const Coord& xyz, const ValueType& value)
951  {
952  assert(BaseT::mTree);
953  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
954  BaseT::mTree->setValueOnSum(xyz, value);
955  }
956 
958  void setActiveState(const Coord& xyz, bool on = true)
959  {
960  assert(BaseT::mTree);
961  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
962  BaseT::mTree->setActiveState(xyz, on);
963  }
965  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
967  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
968 
970  template<typename NodeT> NodeT* getNode() { return NULL; }
971 
974  template<typename NodeT> void insertNode(const Coord&, NodeT&) {}
975 
979  template<typename NodeT> void eraseNode() {}
980 
981  LeafNodeT* touchLeaf(const Coord& xyz)
982  {
983  assert(BaseT::mTree);
984  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
985  return BaseT::mTree->touchLeaf(xyz);
986  }
987 
988  LeafNodeT* probeLeaf(const Coord& xyz)
989  {
990  assert(BaseT::mTree);
991  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
992  return BaseT::mTree->probeLeaf(xyz);
993  }
994 
995  const LeafNodeT* probeConstLeaf(const Coord& xyz)
996  {
997  assert(BaseT::mTree);
998  return BaseT::mTree->probeConstLeaf(xyz);
999  }
1000 
1002  virtual void clear() {}
1003 
1004 private:
1005  // Allow trees to deregister themselves.
1006  template<typename> friend class Tree;
1007 
1010  virtual void release() { this->BaseT::release(); }
1011 
1012 }; // ValueAccessor0
1013 
1014 
1021 template<typename _TreeType, Index L0>
1022 class ValueAccessor1 : public ValueAccessorBase<_TreeType>
1023 {
1024 public:
1025  BOOST_STATIC_ASSERT(_TreeType::DEPTH >= 2);
1026  BOOST_STATIC_ASSERT( L0 < _TreeType::RootNodeType::LEVEL );
1027  typedef _TreeType TreeType;
1028  typedef typename TreeType::ValueType ValueType;
1029  typedef typename TreeType::RootNodeType RootNodeT;
1030  typedef typename TreeType::LeafNodeType LeafNodeT;
1033  typedef typename boost::mpl::at<InvTreeT, boost::mpl::int_<L0> >::type NodeT0;
1034 
1036  ValueAccessor1(TreeType& tree) : BaseT(tree), mKey0(Coord::max()), mNode0(NULL)
1037  {
1038  }
1039 
1041  ValueAccessor1(const ValueAccessor1& other) : BaseT(other) { this->copy(other); }
1042 
1044  static Index numCacheLevels() { return 1; }
1045 
1047  ValueAccessor1& operator=(const ValueAccessor1& other)
1048  {
1049  if (&other != this) {
1050  this->BaseT::operator=(other);
1051  this->copy(other);
1052  }
1053  return *this;
1054  }
1055 
1057  virtual ~ValueAccessor1() {}
1058 
1061  bool isCached(const Coord& xyz) const
1062  {
1063  assert(BaseT::mTree);
1064  return this->isHashed(xyz);
1065  }
1066 
1068  const ValueType& getValue(const Coord& xyz) const
1069  {
1070  assert(BaseT::mTree);
1071  if (this->isHashed(xyz)) {
1072  assert(mNode0);
1073  return mNode0->getValueAndCache(xyz, this->self());
1074  }
1075  return BaseT::mTree->getRootNode().getValueAndCache(xyz, this->self());
1076  }
1077 
1079  bool isValueOn(const Coord& xyz) const
1080  {
1081  assert(BaseT::mTree);
1082  if (this->isHashed(xyz)) {
1083  assert(mNode0);
1084  return mNode0->isValueOnAndCache(xyz, this->self());
1085  }
1086  return BaseT::mTree->getRootNode().isValueOnAndCache(xyz, this->self());
1087  }
1088 
1090  bool probeValue(const Coord& xyz, ValueType& value) const
1091  {
1092  assert(BaseT::mTree);
1093  if (this->isHashed(xyz)) {
1094  assert(mNode0);
1095  return mNode0->probeValueAndCache(xyz, value, this->self());
1096  }
1097  return BaseT::mTree->getRootNode().probeValueAndCache(xyz, value, this->self());
1098  }
1099 
1103  int getValueDepth(const Coord& xyz) const
1104  {
1105  assert(BaseT::mTree);
1106  if (this->isHashed(xyz)) {
1107  assert(mNode0);
1108  return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->self());
1109  }
1110  return BaseT::mTree->getRootNode().getValueDepthAndCache(xyz, this->self());
1111  }
1112 
1115  bool isVoxel(const Coord& xyz) const
1116  {
1117  assert(BaseT::mTree);
1118  if (this->isHashed(xyz)) {
1119  assert(mNode0);
1120  return mNode0->getValueLevelAndCache(xyz, this->self()) == 0;
1121  }
1122  return BaseT::mTree->getRootNode().getValueDepthAndCache(xyz, this->self()) ==
1123  static_cast<int>(RootNodeT::LEVEL);
1124  }
1125 
1127 
1128  void setValue(const Coord& xyz, const ValueType& value)
1129  {
1130  assert(BaseT::mTree);
1131  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1132  if (this->isHashed(xyz)) {
1133  assert(mNode0);
1134  const_cast<NodeT0*>(mNode0)->setValueAndCache(xyz, value, *this);
1135  } else {
1136  BaseT::mTree->getRootNode().setValueAndCache(xyz, value, *this);
1137  }
1138  }
1139  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
1141 
1143  void setValueOnly(const Coord& xyz, const ValueType& value)
1144  {
1145  assert(BaseT::mTree);
1146  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1147  if (this->isHashed(xyz)) {
1148  assert(mNode0);
1149  const_cast<NodeT0*>(mNode0)->setValueOnlyAndCache(xyz, value, *this);
1150  } else {
1151  BaseT::mTree->getRootNode().setValueOnlyAndCache(xyz, value, *this);
1152  }
1153  }
1154 
1156  void setValueOff(const Coord& xyz, const ValueType& value)
1157  {
1158  assert(BaseT::mTree);
1159  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1160  if (this->isHashed(xyz)) {
1161  assert(mNode0);
1162  const_cast<NodeT0*>(mNode0)->setValueOffAndCache(xyz, value, *this);
1163  } else {
1164  BaseT::mTree->getRootNode().setValueOffAndCache(xyz, value, *this);
1165  }
1166  }
1167 
1170  void setValueOnSum(const Coord& xyz, const ValueType& value)
1171  {
1172  assert(BaseT::mTree);
1173  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1174  if (this->isHashed(xyz)) {
1175  assert(mNode0);
1176  const_cast<NodeT0*>(mNode0)->setValueOnSumAndCache(xyz, value, *this);
1177  } else {
1178  BaseT::mTree->getRootNode().setValueOnSumAndCache(xyz, value, *this);
1179  }
1180  }
1181 
1183  void setActiveState(const Coord& xyz, bool on = true)
1184  {
1185  assert(BaseT::mTree);
1186  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1187  if (this->isHashed(xyz)) {
1188  assert(mNode0);
1189  const_cast<NodeT0*>(mNode0)->setActiveStateAndCache(xyz, on, *this);
1190  } else {
1191  BaseT::mTree->getRootNode().setActiveStateAndCache(xyz, on, *this);
1192  }
1193  }
1195  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
1197  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
1198 
1200  template<typename NodeT>
1201  NodeT* getNode()
1202  {
1203  const NodeT* node = NULL;
1204  this->getNode(node);
1205  return const_cast<NodeT*>(node);
1206  }
1207 
1210  template<typename NodeT>
1211  void insertNode(const Coord& xyz, NodeT& node) { this->insert(xyz, &node); }
1212 
1216  template<typename NodeT>
1217  void eraseNode()
1218  {
1219  const NodeT* node = NULL;
1220  this->eraseNode(node);
1221  }
1222 
1229  LeafNodeT* touchLeaf(const Coord& xyz)
1230  {
1231  assert(BaseT::mTree);
1232  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1233  if (this->isHashed(xyz)) {
1234  assert(mNode0);
1235  return const_cast<NodeT0*>(mNode0)->touchLeafAndCache(xyz, *this);
1236  }
1237  return BaseT::mTree->getRootNode().touchLeafAndCache(xyz, *this);
1238  }
1239 
1242  LeafNodeT* probeLeaf(const Coord& xyz)
1243  {
1244  assert(BaseT::mTree);
1245  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1246  if (this->isHashed(xyz)) {
1247  assert(mNode0);
1248  return const_cast<NodeT0*>(mNode0)->probeLeafAndCache(xyz, *this);
1249  }
1250  return BaseT::mTree->getRootNode().probeLeafAndCache(xyz, *this);
1251  }
1252 
1255  const LeafNodeT* probeConstLeaf(const Coord& xyz)
1256  {
1257  assert(BaseT::mTree);
1258  if (this->isHashed(xyz)) {
1259  assert(mNode0);
1260  return mNode0->probeLeafAndCache(xyz, *this);
1261  }
1262  return BaseT::mTree->getRootNode().probeConstLeafAndCache(xyz, *this);
1263  }
1264 
1266  virtual void clear()
1267  {
1268  mKey0 = Coord::max();
1269  mNode0 = NULL;
1270  }
1271 
1272 private:
1273  // Allow nodes to insert themselves into the cache.
1274  template<typename> friend class RootNode;
1275  template<typename, Index> friend class InternalNode;
1276  template<typename, Index> friend class LeafNode;
1277  // Allow trees to deregister themselves.
1278  template<typename> friend class Tree;
1279 
1280  // This private method is merely for convenience.
1281  inline ValueAccessor1& self() const { return const_cast<ValueAccessor1&>(*this); }
1282 
1283  void getNode(const NodeT0*& node) { node = mNode0; }
1284  void getNode(const RootNodeT*& node)
1285  {
1286  node = (BaseT::mTree ? &BaseT::mTree->getRootNode() : NULL);
1287  }
1288  template <typename OtherNodeType> void getNode(const OtherNodeType*& node) { node = NULL; }
1289  void eraseNode(const NodeT0*) { mKey0 = Coord::max(); mNode0 = NULL; }
1290  template <typename OtherNodeType> void eraseNode(const OtherNodeType*) {}
1291 
1293  inline void copy(const ValueAccessor1& other)
1294  {
1295  mKey0 = other.mKey0;
1296  mNode0 = other.mNode0;
1297  }
1298 
1301  virtual void release()
1302  {
1303  this->BaseT::release();
1304  this->clear();
1305  }
1310  inline void insert(const Coord& xyz, const NodeT0* node)
1311  {
1312  assert(node);
1313  mKey0 = xyz & ~(NodeT0::DIM-1);
1314  mNode0 = node;
1315  }
1316 
1319  template<typename OtherNodeType> inline void insert(const Coord&, const OtherNodeType*) {}
1320 
1321  inline bool isHashed(const Coord& xyz) const
1322  {
1323  return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
1324  && (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
1325  && (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
1326  }
1327  mutable Coord mKey0;
1328  mutable const NodeT0* mNode0;
1329 }; // ValueAccessor1
1330 
1331 
1339 template<typename _TreeType, Index L0, Index L1>
1340 class ValueAccessor2 : public ValueAccessorBase<_TreeType>
1341 {
1342 public:
1343  BOOST_STATIC_ASSERT(_TreeType::DEPTH >= 3);
1344  BOOST_STATIC_ASSERT( L0 < L1 && L1 < _TreeType::RootNodeType::LEVEL );
1345  typedef _TreeType TreeType;
1346  typedef typename TreeType::ValueType ValueType;
1347  typedef typename TreeType::RootNodeType RootNodeT;
1348  typedef typename TreeType::LeafNodeType LeafNodeT;
1351  typedef typename boost::mpl::at<InvTreeT, boost::mpl::int_<L0> >::type NodeT0;
1352  typedef typename boost::mpl::at<InvTreeT, boost::mpl::int_<L1> >::type NodeT1;
1353 
1356  mKey0(Coord::max()), mNode0(NULL),
1357  mKey1(Coord::max()), mNode1(NULL) {}
1358 
1360  ValueAccessor2(const ValueAccessor2& other) : BaseT(other) { this->copy(other); }
1361 
1363  static Index numCacheLevels() { return 2; }
1364 
1366  ValueAccessor2& operator=(const ValueAccessor2& other)
1367  {
1368  if (&other != this) {
1369  this->BaseT::operator=(other);
1370  this->copy(other);
1371  }
1372  return *this;
1373  }
1374 
1376  virtual ~ValueAccessor2() {}
1377 
1380  bool isCached(const Coord& xyz) const
1381  {
1382  assert(BaseT::mTree);
1383  return this->isHashed1(xyz) || this->isHashed0(xyz);
1384  }
1385 
1387  const ValueType& getValue(const Coord& xyz) const
1388  {
1389  assert(BaseT::mTree);
1390  if (this->isHashed0(xyz)) {
1391  assert(mNode0);
1392  return mNode0->getValueAndCache(xyz, this->self());
1393  } else if (this->isHashed1(xyz)) {
1394  assert(mNode1);
1395  return mNode1->getValueAndCache(xyz, this->self());
1396  }
1397  return BaseT::mTree->getRootNode().getValueAndCache(xyz, this->self());
1398  }
1399 
1401  bool isValueOn(const Coord& xyz) const
1402  {
1403  assert(BaseT::mTree);
1404  if (this->isHashed0(xyz)) {
1405  assert(mNode0);
1406  return mNode0->isValueOnAndCache(xyz, this->self());
1407  } else if (this->isHashed1(xyz)) {
1408  assert(mNode1);
1409  return mNode1->isValueOnAndCache(xyz, this->self());
1410  }
1411  return BaseT::mTree->getRootNode().isValueOnAndCache(xyz, this->self());
1412  }
1413 
1415  bool probeValue(const Coord& xyz, ValueType& value) const
1416  {
1417  assert(BaseT::mTree);
1418  if (this->isHashed0(xyz)) {
1419  assert(mNode0);
1420  return mNode0->probeValueAndCache(xyz, value, this->self());
1421  } else if (this->isHashed1(xyz)) {
1422  assert(mNode1);
1423  return mNode1->probeValueAndCache(xyz, value, this->self());
1424  }
1425  return BaseT::mTree->getRootNode().probeValueAndCache(xyz, value, this->self());
1426  }
1427 
1431  int getValueDepth(const Coord& xyz) const
1432  {
1433  assert(BaseT::mTree);
1434  if (this->isHashed0(xyz)) {
1435  assert(mNode0);
1436  return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->self());
1437  } else if (this->isHashed1(xyz)) {
1438  assert(mNode1);
1439  return RootNodeT::LEVEL - mNode1->getValueLevelAndCache(xyz, this->self());
1440  }
1441  return BaseT::mTree->getRootNode().getValueDepthAndCache(xyz, this->self());
1442  }
1443 
1446  bool isVoxel(const Coord& xyz) const
1447  {
1448  assert(BaseT::mTree);
1449  if (this->isHashed0(xyz)) {
1450  assert(mNode0);
1451  return mNode0->getValueLevelAndCache(xyz, this->self())==0;
1452  } else if (this->isHashed1(xyz)) {
1453  assert(mNode1);
1454  return mNode1->getValueLevelAndCache(xyz, this->self())==0;
1455  }
1456  return BaseT::mTree->getRootNode().getValueDepthAndCache(xyz, this->self()) ==
1457  static_cast<int>(RootNodeT::LEVEL);
1458  }
1459 
1461 
1462  void setValue(const Coord& xyz, const ValueType& value)
1463  {
1464  assert(BaseT::mTree);
1465  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1466  if (this->isHashed0(xyz)) {
1467  assert(mNode0);
1468  const_cast<NodeT0*>(mNode0)->setValueAndCache(xyz, value, *this);
1469  } else if (this->isHashed1(xyz)) {
1470  assert(mNode1);
1471  const_cast<NodeT1*>(mNode1)->setValueAndCache(xyz, value, *this);
1472  } else {
1473  BaseT::mTree->getRootNode().setValueAndCache(xyz, value, *this);
1474  }
1475  }
1476  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
1478 
1480  void setValueOnly(const Coord& xyz, const ValueType& value)
1481  {
1482  assert(BaseT::mTree);
1483  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1484  if (this->isHashed0(xyz)) {
1485  assert(mNode0);
1486  const_cast<NodeT0*>(mNode0)->setValueOnlyAndCache(xyz, value, *this);
1487  } else if (this->isHashed1(xyz)) {
1488  assert(mNode1);
1489  const_cast<NodeT1*>(mNode1)->setValueOnlyAndCache(xyz, value, *this);
1490  } else {
1491  BaseT::mTree->getRootNode().setValueOnlyAndCache(xyz, value, *this);
1492  }
1493  }
1494 
1496  void setValueOff(const Coord& xyz, const ValueType& value)
1497  {
1498  assert(BaseT::mTree);
1499  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1500  if (this->isHashed0(xyz)) {
1501  assert(mNode0);
1502  const_cast<NodeT0*>(mNode0)->setValueOffAndCache(xyz, value, *this);
1503  } else if (this->isHashed1(xyz)) {
1504  assert(mNode1);
1505  const_cast<NodeT1*>(mNode1)->setValueOffAndCache(xyz, value, *this);
1506  } else {
1507  BaseT::mTree->getRootNode().setValueOffAndCache(xyz, value, *this);
1508  }
1509  }
1510 
1513  void setValueOnSum(const Coord& xyz, const ValueType& value)
1514  {
1515  assert(BaseT::mTree);
1516  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1517  if (this->isHashed0(xyz)) {
1518  assert(mNode0);
1519  const_cast<NodeT0*>(mNode0)->setValueOnSumAndCache(xyz, value, *this);
1520  } else if (this->isHashed1(xyz)) {
1521  assert(mNode1);
1522  const_cast<NodeT1*>(mNode1)->setValueOnSumAndCache(xyz, value, *this);
1523  } else {
1524  BaseT::mTree->getRootNode().setValueOnSumAndCache(xyz, value, *this);
1525  }
1526  }
1527 
1529  void setActiveState(const Coord& xyz, bool on = true)
1530  {
1531  assert(BaseT::mTree);
1532  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1533  if (this->isHashed0(xyz)) {
1534  assert(mNode0);
1535  const_cast<NodeT0*>(mNode0)->setActiveStateAndCache(xyz, on, *this);
1536  } else if (this->isHashed1(xyz)) {
1537  assert(mNode1);
1538  const_cast<NodeT1*>(mNode1)->setActiveStateAndCache(xyz, on, *this);
1539  } else {
1540  BaseT::mTree->getRootNode().setActiveStateAndCache(xyz, on, *this);
1541  }
1542  }
1544  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
1546  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
1547 
1549  template<typename NodeT>
1550  NodeT* getNode()
1551  {
1552  const NodeT* node = NULL;
1553  this->getNode(node);
1554  return const_cast<NodeT*>(node);
1555  }
1556 
1559  template<typename NodeT>
1560  void insertNode(const Coord& xyz, NodeT& node) { this->insert(xyz, &node); }
1561 
1565  template<typename NodeT>
1566  void eraseNode()
1567  {
1568  const NodeT* node = NULL;
1569  this->eraseNode(node);
1570  }
1571 
1578  LeafNodeT* touchLeaf(const Coord& xyz)
1579  {
1580  assert(BaseT::mTree);
1581  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1582  if (this->isHashed0(xyz)) {
1583  assert(mNode0);
1584  return const_cast<NodeT0*>(mNode0)->touchLeafAndCache(xyz, *this);
1585  } else if (this->isHashed1(xyz)) {
1586  assert(mNode1);
1587  return const_cast<NodeT1*>(mNode1)->touchLeafAndCache(xyz, *this);
1588  }
1589  return BaseT::mTree->getRootNode().touchLeafAndCache(xyz, *this);
1590  }
1591 
1594  LeafNodeT* probeLeaf(const Coord& xyz)
1595  {
1596  assert(BaseT::mTree);
1597  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1598  if (this->isHashed0(xyz)) {
1599  assert(mNode0);
1600  return const_cast<NodeT0*>(mNode0)->probeLeafAndCache(xyz, *this);
1601  } else if (this->isHashed1(xyz)) {
1602  assert(mNode1);
1603  return const_cast<NodeT1*>(mNode1)->probeLeafAndCache(xyz, *this);
1604  }
1605  return BaseT::mTree->getRootNode().probeLeafAndCache(xyz, *this);
1606  }
1607 
1610  const LeafNodeT* probeConstLeaf(const Coord& xyz)
1611  {
1612  assert(BaseT::mTree);
1613  if (this->isHashed0(xyz)) {
1614  assert(mNode0);
1615  return mNode0->probeConstLeafAndCache(xyz, *this);
1616  } else if (this->isHashed1(xyz)) {
1617  assert(mNode1);
1618  return mNode1->probeConstLeafAndCache(xyz, *this);
1619  }
1620  return BaseT::mTree->getRootNode().probeConstLeafAndCache(xyz, *this);
1621  }
1622 
1624  virtual void clear()
1625  {
1626  mKey0 = Coord::max();
1627  mNode0 = NULL;
1628  mKey1 = Coord::max();
1629  mNode1 = NULL;
1630  }
1631 
1632 private:
1633  // Allow nodes to insert themselves into the cache.
1634  template<typename> friend class RootNode;
1635  template<typename, Index> friend class InternalNode;
1636  template<typename, Index> friend class LeafNode;
1637  // Allow trees to deregister themselves.
1638  template<typename> friend class Tree;
1639 
1640  // This private method is merely for convenience.
1641  inline ValueAccessor2& self() const { return const_cast<ValueAccessor2&>(*this); }
1642 
1643  void getNode(const NodeT0*& node) { node = mNode0; }
1644  void getNode(const NodeT1*& node) { node = mNode1; }
1645  void getNode(const RootNodeT*& node)
1646  {
1647  node = (BaseT::mTree ? &BaseT::mTree->getRootNode() : NULL);
1648  }
1649  template <typename OtherNodeType> void getNode(const OtherNodeType*& node) { node = NULL; }
1650 
1651  void eraseNode(const NodeT0*) { mKey0 = Coord::max(); mNode0 = NULL; }
1652  void eraseNode(const NodeT1*) { mKey1 = Coord::max(); mNode1 = NULL; }
1653  template <typename OtherNodeType> void eraseNode(const OtherNodeType*) {}
1654 
1656  inline void copy(const ValueAccessor2& other)
1657  {
1658  mKey0 = other.mKey0;
1659  mNode0 = other.mNode0;
1660  mKey1 = other.mKey1;
1661  mNode1 = other.mNode1;
1662  }
1663 
1666  virtual void release()
1667  {
1668  this->BaseT::release();
1669  this->clear();
1670  }
1671 
1676  inline void insert(const Coord& xyz, const NodeT0* node)
1677  {
1678  assert(node);
1679  mKey0 = xyz & ~(NodeT0::DIM-1);
1680  mNode0 = node;
1681  }
1682  inline void insert(const Coord& xyz, const NodeT1* node)
1683  {
1684  assert(node);
1685  mKey1 = xyz & ~(NodeT1::DIM-1);
1686  mNode1 = node;
1687  }
1690  template<typename NodeT> inline void insert(const Coord&, const NodeT*) {}
1691 
1692  inline bool isHashed0(const Coord& xyz) const
1693  {
1694  return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
1695  && (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
1696  && (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
1697  }
1698  inline bool isHashed1(const Coord& xyz) const
1699  {
1700  return (xyz[0] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[0]
1701  && (xyz[1] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[1]
1702  && (xyz[2] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[2];
1703  }
1704  mutable Coord mKey0;
1705  mutable const NodeT0* mNode0;
1706  mutable Coord mKey1;
1707  mutable const NodeT1* mNode1;
1708 }; // ValueAccessor2
1709 
1710 
1721 template<typename _TreeType, Index L0, Index L1, Index L2>
1722 class ValueAccessor3 : public ValueAccessorBase<_TreeType>
1723 {
1724 public:
1725  BOOST_STATIC_ASSERT(_TreeType::DEPTH >= 4);
1726  BOOST_STATIC_ASSERT(L0 < L1 && L1 < L2 && L2 < _TreeType::RootNodeType::LEVEL);
1727  typedef _TreeType TreeType;
1728  typedef typename TreeType::ValueType ValueType;
1729  typedef typename TreeType::RootNodeType RootNodeT;
1730  typedef typename TreeType::LeafNodeType LeafNodeT;
1733  typedef typename boost::mpl::at<InvTreeT, boost::mpl::int_<L0> >::type NodeT0;
1734  typedef typename boost::mpl::at<InvTreeT, boost::mpl::int_<L1> >::type NodeT1;
1735  typedef typename boost::mpl::at<InvTreeT, boost::mpl::int_<L2> >::type NodeT2;
1736 
1739  mKey0(Coord::max()), mNode0(NULL),
1740  mKey1(Coord::max()), mNode1(NULL),
1741  mKey2(Coord::max()), mNode2(NULL) {}
1742 
1744  ValueAccessor3(const ValueAccessor3& other) : BaseT(other) { this->copy(other); }
1745 
1747  ValueAccessor3& operator=(const ValueAccessor3& other)
1748  {
1749  if (&other != this) {
1750  this->BaseT::operator=(other);
1751  this->copy(other);
1752  }
1753  return *this;
1754  }
1755 
1757  static Index numCacheLevels() { return 3; }
1758 
1760  virtual ~ValueAccessor3() {}
1761 
1764  bool isCached(const Coord& xyz) const
1765  {
1766  assert(BaseT::mTree);
1767  return this->isHashed2(xyz) || this->isHashed1(xyz) || this->isHashed0(xyz);
1768  }
1769 
1771  const ValueType& getValue(const Coord& xyz) const
1772  {
1773  assert(BaseT::mTree);
1774  if (this->isHashed0(xyz)) {
1775  assert(mNode0);
1776  return mNode0->getValueAndCache(xyz, this->self());
1777  } else if (this->isHashed1(xyz)) {
1778  assert(mNode1);
1779  return mNode1->getValueAndCache(xyz, this->self());
1780  } else if (this->isHashed2(xyz)) {
1781  assert(mNode2);
1782  return mNode2->getValueAndCache(xyz, this->self());
1783  }
1784  return BaseT::mTree->getRootNode().getValueAndCache(xyz, this->self());
1785  }
1786 
1788  bool isValueOn(const Coord& xyz) const
1789  {
1790  assert(BaseT::mTree);
1791  if (this->isHashed0(xyz)) {
1792  assert(mNode0);
1793  return mNode0->isValueOnAndCache(xyz, this->self());
1794  } else if (this->isHashed1(xyz)) {
1795  assert(mNode1);
1796  return mNode1->isValueOnAndCache(xyz, this->self());
1797  } else if (this->isHashed2(xyz)) {
1798  assert(mNode2);
1799  return mNode2->isValueOnAndCache(xyz, this->self());
1800  }
1801  return BaseT::mTree->getRootNode().isValueOnAndCache(xyz, this->self());
1802  }
1803 
1805  bool probeValue(const Coord& xyz, ValueType& value) const
1806  {
1807  assert(BaseT::mTree);
1808  if (this->isHashed0(xyz)) {
1809  assert(mNode0);
1810  return mNode0->probeValueAndCache(xyz, value, this->self());
1811  } else if (this->isHashed1(xyz)) {
1812  assert(mNode1);
1813  return mNode1->probeValueAndCache(xyz, value, this->self());
1814  } else if (this->isHashed2(xyz)) {
1815  assert(mNode2);
1816  return mNode2->probeValueAndCache(xyz, value, this->self());
1817  }
1818  return BaseT::mTree->getRootNode().probeValueAndCache(xyz, value, this->self());
1819  }
1820 
1824  int getValueDepth(const Coord& xyz) const
1825  {
1826  assert(BaseT::mTree);
1827  if (this->isHashed0(xyz)) {
1828  assert(mNode0);
1829  return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->self());
1830  } else if (this->isHashed1(xyz)) {
1831  assert(mNode1);
1832  return RootNodeT::LEVEL - mNode1->getValueLevelAndCache(xyz, this->self());
1833  } else if (this->isHashed2(xyz)) {
1834  assert(mNode2);
1835  return RootNodeT::LEVEL - mNode2->getValueLevelAndCache(xyz, this->self());
1836  }
1837  return BaseT::mTree->getRootNode().getValueDepthAndCache(xyz, this->self());
1838  }
1839 
1842  bool isVoxel(const Coord& xyz) const
1843  {
1844  assert(BaseT::mTree);
1845  if (this->isHashed0(xyz)) {
1846  assert(mNode0);
1847  return mNode0->getValueLevelAndCache(xyz, this->self())==0;
1848  } else if (this->isHashed1(xyz)) {
1849  assert(mNode1);
1850  return mNode1->getValueLevelAndCache(xyz, this->self())==0;
1851  } else if (this->isHashed2(xyz)) {
1852  assert(mNode2);
1853  return mNode2->getValueLevelAndCache(xyz, this->self())==0;
1854  }
1855  return BaseT::mTree->getRootNode().getValueDepthAndCache(xyz, this->self()) ==
1856  static_cast<int>(RootNodeT::LEVEL);
1857  }
1858 
1860 
1861  void setValue(const Coord& xyz, const ValueType& value)
1862  {
1863  assert(BaseT::mTree);
1864  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1865  if (this->isHashed0(xyz)) {
1866  assert(mNode0);
1867  const_cast<NodeT0*>(mNode0)->setValueAndCache(xyz, value, *this);
1868  } else if (this->isHashed1(xyz)) {
1869  assert(mNode1);
1870  const_cast<NodeT1*>(mNode1)->setValueAndCache(xyz, value, *this);
1871  } else if (this->isHashed2(xyz)) {
1872  assert(mNode2);
1873  const_cast<NodeT2*>(mNode2)->setValueAndCache(xyz, value, *this);
1874  } else {
1875  BaseT::mTree->getRootNode().setValueAndCache(xyz, value, *this);
1876  }
1877  }
1878  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
1880 
1882  void setValueOnly(const Coord& xyz, const ValueType& value)
1883  {
1884  assert(BaseT::mTree);
1885  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1886  if (this->isHashed0(xyz)) {
1887  assert(mNode0);
1888  const_cast<NodeT0*>(mNode0)->setValueOnlyAndCache(xyz, value, *this);
1889  } else if (this->isHashed1(xyz)) {
1890  assert(mNode1);
1891  const_cast<NodeT1*>(mNode1)->setValueOnlyAndCache(xyz, value, *this);
1892  } else if (this->isHashed2(xyz)) {
1893  assert(mNode2);
1894  const_cast<NodeT2*>(mNode2)->setValueOnlyAndCache(xyz, value, *this);
1895  } else {
1896  BaseT::mTree->getRootNode().setValueOnlyAndCache(xyz, value, *this);
1897  }
1898  }
1899 
1901  void setValueOff(const Coord& xyz, const ValueType& value)
1902  {
1903  assert(BaseT::mTree);
1904  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1905  if (this->isHashed0(xyz)) {
1906  assert(mNode0);
1907  const_cast<NodeT0*>(mNode0)->setValueOffAndCache(xyz, value, *this);
1908  } else if (this->isHashed1(xyz)) {
1909  assert(mNode1);
1910  const_cast<NodeT1*>(mNode1)->setValueOffAndCache(xyz, value, *this);
1911  } else if (this->isHashed2(xyz)) {
1912  assert(mNode2);
1913  const_cast<NodeT2*>(mNode2)->setValueOffAndCache(xyz, value, *this);
1914  } else {
1915  BaseT::mTree->getRootNode().setValueOffAndCache(xyz, value, *this);
1916  }
1917  }
1918 
1921  void setValueOnSum(const Coord& xyz, const ValueType& value)
1922  {
1923  assert(BaseT::mTree);
1924  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1925  if (this->isHashed0(xyz)) {
1926  assert(mNode0);
1927  const_cast<NodeT0*>(mNode0)->setValueOnSumAndCache(xyz, value, *this);
1928  } else if (this->isHashed1(xyz)) {
1929  assert(mNode1);
1930  const_cast<NodeT1*>(mNode1)->setValueOnSumAndCache(xyz, value, *this);
1931  } else if (this->isHashed2(xyz)) {
1932  assert(mNode2);
1933  const_cast<NodeT2*>(mNode2)->setValueOnSumAndCache(xyz, value, *this);
1934  } else {
1935  BaseT::mTree->getRootNode().setValueOnSumAndCache(xyz, value, *this);
1936  }
1937  }
1938 
1940  void setActiveState(const Coord& xyz, bool on = true)
1941  {
1942  assert(BaseT::mTree);
1943  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1944  if (this->isHashed0(xyz)) {
1945  assert(mNode0);
1946  const_cast<NodeT0*>(mNode0)->setActiveStateAndCache(xyz, on, *this);
1947  } else if (this->isHashed1(xyz)) {
1948  assert(mNode1);
1949  const_cast<NodeT1*>(mNode1)->setActiveStateAndCache(xyz, on, *this);
1950  } else if (this->isHashed2(xyz)) {
1951  assert(mNode2);
1952  const_cast<NodeT2*>(mNode2)->setActiveStateAndCache(xyz, on, *this);
1953  } else {
1954  BaseT::mTree->getRootNode().setActiveStateAndCache(xyz, on, *this);
1955  }
1956  }
1958  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
1960  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
1961 
1963  template<typename NodeT>
1964  NodeT* getNode()
1965  {
1966  const NodeT* node = NULL;
1967  this->getNode(node);
1968  return const_cast<NodeT*>(node);
1969  }
1970 
1973  template<typename NodeT>
1974  void insertNode(const Coord& xyz, NodeT& node) { this->insert(xyz, &node); }
1975 
1979  template<typename NodeT>
1980  void eraseNode()
1981  {
1982  const NodeT* node = NULL;
1983  this->eraseNode(node);
1984  }
1985 
1992  LeafNodeT* touchLeaf(const Coord& xyz)
1993  {
1994  assert(BaseT::mTree);
1995  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1996  if (this->isHashed0(xyz)) {
1997  assert(mNode0);
1998  return const_cast<NodeT0*>(mNode0)->touchLeafAndCache(xyz, *this);
1999  } else if (this->isHashed1(xyz)) {
2000  assert(mNode1);
2001  return const_cast<NodeT1*>(mNode1)->touchLeafAndCache(xyz, *this);
2002  } else if (this->isHashed2(xyz)) {
2003  assert(mNode2);
2004  return const_cast<NodeT2*>(mNode2)->touchLeafAndCache(xyz, *this);
2005  }
2006  return BaseT::mTree->getRootNode().touchLeafAndCache(xyz, *this);
2007  }
2008 
2011  LeafNodeT* probeLeaf(const Coord& xyz)
2012  {
2013  assert(BaseT::mTree);
2014  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
2015  if (this->isHashed0(xyz)) {
2016  assert(mNode0);
2017  return const_cast<NodeT0*>(mNode0)->probeLeafAndCache(xyz, *this);
2018  } else if (this->isHashed1(xyz)) {
2019  assert(mNode1);
2020  return const_cast<NodeT1*>(mNode1)->probeLeafAndCache(xyz, *this);
2021  } else if (this->isHashed2(xyz)) {
2022  assert(mNode2);
2023  return const_cast<NodeT2*>(mNode2)->probeLeafAndCache(xyz, *this);
2024  }
2025  return BaseT::mTree->getRootNode().probeLeafAndCache(xyz, *this);
2026  }
2027 
2030  const LeafNodeT* probeConstLeaf(const Coord& xyz)
2031  {
2032  assert(BaseT::mTree);
2033  if (this->isHashed0(xyz)) {
2034  assert(mNode0);
2035  return mNode0->probeConstLeafAndCache(xyz, *this);
2036  } else if (this->isHashed1(xyz)) {
2037  assert(mNode1);
2038  return mNode1->probeConstLeafAndCache(xyz, *this);
2039  } else if (this->isHashed2(xyz)) {
2040  assert(mNode2);
2041  return mNode2->probeConstLeafAndCache(xyz, *this);
2042  }
2043  return BaseT::mTree->getRootNode().probeConstLeafAndCache(xyz, *this);
2044  }
2045 
2047  virtual void clear()
2048  {
2049  mKey0 = Coord::max();
2050  mNode0 = NULL;
2051  mKey1 = Coord::max();
2052  mNode1 = NULL;
2053  mKey2 = Coord::max();
2054  mNode2 = NULL;
2055  }
2056 
2057 private:
2058  // Allow nodes to insert themselves into the cache.
2059  template<typename> friend class RootNode;
2060  template<typename, Index> friend class InternalNode;
2061  template<typename, Index> friend class LeafNode;
2062  // Allow trees to deregister themselves.
2063  template<typename> friend class Tree;
2064 
2065  // This private method is merely for convenience.
2066  inline ValueAccessor3& self() const { return const_cast<ValueAccessor3&>(*this); }
2067 
2069  inline void copy(const ValueAccessor3& other)
2070  {
2071  mKey0 = other.mKey0;
2072  mNode0 = other.mNode0;
2073  mKey1 = other.mKey1;
2074  mNode1 = other.mNode1;
2075  mKey2 = other.mKey2;
2076  mNode2 = other.mNode2;
2077  }
2078 
2081  virtual void release()
2082  {
2083  this->BaseT::release();
2084  this->clear();
2085  }
2086  void getNode(const NodeT0*& node) { node = mNode0; }
2087  void getNode(const NodeT1*& node) { node = mNode1; }
2088  void getNode(const NodeT2*& node) { node = mNode2; }
2089  void getNode(const RootNodeT*& node)
2090  {
2091  node = (BaseT::mTree ? &BaseT::mTree->getRootNode() : NULL);
2092  }
2093  template <typename OtherNodeType> void getNode(const OtherNodeType*& node) { node = NULL; }
2094 
2095  void eraseNode(const NodeT0*) { mKey0 = Coord::max(); mNode0 = NULL; }
2096  void eraseNode(const NodeT1*) { mKey1 = Coord::max(); mNode1 = NULL; }
2097  void eraseNode(const NodeT2*) { mKey2 = Coord::max(); mNode2 = NULL; }
2098  template <typename OtherNodeType> void eraseNode(const OtherNodeType*) {}
2099 
2104  inline void insert(const Coord& xyz, const NodeT0* node)
2105  {
2106  assert(node);
2107  mKey0 = xyz & ~(NodeT0::DIM-1);
2108  mNode0 = node;
2109  }
2110  inline void insert(const Coord& xyz, const NodeT1* node)
2111  {
2112  assert(node);
2113  mKey1 = xyz & ~(NodeT1::DIM-1);
2114  mNode1 = node;
2115  }
2116  inline void insert(const Coord& xyz, const NodeT2* node)
2117  {
2118  assert(node);
2119  mKey2 = xyz & ~(NodeT2::DIM-1);
2120  mNode2 = node;
2121  }
2124  template<typename OtherNodeType>
2125  inline void insert(const Coord&, const OtherNodeType*)
2126  {
2127  }
2128  inline bool isHashed0(const Coord& xyz) const
2129  {
2130  return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
2131  && (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
2132  && (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
2133  }
2134  inline bool isHashed1(const Coord& xyz) const
2135  {
2136  return (xyz[0] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[0]
2137  && (xyz[1] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[1]
2138  && (xyz[2] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[2];
2139  }
2140  inline bool isHashed2(const Coord& xyz) const
2141  {
2142  return (xyz[0] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[0]
2143  && (xyz[1] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[1]
2144  && (xyz[2] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[2];
2145  }
2146  mutable Coord mKey0;
2147  mutable const NodeT0* mNode0;
2148  mutable Coord mKey1;
2149  mutable const NodeT1* mNode1;
2150  mutable Coord mKey2;
2151  mutable const NodeT2* mNode2;
2152 }; // ValueAccessor3
2153 
2154 } // namespace tree
2155 } // namespace OPENVDB_VERSION_NAME
2156 } // namespace openvdb
2157 
2158 #endif // OPENVDB_TREE_VALUEACCESSOR_HAS_BEEN_INCLUDED
2159 
2160 // Copyright (c) 2012-2013 DreamWorks Animation LLC
2161 // All rights reserved. This software is distributed under the
2162 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )