OpenVDB  0.104.0
ValueAccessor.h
Go to the documentation of this file.
1 
2 //
3 // Copyright (c) 2012 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>
483 class CacheItem
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 
596  // ====================> DEPRECATED METHODS <========================
597  OPENVDB_DEPRECATED const ValueType& getValue(const Coord& xyz, bool& state, int& level)
598  {
599  if (this->isHashed(xyz)) {
600  assert(mNode);
601  return mNode->getValue(xyz, state, level, *mParent);
602  }
603  return mNext.getValue(xyz, state, level);
604  }
605  template <typename ValueProbeType>
606  OPENVDB_DEPRECATED const ValueType& probe(const Coord& xyz, ValueProbeType &p)
607  {
608  if (this->isHashed(xyz)) {
609  assert(mNode);
610  return mNode->probe(xyz, p, *mParent);
611  }
612  return mNext.probe(xyz, p);
613  }
614  template <bool State, bool Level>
615  OPENVDB_DEPRECATED const ValueType& probe(const Coord& xyz, bool& state, int& level)
616  {
617  if (this->isHashed(xyz)) {
618  assert(mNode);
619  return mNode->probe<State, Level>(xyz, state, level, *mParent);
620  }
621  return mNext.probe<State, Level>(xyz, state, level);
622  }
623  OPENVDB_DEPRECATED const ValueType& newGetValue(const Coord& xyz)
624  {
625  if (this->isHashed(xyz)) {
626  assert(mNode);
627  const ValueType& val = mNode->getValue(xyz);
628  mNode->updateCache(xyz, *mParent);
629  return val;
630  }
631  return mNext.newGetValue(xyz);
632  }
633  OPENVDB_DEPRECATED void newSetValue(const Coord& xyz, const ValueType& value)
634  {
635  if (this->isHashed(xyz)) {
636  assert(mNode);
637  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
638  const_cast<NodeType*>(mNode)->setValue(xyz, value);
639  mNode->updateCache(xyz, *mParent);
640  } else {
641  mNext.setValue(xyz, value);
642  }
643  }
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  LeafNodeType* touchLeaf(const Coord& xyz)
804  {
805  assert(mRoot);
806  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
807  return const_cast<RootNodeType*>(mRoot)->touchLeafAndCache(xyz, *mParent);
808  }
809 
810  LeafNodeType* probeLeaf(const Coord& xyz)
811  {
812  assert(mRoot);
813  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
814  return const_cast<RootNodeType*>(mRoot)->probeLeafAndCache(xyz, *mParent);
815  }
816 
817  const LeafNodeType* probeConstLeaf(const Coord& xyz)
818  {
819  assert(mRoot);
820  return mRoot->probeConstLeafAndCache(xyz, *mParent);
821  }
822 
823  int getValueDepth(const Coord& xyz)
824  {
825  assert(mRoot);
826  return mRoot->getValueDepthAndCache(xyz, *mParent);
827  }
828  bool isValueOn(const Coord& xyz)
829  {
830  assert(mRoot);
831  return mRoot->isValueOnAndCache(xyz, *mParent);
832  }
833 
834  bool probeValue(const Coord& xyz, ValueType& value)
835  {
836  assert(mRoot);
837  return mRoot->probeValueAndCache(xyz, value, *mParent);
838  }
839  bool isVoxel(const Coord& xyz)
840  {
841  assert(mRoot);
842  return mRoot->getValueDepthAndCache(xyz, *mParent) ==
843  static_cast<int>(RootNodeType::LEVEL);
844  }
845  const ValueType& getValue(const Coord& xyz)
846  {
847  assert(mRoot);
848  return mRoot->getValueAndCache(xyz, *mParent);
849  }
850  // ====================> DEPRECATED METHODS <========================
851  OPENVDB_DEPRECATED const ValueType& newGetValue(const Coord& xyz)
852  {
853  assert(mRoot);
854  const ValueType& val = mRoot->getValue(xyz);
855  mRoot->updateCache(xyz, *mParent);
856  return val;
857  }
858  OPENVDB_DEPRECATED const ValueType& getValue(const Coord& xyz, bool& state, int& level)
859  {
860  assert(mRoot);
861  return mRoot->getValue(xyz, state, level, *mParent);
862  }
863  template <bool State, bool Level>
864  OPENVDB_DEPRECATED const ValueType& probe(const Coord& xyz, bool& state, int& level)
865  {
866  assert(mRoot);
867  return mRoot->probe<State, Level>(xyz, state, level, *mParent);
868  }
869  template <typename ValueProbeType>
870  OPENVDB_DEPRECATED const ValueType& probe(const Coord& xyz, ValueProbeType& p)
871  {
872  assert(mRoot);
873  return mRoot->probe(xyz, p, *mParent);
874  }
875  OPENVDB_DEPRECATED void newSetValue(const Coord& xyz, const ValueType& value)
876  {
877  assert(mRoot);
878  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
879  const_cast<RootNodeType*>(mRoot)->setValue(xyz, value);
880  mRoot->updateCache(xyz, *mParent);
881  }
883  void setValue(const Coord& xyz, const ValueType& value)
884  {
885  assert(mRoot);
886  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
887  const_cast<RootNodeType*>(mRoot)->setValueAndCache(xyz, value, *mParent);
888  }
889  void setValueOnly(const Coord& xyz, const ValueType& value)
890  {
891  assert(mRoot);
892  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
893  const_cast<RootNodeType*>(mRoot)->setValueOnlyAndCache(xyz, value, *mParent);
894  }
895  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
896 
897  void setValueOnSum(const Coord& xyz, const ValueType& value)
898  {
899  assert(mRoot);
900  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
901  const_cast<RootNodeType*>(mRoot)->setValueOnSumAndCache(xyz, value, *mParent);
902  }
903 
904  void setValueOff(const Coord& xyz, const ValueType& value)
905  {
906  assert(mRoot);
907  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
908  const_cast<RootNodeType*>(mRoot)->setValueOffAndCache(xyz, value, *mParent);
909  }
910 
911  void setActiveState(const Coord& xyz, bool on)
912  {
913  assert(mRoot);
914  BOOST_STATIC_ASSERT(!TreeCacheT::IsConstTree);
915  const_cast<RootNodeType*>(mRoot)->setActiveStateAndCache(xyz, on, *mParent);
916  }
917 
918 private:
919  CacheItem(const CacheItem&);
920  CacheItem& operator=(const CacheItem&);
921 
922  bool isHashed(const Coord&) const { return false; }
923 
924  TreeCacheT* mParent;
925  const RootNodeType* mRoot;
926 };// end of CacheItem specialized for RootNode
927 
928 
930 
931 
936 template<typename _TreeType>
937 class ValueAccessor0 : public ValueAccessorBase<_TreeType>
938 {
939 public:
940  typedef _TreeType TreeType;
941  typedef typename TreeType::ValueType ValueType;
942  typedef typename TreeType::RootNodeType RootNodeT;
943  typedef typename TreeType::LeafNodeType LeafNodeT;
945 
946  ValueAccessor0(TreeType& tree) : BaseT(tree) {}
947 
948  ValueAccessor0(const ValueAccessor0& other) : BaseT(other) {}
949 
951  static Index numCacheLevels() { return 0; }
952 
953  ValueAccessor0& operator=(const ValueAccessor0& other)
954  {
955  if (&other != this) this->BaseT::operator=(other);
956  return *this;
957  }
958 
959  virtual ~ValueAccessor0() {}
960 
962  bool isCached(const Coord&) const { return false; }
963 
965  const ValueType& getValue(const Coord& xyz) const
966  {
967  assert(BaseT::mTree);
968  return BaseT::mTree->getValue(xyz);
969  }
970 
972  bool isValueOn(const Coord& xyz) const
973  {
974  assert(BaseT::mTree);
975  return BaseT::mTree->isValueOn(xyz);
976  }
977 
979  bool probeValue(const Coord& xyz, ValueType& value) const
980  {
981  assert(BaseT::mTree);
982  return BaseT::mTree->probeValue(xyz, value);
983  }
984 
988  int getValueDepth(const Coord& xyz) const
989  {
990  assert(BaseT::mTree);
991  return BaseT::mTree->getValueDepth(xyz);
992  }
993 
996  bool isVoxel(const Coord& xyz) const
997  {
998  assert(BaseT::mTree);
999  return BaseT::mTree->getValueDepth(xyz) == static_cast<int>(RootNodeT::LEVEL);
1000  }
1001 
1003 
1004  void setValue(const Coord& xyz, const ValueType& value)
1005  {
1006  assert(BaseT::mTree);
1007  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1008  BaseT::mTree->setValue(xyz, value);
1009  }
1010  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
1012 
1014  void setValueOnly(const Coord& xyz, const ValueType& value)
1015  {
1016  assert(BaseT::mTree);
1017  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1018  BaseT::mTree->setValueOnly(xyz, value);
1019  }
1020 
1022  void setValueOff(const Coord& xyz, const ValueType& value)
1023  {
1024  assert(BaseT::mTree);
1025  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1026  BaseT::mTree->getRootNode().setValueOff(xyz, value);
1027  }
1028 
1031  void setValueOnSum(const Coord& xyz, const ValueType& value)
1032  {
1033  assert(BaseT::mTree);
1034  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1035  BaseT::mTree->setValueOnSum(xyz, value);
1036  }
1037 
1039  void setActiveState(const Coord& xyz, bool on = true)
1040  {
1041  assert(BaseT::mTree);
1042  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1043  BaseT::mTree->setActiveState(xyz, on);
1044  }
1046  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
1048  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
1049 
1051  template<typename NodeT> NodeT* getNode() { return NULL; }
1052 
1055  template<typename NodeT> void insertNode(const Coord&, NodeT&) {}
1056 
1060  template<typename NodeT> void eraseNode() {}
1061 
1062  LeafNodeT* touchLeaf(const Coord& xyz)
1063  {
1064  assert(BaseT::mTree);
1065  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1066  return BaseT::mTree->touchLeaf(xyz);
1067  }
1068 
1069  LeafNodeT* probeLeaf(const Coord& xyz)
1070  {
1071  assert(BaseT::mTree);
1072  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1073  return BaseT::mTree->probeLeaf(xyz);
1074  }
1075 
1076  const LeafNodeT* probeConstLeaf(const Coord& xyz)
1077  {
1078  assert(BaseT::mTree);
1079  return BaseT::mTree->probeConstLeaf(xyz);
1080  }
1081 
1083  virtual void clear() {}
1084 
1085 private:
1086  // Allow trees to deregister themselves.
1087  template<typename> friend class Tree;
1088 
1091  virtual void release() { this->BaseT::release(); }
1092 
1093 }; // ValueAccessor0
1094 
1095 
1102 template<typename _TreeType, Index L0>
1103 class ValueAccessor1 : public ValueAccessorBase<_TreeType>
1104 {
1105 public:
1106  BOOST_STATIC_ASSERT(_TreeType::DEPTH >= 2);
1107  BOOST_STATIC_ASSERT( L0 < _TreeType::RootNodeType::LEVEL );
1108  typedef _TreeType TreeType;
1109  typedef typename TreeType::ValueType ValueType;
1110  typedef typename TreeType::RootNodeType RootNodeT;
1111  typedef typename TreeType::LeafNodeType LeafNodeT;
1114  typedef typename boost::mpl::at<InvTreeT, boost::mpl::int_<L0> >::type NodeT0;
1115 
1117  ValueAccessor1(TreeType& tree) : BaseT(tree), mKey0(Coord::max()), mNode0(NULL)
1118  {
1119  }
1120 
1122  ValueAccessor1(const ValueAccessor1& other) : BaseT(other) { this->copy(other); }
1123 
1125  static Index numCacheLevels() { return 1; }
1126 
1128  ValueAccessor1& operator=(const ValueAccessor1& other)
1129  {
1130  if (&other != this) {
1131  this->BaseT::operator=(other);
1132  this->copy(other);
1133  }
1134  return *this;
1135  }
1136 
1138  virtual ~ValueAccessor1() {}
1139 
1142  bool isCached(const Coord& xyz) const
1143  {
1144  assert(BaseT::mTree);
1145  return this->isHashed(xyz);
1146  }
1147 
1149  const ValueType& getValue(const Coord& xyz) const
1150  {
1151  assert(BaseT::mTree);
1152  if (this->isHashed(xyz)) {
1153  assert(mNode0);
1154  return mNode0->getValueAndCache(xyz, this->self());
1155  }
1156  return BaseT::mTree->getRootNode().getValueAndCache(xyz, this->self());
1157  }
1158 
1160  bool isValueOn(const Coord& xyz) const
1161  {
1162  assert(BaseT::mTree);
1163  if (this->isHashed(xyz)) {
1164  assert(mNode0);
1165  return mNode0->isValueOnAndCache(xyz, this->self());
1166  }
1167  return BaseT::mTree->getRootNode().isValueOnAndCache(xyz, this->self());
1168  }
1169 
1171  bool probeValue(const Coord& xyz, ValueType& value) const
1172  {
1173  assert(BaseT::mTree);
1174  if (this->isHashed(xyz)) {
1175  assert(mNode0);
1176  return mNode0->probeValueAndCache(xyz, value, this->self());
1177  }
1178  return BaseT::mTree->getRootNode().probeValueAndCache(xyz, value, this->self());
1179  }
1180 
1184  int getValueDepth(const Coord& xyz) const
1185  {
1186  assert(BaseT::mTree);
1187  if (this->isHashed(xyz)) {
1188  assert(mNode0);
1189  return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->self());
1190  }
1191  return BaseT::mTree->getRootNode().getValueDepthAndCache(xyz, this->self());
1192  }
1193 
1196  bool isVoxel(const Coord& xyz) const
1197  {
1198  assert(BaseT::mTree);
1199  if (this->isHashed(xyz)) {
1200  assert(mNode0);
1201  return mNode0->getValueLevelAndCache(xyz, this->self()) == 0;
1202  }
1203  return BaseT::mTree->getRootNode().getValueDepthAndCache(xyz, this->self()) ==
1204  static_cast<int>(RootNodeT::LEVEL);
1205  }
1206 
1208 
1209  void setValue(const Coord& xyz, const ValueType& value)
1210  {
1211  assert(BaseT::mTree);
1212  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1213  if (this->isHashed(xyz)) {
1214  assert(mNode0);
1215  const_cast<NodeT0*>(mNode0)->setValueAndCache(xyz, value, *this);
1216  } else {
1217  BaseT::mTree->getRootNode().setValueAndCache(xyz, value, *this);
1218  }
1219  }
1220  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
1222 
1224  void setValueOnly(const Coord& xyz, const ValueType& value)
1225  {
1226  assert(BaseT::mTree);
1227  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1228  if (this->isHashed(xyz)) {
1229  assert(mNode0);
1230  const_cast<NodeT0*>(mNode0)->setValueOnlyAndCache(xyz, value, *this);
1231  } else {
1232  BaseT::mTree->getRootNode().setValueOnlyAndCache(xyz, value, *this);
1233  }
1234  }
1235 
1237  void setValueOff(const Coord& xyz, const ValueType& value)
1238  {
1239  assert(BaseT::mTree);
1240  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1241  if (this->isHashed(xyz)) {
1242  assert(mNode0);
1243  const_cast<NodeT0*>(mNode0)->setValueOffAndCache(xyz, value, *this);
1244  } else {
1245  BaseT::mTree->getRootNode().setValueOffAndCache(xyz, value, *this);
1246  }
1247  }
1248 
1251  void setValueOnSum(const Coord& xyz, const ValueType& value)
1252  {
1253  assert(BaseT::mTree);
1254  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1255  if (this->isHashed(xyz)) {
1256  assert(mNode0);
1257  const_cast<NodeT0*>(mNode0)->setValueOnSumAndCache(xyz, value, *this);
1258  } else {
1259  BaseT::mTree->getRootNode().setValueOnSumAndCache(xyz, value, *this);
1260  }
1261  }
1262 
1264  void setActiveState(const Coord& xyz, bool on = true)
1265  {
1266  assert(BaseT::mTree);
1267  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1268  if (this->isHashed(xyz)) {
1269  assert(mNode0);
1270  const_cast<NodeT0*>(mNode0)->setActiveStateAndCache(xyz, on, *this);
1271  } else {
1272  BaseT::mTree->getRootNode().setActiveStateAndCache(xyz, on, *this);
1273  }
1274  }
1276  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
1278  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
1279 
1281  template<typename NodeT>
1282  NodeT* getNode()
1283  {
1284  const NodeT* node = NULL;
1285  this->getNode(node);
1286  return const_cast<NodeT*>(node);
1287  }
1288 
1291  template<typename NodeT>
1292  void insertNode(const Coord& xyz, NodeT& node) { this->insert(xyz, &node); }
1293 
1297  template<typename NodeT>
1298  void eraseNode()
1299  {
1300  const NodeT* node = NULL;
1301  this->eraseNode(node);
1302  }
1303 
1310  LeafNodeT* touchLeaf(const Coord& xyz)
1311  {
1312  assert(BaseT::mTree);
1313  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1314  if (this->isHashed(xyz)) {
1315  assert(mNode0);
1316  return const_cast<NodeT0*>(mNode0)->touchLeafAndCache(xyz, *this);
1317  }
1318  return BaseT::mTree->getRootNode().touchLeafAndCache(xyz, *this);
1319  }
1320 
1323  LeafNodeT* probeLeaf(const Coord& xyz)
1324  {
1325  assert(BaseT::mTree);
1326  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1327  if (this->isHashed(xyz)) {
1328  assert(mNode0);
1329  return const_cast<NodeT0*>(mNode0)->probeLeafAndCache(xyz, *this);
1330  }
1331  return BaseT::mTree->getRootNode().probeLeafAndCache(xyz, *this);
1332  }
1333 
1336  const LeafNodeT* probeConstLeaf(const Coord& xyz)
1337  {
1338  assert(BaseT::mTree);
1339  if (this->isHashed(xyz)) {
1340  assert(mNode0);
1341  return mNode0->probeLeafAndCache(xyz, *this);
1342  }
1343  return BaseT::mTree->getRootNode().probeConstLeafAndCache(xyz, *this);
1344  }
1345 
1347  virtual void clear()
1348  {
1349  mKey0 = Coord::max();
1350  mNode0 = NULL;
1351  }
1352 
1353 private:
1354  // Allow nodes to insert themselves into the cache.
1355  template<typename> friend class RootNode;
1356  template<typename, Index> friend class InternalNode;
1357  template<typename, Index> friend class LeafNode;
1358  // Allow trees to deregister themselves.
1359  template<typename> friend class Tree;
1360 
1361  // This private method is merely for convenience.
1362  inline ValueAccessor1& self() const { return const_cast<ValueAccessor1&>(*this); }
1363 
1364  void getNode(const NodeT0*& node) { node = mNode0; }
1365  void getNode(const RootNodeT*& node)
1366  {
1367  node = (BaseT::mTree ? &BaseT::mTree->getRootNode() : NULL);
1368  }
1369  template <typename OtherNodeType> void getNode(const OtherNodeType*& node) { node = NULL; }
1370  void eraseNode(const NodeT0*) { mKey0 = Coord::max(); mNode0 = NULL; }
1371  template <typename OtherNodeType> void eraseNode(const OtherNodeType*) {}
1372 
1374  inline void copy(const ValueAccessor1& other)
1375  {
1376  mKey0 = other.mKey0;
1377  mNode0 = other.mNode0;
1378  }
1379 
1382  virtual void release()
1383  {
1384  this->BaseT::release();
1385  this->clear();
1386  }
1391  inline void insert(const Coord& xyz, const NodeT0* node)
1392  {
1393  assert(node);
1394  mKey0 = xyz & ~(NodeT0::DIM-1);
1395  mNode0 = node;
1396  }
1397 
1400  template<typename OtherNodeType> inline void insert(const Coord&, const OtherNodeType*) {}
1401 
1402  inline bool isHashed(const Coord& xyz) const
1403  {
1404  return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
1405  && (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
1406  && (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
1407  }
1408  mutable Coord mKey0;
1409  mutable const NodeT0* mNode0;
1410 }; // ValueAccessor1
1411 
1412 
1420 template<typename _TreeType, Index L0, Index L1>
1421 class ValueAccessor2 : public ValueAccessorBase<_TreeType>
1422 {
1423 public:
1424  BOOST_STATIC_ASSERT(_TreeType::DEPTH >= 3);
1425  BOOST_STATIC_ASSERT( L0 < L1 && L1 < _TreeType::RootNodeType::LEVEL );
1426  typedef _TreeType TreeType;
1427  typedef typename TreeType::ValueType ValueType;
1428  typedef typename TreeType::RootNodeType RootNodeT;
1429  typedef typename TreeType::LeafNodeType LeafNodeT;
1432  typedef typename boost::mpl::at<InvTreeT, boost::mpl::int_<L0> >::type NodeT0;
1433  typedef typename boost::mpl::at<InvTreeT, boost::mpl::int_<L1> >::type NodeT1;
1434 
1437  mKey0(Coord::max()), mNode0(NULL),
1438  mKey1(Coord::max()), mNode1(NULL) {}
1439 
1441  ValueAccessor2(const ValueAccessor2& other) : BaseT(other) { this->copy(other); }
1442 
1444  static Index numCacheLevels() { return 2; }
1445 
1447  ValueAccessor2& operator=(const ValueAccessor2& other)
1448  {
1449  if (&other != this) {
1450  this->BaseT::operator=(other);
1451  this->copy(other);
1452  }
1453  return *this;
1454  }
1455 
1457  virtual ~ValueAccessor2() {}
1458 
1461  bool isCached(const Coord& xyz) const
1462  {
1463  assert(BaseT::mTree);
1464  return this->isHashed1(xyz) || this->isHashed0(xyz);
1465  }
1466 
1468  const ValueType& getValue(const Coord& xyz) const
1469  {
1470  assert(BaseT::mTree);
1471  if (this->isHashed0(xyz)) {
1472  assert(mNode0);
1473  return mNode0->getValueAndCache(xyz, this->self());
1474  } else if (this->isHashed1(xyz)) {
1475  assert(mNode1);
1476  return mNode1->getValueAndCache(xyz, this->self());
1477  }
1478  return BaseT::mTree->getRootNode().getValueAndCache(xyz, this->self());
1479  }
1480 
1482  bool isValueOn(const Coord& xyz) const
1483  {
1484  assert(BaseT::mTree);
1485  if (this->isHashed0(xyz)) {
1486  assert(mNode0);
1487  return mNode0->isValueOnAndCache(xyz, this->self());
1488  } else if (this->isHashed1(xyz)) {
1489  assert(mNode1);
1490  return mNode1->isValueOnAndCache(xyz, this->self());
1491  }
1492  return BaseT::mTree->getRootNode().isValueOnAndCache(xyz, this->self());
1493  }
1494 
1496  bool probeValue(const Coord& xyz, ValueType& value) const
1497  {
1498  assert(BaseT::mTree);
1499  if (this->isHashed0(xyz)) {
1500  assert(mNode0);
1501  return mNode0->probeValueAndCache(xyz, value, this->self());
1502  } else if (this->isHashed1(xyz)) {
1503  assert(mNode1);
1504  return mNode1->probeValueAndCache(xyz, value, this->self());
1505  }
1506  return BaseT::mTree->getRootNode().probeValueAndCache(xyz, value, this->self());
1507  }
1508 
1512  int getValueDepth(const Coord& xyz) const
1513  {
1514  assert(BaseT::mTree);
1515  if (this->isHashed0(xyz)) {
1516  assert(mNode0);
1517  return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->self());
1518  } else if (this->isHashed1(xyz)) {
1519  assert(mNode1);
1520  return RootNodeT::LEVEL - mNode1->getValueLevelAndCache(xyz, this->self());
1521  }
1522  return BaseT::mTree->getRootNode().getValueDepthAndCache(xyz, this->self());
1523  }
1524 
1527  bool isVoxel(const Coord& xyz) const
1528  {
1529  assert(BaseT::mTree);
1530  if (this->isHashed0(xyz)) {
1531  assert(mNode0);
1532  return mNode0->getValueLevelAndCache(xyz, this->self())==0;
1533  } else if (this->isHashed1(xyz)) {
1534  assert(mNode1);
1535  return mNode1->getValueLevelAndCache(xyz, this->self())==0;
1536  }
1537  return BaseT::mTree->getRootNode().getValueDepthAndCache(xyz, this->self()) ==
1538  static_cast<int>(RootNodeT::LEVEL);
1539  }
1540 
1542 
1543  void setValue(const Coord& xyz, const ValueType& value)
1544  {
1545  assert(BaseT::mTree);
1546  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1547  if (this->isHashed0(xyz)) {
1548  assert(mNode0);
1549  const_cast<NodeT0*>(mNode0)->setValueAndCache(xyz, value, *this);
1550  } else if (this->isHashed1(xyz)) {
1551  assert(mNode1);
1552  const_cast<NodeT1*>(mNode1)->setValueAndCache(xyz, value, *this);
1553  } else {
1554  BaseT::mTree->getRootNode().setValueAndCache(xyz, value, *this);
1555  }
1556  }
1557  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
1559 
1561  void setValueOnly(const Coord& xyz, const ValueType& value)
1562  {
1563  assert(BaseT::mTree);
1564  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1565  if (this->isHashed0(xyz)) {
1566  assert(mNode0);
1567  const_cast<NodeT0*>(mNode0)->setValueOnlyAndCache(xyz, value, *this);
1568  } else if (this->isHashed1(xyz)) {
1569  assert(mNode1);
1570  const_cast<NodeT1*>(mNode1)->setValueOnlyAndCache(xyz, value, *this);
1571  } else {
1572  BaseT::mTree->getRootNode().setValueOnlyAndCache(xyz, value, *this);
1573  }
1574  }
1575 
1577  void setValueOff(const Coord& xyz, const ValueType& value)
1578  {
1579  assert(BaseT::mTree);
1580  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1581  if (this->isHashed0(xyz)) {
1582  assert(mNode0);
1583  const_cast<NodeT0*>(mNode0)->setValueOffAndCache(xyz, value, *this);
1584  } else if (this->isHashed1(xyz)) {
1585  assert(mNode1);
1586  const_cast<NodeT1*>(mNode1)->setValueOffAndCache(xyz, value, *this);
1587  } else {
1588  BaseT::mTree->getRootNode().setValueOffAndCache(xyz, value, *this);
1589  }
1590  }
1591 
1594  void setValueOnSum(const Coord& xyz, const ValueType& value)
1595  {
1596  assert(BaseT::mTree);
1597  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1598  if (this->isHashed0(xyz)) {
1599  assert(mNode0);
1600  const_cast<NodeT0*>(mNode0)->setValueOnSumAndCache(xyz, value, *this);
1601  } else if (this->isHashed1(xyz)) {
1602  assert(mNode1);
1603  const_cast<NodeT1*>(mNode1)->setValueOnSumAndCache(xyz, value, *this);
1604  } else {
1605  BaseT::mTree->getRootNode().setValueOnSumAndCache(xyz, value, *this);
1606  }
1607  }
1608 
1610  void setActiveState(const Coord& xyz, bool on = true)
1611  {
1612  assert(BaseT::mTree);
1613  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1614  if (this->isHashed0(xyz)) {
1615  assert(mNode0);
1616  const_cast<NodeT0*>(mNode0)->setActiveStateAndCache(xyz, on, *this);
1617  } else if (this->isHashed1(xyz)) {
1618  assert(mNode1);
1619  const_cast<NodeT1*>(mNode1)->setActiveStateAndCache(xyz, on, *this);
1620  } else {
1621  BaseT::mTree->getRootNode().setActiveStateAndCache(xyz, on, *this);
1622  }
1623  }
1625  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
1627  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
1628 
1630  template<typename NodeT>
1631  NodeT* getNode()
1632  {
1633  const NodeT* node = NULL;
1634  this->getNode(node);
1635  return const_cast<NodeT*>(node);
1636  }
1637 
1640  template<typename NodeT>
1641  void insertNode(const Coord& xyz, NodeT& node) { this->insert(xyz, &node); }
1642 
1646  template<typename NodeT>
1647  void eraseNode()
1648  {
1649  const NodeT* node = NULL;
1650  this->eraseNode(node);
1651  }
1652 
1659  LeafNodeT* touchLeaf(const Coord& xyz)
1660  {
1661  assert(BaseT::mTree);
1662  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1663  if (this->isHashed0(xyz)) {
1664  assert(mNode0);
1665  return const_cast<NodeT0*>(mNode0)->touchLeafAndCache(xyz, *this);
1666  } else if (this->isHashed1(xyz)) {
1667  assert(mNode1);
1668  return const_cast<NodeT1*>(mNode1)->touchLeafAndCache(xyz, *this);
1669  }
1670  return BaseT::mTree->getRootNode().touchLeafAndCache(xyz, *this);
1671  }
1672 
1675  LeafNodeT* probeLeaf(const Coord& xyz)
1676  {
1677  assert(BaseT::mTree);
1678  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1679  if (this->isHashed0(xyz)) {
1680  assert(mNode0);
1681  return const_cast<NodeT0*>(mNode0)->probeLeafAndCache(xyz, *this);
1682  } else if (this->isHashed1(xyz)) {
1683  assert(mNode1);
1684  return const_cast<NodeT1*>(mNode1)->probeLeafAndCache(xyz, *this);
1685  }
1686  return BaseT::mTree->getRootNode().probeLeafAndCache(xyz, *this);
1687  }
1688 
1691  const LeafNodeT* probeConstLeaf(const Coord& xyz)
1692  {
1693  assert(BaseT::mTree);
1694  if (this->isHashed0(xyz)) {
1695  assert(mNode0);
1696  return mNode0->probeConstLeafAndCache(xyz, *this);
1697  } else if (this->isHashed1(xyz)) {
1698  assert(mNode1);
1699  return mNode1->probeConstLeafAndCache(xyz, *this);
1700  }
1701  return BaseT::mTree->getRootNode().probeConstLeafAndCache(xyz, *this);
1702  }
1703 
1705  virtual void clear()
1706  {
1707  mKey0 = Coord::max();
1708  mNode0 = NULL;
1709  mKey1 = Coord::max();
1710  mNode1 = NULL;
1711  }
1712 
1713 private:
1714  // Allow nodes to insert themselves into the cache.
1715  template<typename> friend class RootNode;
1716  template<typename, Index> friend class InternalNode;
1717  template<typename, Index> friend class LeafNode;
1718  // Allow trees to deregister themselves.
1719  template<typename> friend class Tree;
1720 
1721  // This private method is merely for convenience.
1722  inline ValueAccessor2& self() const { return const_cast<ValueAccessor2&>(*this); }
1723 
1724  void getNode(const NodeT0*& node) { node = mNode0; }
1725  void getNode(const NodeT1*& node) { node = mNode1; }
1726  void getNode(const RootNodeT*& node)
1727  {
1728  node = (BaseT::mTree ? &BaseT::mTree->getRootNode() : NULL);
1729  }
1730  template <typename OtherNodeType> void getNode(const OtherNodeType*& node) { node = NULL; }
1731 
1732  void eraseNode(const NodeT0*) { mKey0 = Coord::max(); mNode0 = NULL; }
1733  void eraseNode(const NodeT1*) { mKey1 = Coord::max(); mNode1 = NULL; }
1734  template <typename OtherNodeType> void eraseNode(const OtherNodeType*) {}
1735 
1737  inline void copy(const ValueAccessor2& other)
1738  {
1739  mKey0 = other.mKey0;
1740  mNode0 = other.mNode0;
1741  mKey1 = other.mKey1;
1742  mNode1 = other.mNode1;
1743  }
1744 
1747  virtual void release()
1748  {
1749  this->BaseT::release();
1750  this->clear();
1751  }
1752 
1757  inline void insert(const Coord& xyz, const NodeT0* node)
1758  {
1759  assert(node);
1760  mKey0 = xyz & ~(NodeT0::DIM-1);
1761  mNode0 = node;
1762  }
1763  inline void insert(const Coord& xyz, const NodeT1* node)
1764  {
1765  assert(node);
1766  mKey1 = xyz & ~(NodeT1::DIM-1);
1767  mNode1 = node;
1768  }
1771  template<typename NodeT> inline void insert(const Coord&, const NodeT*) {}
1772 
1773  inline bool isHashed0(const Coord& xyz) const
1774  {
1775  return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
1776  && (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
1777  && (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
1778  }
1779  inline bool isHashed1(const Coord& xyz) const
1780  {
1781  return (xyz[0] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[0]
1782  && (xyz[1] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[1]
1783  && (xyz[2] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[2];
1784  }
1785  mutable Coord mKey0;
1786  mutable const NodeT0* mNode0;
1787  mutable Coord mKey1;
1788  mutable const NodeT1* mNode1;
1789 }; // ValueAccessor2
1790 
1791 
1802 template<typename _TreeType, Index L0, Index L1, Index L2>
1803 class ValueAccessor3 : public ValueAccessorBase<_TreeType>
1804 {
1805 public:
1806  BOOST_STATIC_ASSERT(_TreeType::DEPTH >= 4);
1807  BOOST_STATIC_ASSERT(L0 < L1 && L1 < L2 && L2 < _TreeType::RootNodeType::LEVEL);
1808  typedef _TreeType TreeType;
1809  typedef typename TreeType::ValueType ValueType;
1810  typedef typename TreeType::RootNodeType RootNodeT;
1811  typedef typename TreeType::LeafNodeType LeafNodeT;
1814  typedef typename boost::mpl::at<InvTreeT, boost::mpl::int_<L0> >::type NodeT0;
1815  typedef typename boost::mpl::at<InvTreeT, boost::mpl::int_<L1> >::type NodeT1;
1816  typedef typename boost::mpl::at<InvTreeT, boost::mpl::int_<L2> >::type NodeT2;
1817 
1820  mKey0(Coord::max()), mNode0(NULL),
1821  mKey1(Coord::max()), mNode1(NULL),
1822  mKey2(Coord::max()), mNode2(NULL) {}
1823 
1825  ValueAccessor3(const ValueAccessor3& other) : BaseT(other) { this->copy(other); }
1826 
1828  ValueAccessor3& operator=(const ValueAccessor3& other)
1829  {
1830  if (&other != this) {
1831  this->BaseT::operator=(other);
1832  this->copy(other);
1833  }
1834  return *this;
1835  }
1836 
1838  static Index numCacheLevels() { return 3; }
1839 
1841  virtual ~ValueAccessor3() {}
1842 
1845  bool isCached(const Coord& xyz) const
1846  {
1847  assert(BaseT::mTree);
1848  return this->isHashed2(xyz) || this->isHashed1(xyz) || this->isHashed0(xyz);
1849  }
1850 
1852  const ValueType& getValue(const Coord& xyz) const
1853  {
1854  assert(BaseT::mTree);
1855  if (this->isHashed0(xyz)) {
1856  assert(mNode0);
1857  return mNode0->getValueAndCache(xyz, this->self());
1858  } else if (this->isHashed1(xyz)) {
1859  assert(mNode1);
1860  return mNode1->getValueAndCache(xyz, this->self());
1861  } else if (this->isHashed2(xyz)) {
1862  assert(mNode2);
1863  return mNode2->getValueAndCache(xyz, this->self());
1864  }
1865  return BaseT::mTree->getRootNode().getValueAndCache(xyz, this->self());
1866  }
1867 
1869  bool isValueOn(const Coord& xyz) const
1870  {
1871  assert(BaseT::mTree);
1872  if (this->isHashed0(xyz)) {
1873  assert(mNode0);
1874  return mNode0->isValueOnAndCache(xyz, this->self());
1875  } else if (this->isHashed1(xyz)) {
1876  assert(mNode1);
1877  return mNode1->isValueOnAndCache(xyz, this->self());
1878  } else if (this->isHashed2(xyz)) {
1879  assert(mNode2);
1880  return mNode2->isValueOnAndCache(xyz, this->self());
1881  }
1882  return BaseT::mTree->getRootNode().isValueOnAndCache(xyz, this->self());
1883  }
1884 
1886  bool probeValue(const Coord& xyz, ValueType& value) const
1887  {
1888  assert(BaseT::mTree);
1889  if (this->isHashed0(xyz)) {
1890  assert(mNode0);
1891  return mNode0->probeValueAndCache(xyz, value, this->self());
1892  } else if (this->isHashed1(xyz)) {
1893  assert(mNode1);
1894  return mNode1->probeValueAndCache(xyz, value, this->self());
1895  } else if (this->isHashed2(xyz)) {
1896  assert(mNode2);
1897  return mNode2->probeValueAndCache(xyz, value, this->self());
1898  }
1899  return BaseT::mTree->getRootNode().probeValueAndCache(xyz, value, this->self());
1900  }
1901 
1905  int getValueDepth(const Coord& xyz) const
1906  {
1907  assert(BaseT::mTree);
1908  if (this->isHashed0(xyz)) {
1909  assert(mNode0);
1910  return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->self());
1911  } else if (this->isHashed1(xyz)) {
1912  assert(mNode1);
1913  return RootNodeT::LEVEL - mNode1->getValueLevelAndCache(xyz, this->self());
1914  } else if (this->isHashed2(xyz)) {
1915  assert(mNode2);
1916  return RootNodeT::LEVEL - mNode2->getValueLevelAndCache(xyz, this->self());
1917  }
1918  return BaseT::mTree->getRootNode().getValueDepthAndCache(xyz, this->self());
1919  }
1920 
1923  bool isVoxel(const Coord& xyz) const
1924  {
1925  assert(BaseT::mTree);
1926  if (this->isHashed0(xyz)) {
1927  assert(mNode0);
1928  return mNode0->getValueLevelAndCache(xyz, this->self())==0;
1929  } else if (this->isHashed1(xyz)) {
1930  assert(mNode1);
1931  return mNode1->getValueLevelAndCache(xyz, this->self())==0;
1932  } else if (this->isHashed2(xyz)) {
1933  assert(mNode2);
1934  return mNode2->getValueLevelAndCache(xyz, this->self())==0;
1935  }
1936  return BaseT::mTree->getRootNode().getValueDepthAndCache(xyz, this->self()) ==
1937  static_cast<int>(RootNodeT::LEVEL);
1938  }
1939 
1941 
1942  void setValue(const Coord& xyz, const ValueType& value)
1943  {
1944  assert(BaseT::mTree);
1945  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1946  if (this->isHashed0(xyz)) {
1947  assert(mNode0);
1948  const_cast<NodeT0*>(mNode0)->setValueAndCache(xyz, value, *this);
1949  } else if (this->isHashed1(xyz)) {
1950  assert(mNode1);
1951  const_cast<NodeT1*>(mNode1)->setValueAndCache(xyz, value, *this);
1952  } else if (this->isHashed2(xyz)) {
1953  assert(mNode2);
1954  const_cast<NodeT2*>(mNode2)->setValueAndCache(xyz, value, *this);
1955  } else {
1956  BaseT::mTree->getRootNode().setValueAndCache(xyz, value, *this);
1957  }
1958  }
1959  void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
1961 
1963  void setValueOnly(const Coord& xyz, const ValueType& value)
1964  {
1965  assert(BaseT::mTree);
1966  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1967  if (this->isHashed0(xyz)) {
1968  assert(mNode0);
1969  const_cast<NodeT0*>(mNode0)->setValueOnlyAndCache(xyz, value, *this);
1970  } else if (this->isHashed1(xyz)) {
1971  assert(mNode1);
1972  const_cast<NodeT1*>(mNode1)->setValueOnlyAndCache(xyz, value, *this);
1973  } else if (this->isHashed2(xyz)) {
1974  assert(mNode2);
1975  const_cast<NodeT2*>(mNode2)->setValueOnlyAndCache(xyz, value, *this);
1976  } else {
1977  BaseT::mTree->getRootNode().setValueOnlyAndCache(xyz, value, *this);
1978  }
1979  }
1980 
1982  void setValueOff(const Coord& xyz, const ValueType& value)
1983  {
1984  assert(BaseT::mTree);
1985  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
1986  if (this->isHashed0(xyz)) {
1987  assert(mNode0);
1988  const_cast<NodeT0*>(mNode0)->setValueOffAndCache(xyz, value, *this);
1989  } else if (this->isHashed1(xyz)) {
1990  assert(mNode1);
1991  const_cast<NodeT1*>(mNode1)->setValueOffAndCache(xyz, value, *this);
1992  } else if (this->isHashed2(xyz)) {
1993  assert(mNode2);
1994  const_cast<NodeT2*>(mNode2)->setValueOffAndCache(xyz, value, *this);
1995  } else {
1996  BaseT::mTree->getRootNode().setValueOffAndCache(xyz, value, *this);
1997  }
1998  }
1999 
2002  void setValueOnSum(const Coord& xyz, const ValueType& value)
2003  {
2004  assert(BaseT::mTree);
2005  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
2006  if (this->isHashed0(xyz)) {
2007  assert(mNode0);
2008  const_cast<NodeT0*>(mNode0)->setValueOnSumAndCache(xyz, value, *this);
2009  } else if (this->isHashed1(xyz)) {
2010  assert(mNode1);
2011  const_cast<NodeT1*>(mNode1)->setValueOnSumAndCache(xyz, value, *this);
2012  } else if (this->isHashed2(xyz)) {
2013  assert(mNode2);
2014  const_cast<NodeT2*>(mNode2)->setValueOnSumAndCache(xyz, value, *this);
2015  } else {
2016  BaseT::mTree->getRootNode().setValueOnSumAndCache(xyz, value, *this);
2017  }
2018  }
2019 
2021  void setActiveState(const Coord& xyz, bool on = true)
2022  {
2023  assert(BaseT::mTree);
2024  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
2025  if (this->isHashed0(xyz)) {
2026  assert(mNode0);
2027  const_cast<NodeT0*>(mNode0)->setActiveStateAndCache(xyz, on, *this);
2028  } else if (this->isHashed1(xyz)) {
2029  assert(mNode1);
2030  const_cast<NodeT1*>(mNode1)->setActiveStateAndCache(xyz, on, *this);
2031  } else if (this->isHashed2(xyz)) {
2032  assert(mNode2);
2033  const_cast<NodeT2*>(mNode2)->setActiveStateAndCache(xyz, on, *this);
2034  } else {
2035  BaseT::mTree->getRootNode().setActiveStateAndCache(xyz, on, *this);
2036  }
2037  }
2039  void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
2041  void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
2042 
2044  template<typename NodeT>
2045  NodeT* getNode()
2046  {
2047  const NodeT* node = NULL;
2048  this->getNode(node);
2049  return const_cast<NodeT*>(node);
2050  }
2051 
2054  template<typename NodeT>
2055  void insertNode(const Coord& xyz, NodeT& node) { this->insert(xyz, &node); }
2056 
2060  template<typename NodeT>
2061  void eraseNode()
2062  {
2063  const NodeT* node = NULL;
2064  this->eraseNode(node);
2065  }
2066 
2073  LeafNodeT* touchLeaf(const Coord& xyz)
2074  {
2075  assert(BaseT::mTree);
2076  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
2077  if (this->isHashed0(xyz)) {
2078  assert(mNode0);
2079  return const_cast<NodeT0*>(mNode0)->touchLeafAndCache(xyz, *this);
2080  } else if (this->isHashed1(xyz)) {
2081  assert(mNode1);
2082  return const_cast<NodeT1*>(mNode1)->touchLeafAndCache(xyz, *this);
2083  } else if (this->isHashed2(xyz)) {
2084  assert(mNode2);
2085  return const_cast<NodeT2*>(mNode2)->touchLeafAndCache(xyz, *this);
2086  }
2087  return BaseT::mTree->getRootNode().touchLeafAndCache(xyz, *this);
2088  }
2089 
2092  LeafNodeT* probeLeaf(const Coord& xyz)
2093  {
2094  assert(BaseT::mTree);
2095  BOOST_STATIC_ASSERT(!BaseT::IsConstTree);
2096  if (this->isHashed0(xyz)) {
2097  assert(mNode0);
2098  return const_cast<NodeT0*>(mNode0)->probeLeafAndCache(xyz, *this);
2099  } else if (this->isHashed1(xyz)) {
2100  assert(mNode1);
2101  return const_cast<NodeT1*>(mNode1)->probeLeafAndCache(xyz, *this);
2102  } else if (this->isHashed2(xyz)) {
2103  assert(mNode2);
2104  return const_cast<NodeT2*>(mNode2)->probeLeafAndCache(xyz, *this);
2105  }
2106  return BaseT::mTree->getRootNode().probeLeafAndCache(xyz, *this);
2107  }
2108 
2111  const LeafNodeT* probeConstLeaf(const Coord& xyz)
2112  {
2113  assert(BaseT::mTree);
2114  if (this->isHashed0(xyz)) {
2115  assert(mNode0);
2116  return mNode0->probeConstLeafAndCache(xyz, *this);
2117  } else if (this->isHashed1(xyz)) {
2118  assert(mNode1);
2119  return mNode1->probeConstLeafAndCache(xyz, *this);
2120  } else if (this->isHashed2(xyz)) {
2121  assert(mNode2);
2122  return mNode2->probeConstLeafAndCache(xyz, *this);
2123  }
2124  return BaseT::mTree->getRootNode().probeConstLeafAndCache(xyz, *this);
2125  }
2126 
2128  virtual void clear()
2129  {
2130  mKey0 = Coord::max();
2131  mNode0 = NULL;
2132  mKey1 = Coord::max();
2133  mNode1 = NULL;
2134  mKey2 = Coord::max();
2135  mNode2 = NULL;
2136  }
2137 
2138 private:
2139  // Allow nodes to insert themselves into the cache.
2140  template<typename> friend class RootNode;
2141  template<typename, Index> friend class InternalNode;
2142  template<typename, Index> friend class LeafNode;
2143  // Allow trees to deregister themselves.
2144  template<typename> friend class Tree;
2145 
2146  // This private method is merely for convenience.
2147  inline ValueAccessor3& self() const { return const_cast<ValueAccessor3&>(*this); }
2148 
2150  inline void copy(const ValueAccessor3& other)
2151  {
2152  mKey0 = other.mKey0;
2153  mNode0 = other.mNode0;
2154  mKey1 = other.mKey1;
2155  mNode1 = other.mNode1;
2156  mKey2 = other.mKey2;
2157  mNode2 = other.mNode2;
2158  }
2159 
2162  virtual void release()
2163  {
2164  this->BaseT::release();
2165  this->clear();
2166  }
2167  void getNode(const NodeT0*& node) { node = mNode0; }
2168  void getNode(const NodeT1*& node) { node = mNode1; }
2169  void getNode(const NodeT2*& node) { node = mNode2; }
2170  void getNode(const RootNodeT*& node)
2171  {
2172  node = (BaseT::mTree ? &BaseT::mTree->getRootNode() : NULL);
2173  }
2174  template <typename OtherNodeType> void getNode(const OtherNodeType*& node) { node = NULL; }
2175 
2176  void eraseNode(const NodeT0*) { mKey0 = Coord::max(); mNode0 = NULL; }
2177  void eraseNode(const NodeT1*) { mKey1 = Coord::max(); mNode1 = NULL; }
2178  void eraseNode(const NodeT2*) { mKey2 = Coord::max(); mNode2 = NULL; }
2179  template <typename OtherNodeType> void eraseNode(const OtherNodeType*) {}
2180 
2185  inline void insert(const Coord& xyz, const NodeT0* node)
2186  {
2187  assert(node);
2188  mKey0 = xyz & ~(NodeT0::DIM-1);
2189  mNode0 = node;
2190  }
2191  inline void insert(const Coord& xyz, const NodeT1* node)
2192  {
2193  assert(node);
2194  mKey1 = xyz & ~(NodeT1::DIM-1);
2195  mNode1 = node;
2196  }
2197  inline void insert(const Coord& xyz, const NodeT2* node)
2198  {
2199  assert(node);
2200  mKey2 = xyz & ~(NodeT2::DIM-1);
2201  mNode2 = node;
2202  }
2205  template<typename OtherNodeType>
2206  inline void insert(const Coord&, const OtherNodeType*)
2207  {
2208  }
2209  inline bool isHashed0(const Coord& xyz) const
2210  {
2211  return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
2212  && (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
2213  && (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
2214  }
2215  inline bool isHashed1(const Coord& xyz) const
2216  {
2217  return (xyz[0] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[0]
2218  && (xyz[1] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[1]
2219  && (xyz[2] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[2];
2220  }
2221  inline bool isHashed2(const Coord& xyz) const
2222  {
2223  return (xyz[0] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[0]
2224  && (xyz[1] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[1]
2225  && (xyz[2] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[2];
2226  }
2227  mutable Coord mKey0;
2228  mutable const NodeT0* mNode0;
2229  mutable Coord mKey1;
2230  mutable const NodeT1* mNode1;
2231  mutable Coord mKey2;
2232  mutable const NodeT2* mNode2;
2233 }; // ValueAccessor3
2234 
2235 } // namespace tree
2236 } // namespace OPENVDB_VERSION_NAME
2237 } // namespace openvdb
2238 
2239 #endif // OPENVDB_TREE_VALUEACCESSOR_HAS_BEEN_INCLUDED
2240 
2241 // Copyright (c) 2012 DreamWorks Animation LLC
2242 // All rights reserved. This software is distributed under the
2243 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )