8 #ifndef OPENVDB_TREE_ROOTNODE_HAS_BEEN_INCLUDED 9 #define OPENVDB_TREE_ROOTNODE_HAS_BEEN_INCLUDED 18 #include <openvdb/version.h> 19 #include <tbb/parallel_for.h> 32 template<
typename HeadType,
int HeadLevel>
struct NodeChain;
38 template<
typename ChildType>
47 static const Index LEVEL = 1 + ChildType::LEVEL;
51 static_assert(NodeChainType::Size == LEVEL + 1,
52 "wrong number of entries in RootNode node chain");
56 template<
typename OtherValueType>
64 template<
typename OtherNodeType>
84 template<
typename OtherChildType>
95 template<
typename OtherChildType>
109 template<
typename OtherChildType>
121 template<
typename OtherChildType>
128 Tile(): value(zeroVal<ValueType>()), active(
false) {}
129 Tile(
const ValueType& v,
bool b): value(v), active(b) {}
139 NodeStruct(): child(
nullptr) {}
140 NodeStruct(ChildType& c): child(&c) {}
141 NodeStruct(
const Tile& t): child(
nullptr), tile(t) {}
142 NodeStruct(
const NodeStruct&) =
default;
143 NodeStruct(NodeStruct&&) noexcept =
default;
144 NodeStruct& operator=(
const NodeStruct&) =
default;
147 bool isChild()
const {
return child !=
nullptr; }
148 bool isTile()
const {
return child ==
nullptr; }
149 bool isTileOff()
const {
return isTile() && !tile.active; }
150 bool isTileOn()
const {
return isTile() && tile.active; }
152 void set(ChildType& c) {
delete child; child = &c; }
153 void set(
const Tile& t) {
delete child; child =
nullptr; tile = t; }
154 ChildType& steal(
const Tile& t) { ChildType* c=child; child=
nullptr; tile=t;
return *c; }
157 using MapType = std::map<Coord, NodeStruct>;
158 using MapIter =
typename MapType::iterator;
159 using MapCIter =
typename MapType::const_iterator;
161 using CoordSet = std::set<Coord>;
162 using CoordSetIter =
typename CoordSet::iterator;
163 using CoordSetCIter =
typename CoordSet::const_iterator;
165 static void setTile(
const MapIter& i,
const Tile& t) { i->second.set(t); }
166 static void setChild(
const MapIter& i, ChildType& c) { i->second.set(c); }
167 static Tile& getTile(
const MapIter& i) {
return i->second.tile; }
168 static const Tile& getTile(
const MapCIter& i) {
return i->second.tile; }
169 static ChildType& getChild(
const MapIter& i) {
return *(i->second.child); }
170 static const ChildType& getChild(
const MapCIter& i) {
return *(i->second.child); }
171 static ChildType& stealChild(
const MapIter& i,
const Tile& t) {
return i->second.steal(t);}
172 static const ChildType& stealChild(
const MapCIter& i,
const Tile& t) {
return i->second.steal(t);}
174 static bool isChild(
const MapCIter& i) {
return i->second.isChild(); }
175 static bool isChild(
const MapIter& i) {
return i->second.isChild(); }
176 static bool isTile(
const MapCIter& i) {
return i->second.isTile(); }
177 static bool isTile(
const MapIter& i) {
return i->second.isTile(); }
178 static bool isTileOff(
const MapCIter& i) {
return i->second.isTileOff(); }
179 static bool isTileOff(
const MapIter& i) {
return i->second.isTileOff(); }
180 static bool isTileOn(
const MapCIter& i) {
return i->second.isTileOn(); }
181 static bool isTileOn(
const MapIter& i) {
return i->second.isTileOn(); }
184 static inline bool test(
const MapIter&) {
return true; }
185 static inline bool test(
const MapCIter&) {
return true; }
188 static inline bool test(
const MapIter& i) {
return isTileOn(i); }
189 static inline bool test(
const MapCIter& i) {
return isTileOn(i); }
191 struct ValueOffPred {
192 static inline bool test(
const MapIter& i) {
return isTileOff(i); }
193 static inline bool test(
const MapCIter& i) {
return isTileOff(i); }
195 struct ValueAllPred {
196 static inline bool test(
const MapIter& i) {
return isTile(i); }
197 static inline bool test(
const MapCIter& i) {
return isTile(i); }
200 static inline bool test(
const MapIter& i) {
return isChild(i); }
201 static inline bool test(
const MapCIter& i) {
return isChild(i); }
203 struct ChildOffPred {
204 static inline bool test(
const MapIter& i) {
return isTile(i); }
205 static inline bool test(
const MapCIter& i) {
return isTile(i); }
208 template<
typename _RootNodeT,
typename _MapIterT,
typename FilterPredT>
212 using RootNodeT = _RootNodeT;
213 using MapIterT = _MapIterT;
217 return (mParentNode == other.mParentNode) && (mIter == other.mIter);
219 bool operator!=(
const BaseIter& other)
const {
return !(*
this == other); }
221 RootNodeT* getParentNode()
const {
return mParentNode; }
223 RootNodeT& parent()
const 229 bool test()
const {
OPENVDB_ASSERT(mParentNode);
return mIter != mParentNode->mTable.end(); }
230 operator bool()
const {
return this->test(); }
232 void increment() {
if (this->test()) { ++mIter; } this->skip(); }
233 bool next() { this->increment();
return this->test(); }
234 void increment(
Index n) {
for (
Index i = 0; i < n && this->next(); ++i) {} }
240 return !mParentNode ? 0U :
Index(std::distance(mParentNode->mTable.begin(), mIter));
243 bool isValueOn()
const {
return RootNodeT::isTileOn(mIter); }
244 bool isValueOff()
const {
return RootNodeT::isTileOff(mIter); }
245 void setValueOn(
bool on =
true)
const { mIter->second.tile.active = on; }
246 void setValueOff()
const { mIter->second.tile.active =
false; }
249 Coord getCoord()
const {
return mIter->first; }
251 void getCoord(Coord& xyz)
const { xyz = this->getCoord(); }
254 BaseIter(): mParentNode(
nullptr) {}
255 BaseIter(RootNodeT& parent,
const MapIterT& iter): mParentNode(&parent), mIter(iter) {}
257 void skip() {
while (this->test() && !FilterPredT::test(mIter)) ++mIter; }
259 RootNodeT* mParentNode;
263 template<
typename RootNodeT,
typename MapIterT,
typename FilterPredT,
typename ChildNodeT>
264 class ChildIter:
public BaseIter<RootNodeT, MapIterT, FilterPredT>
267 using BaseT = BaseIter<RootNodeT, MapIterT, FilterPredT>;
268 using NodeType = RootNodeT;
271 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
272 using NonConstValueType =
typename std::remove_const<ValueType>::type;
273 using NonConstChildNodeType =
typename std::remove_const<ChildNodeType>::type;
277 ChildIter(RootNodeT& parent,
const MapIterT& iter): BaseT(parent, iter) { BaseT::skip(); }
279 ChildIter& operator++() { BaseT::increment();
return *
this; }
281 ChildNodeT& getValue()
const {
return getChild(mIter); }
282 ChildNodeT&
operator*()
const {
return this->getValue(); }
283 ChildNodeT* operator->()
const {
return &this->getValue(); }
286 template<
typename RootNodeT,
typename MapIterT,
typename FilterPredT,
typename ValueT>
287 class ValueIter:
public BaseIter<RootNodeT, MapIterT, FilterPredT>
290 using BaseT = BaseIter<RootNodeT, MapIterT, FilterPredT>;
291 using NodeType = RootNodeT;
293 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
294 using NonConstValueType =
typename std::remove_const<ValueT>::type;
298 ValueIter(RootNodeT& parent,
const MapIterT& iter): BaseT(parent, iter) { BaseT::skip(); }
300 ValueIter& operator++() { BaseT::increment();
return *
this; }
302 ValueT& getValue()
const {
return getTile(mIter).value; }
303 ValueT&
operator*()
const {
return this->getValue(); }
304 ValueT* operator->()
const {
return &(this->getValue()); }
306 void setValue(
const ValueT& v)
const {
OPENVDB_ASSERT(isTile(mIter)); getTile(mIter).value = v; }
308 template<
typename ModifyOp>
309 void modifyValue(
const ModifyOp&
op)
const 312 op(getTile(mIter).value);
316 template<
typename RootNodeT,
typename MapIterT,
typename ChildNodeT,
typename ValueT>
317 class DenseIter:
public BaseIter<RootNodeT, MapIterT, NullPred>
320 using BaseT = BaseIter<RootNodeT, MapIterT, NullPred>;
321 using NodeType = RootNodeT;
324 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
325 using NonConstValueType =
typename std::remove_const<ValueT>::type;
326 using NonConstChildNodeType =
typename std::remove_const<ChildNodeT>::type;
330 DenseIter(RootNodeT& parent,
const MapIterT& iter): BaseT(parent, iter) {}
332 DenseIter& operator++() { BaseT::increment();
return *
this; }
334 bool isChildNode()
const {
return isChild(mIter); }
336 ChildNodeT* probeChild(NonConstValueType& value)
const 338 if (isChild(mIter))
return &getChild(mIter);
339 value = getTile(mIter).value;
342 bool probeChild(ChildNodeT*& child, NonConstValueType& value)
const 344 child = this->probeChild(value);
345 return child !=
nullptr;
347 bool probeValue(NonConstValueType& value)
const {
return !this->probeChild(value); }
349 void setChild(ChildNodeT& c)
const { RootNodeT::setChild(mIter, c); }
350 void setChild(ChildNodeT* c)
const {
OPENVDB_ASSERT(c !=
nullptr); RootNodeT::setChild(mIter, *c); }
351 void setValue(
const ValueT& v)
const 353 if (isTile(mIter)) getTile(mIter).value = v;
357 else stealChild(mIter, Tile(v,
true));
362 using ChildOnIter = ChildIter<RootNode, MapIter, ChildOnPred, ChildType>;
363 using ChildOnCIter = ChildIter<const RootNode, MapCIter, ChildOnPred, const ChildType>;
364 using ChildOffIter = ValueIter<RootNode, MapIter, ChildOffPred, const ValueType>;
365 using ChildOffCIter = ValueIter<const RootNode, MapCIter, ChildOffPred, ValueType>;
366 using ChildAllIter = DenseIter<RootNode, MapIter, ChildType, ValueType>;
367 using ChildAllCIter = DenseIter<const RootNode, MapCIter, const ChildType, const ValueType>;
369 using ValueOnIter = ValueIter<RootNode, MapIter, ValueOnPred, ValueType>;
370 using ValueOnCIter = ValueIter<const RootNode, MapCIter, ValueOnPred, const ValueType>;
371 using ValueOffIter = ValueIter<RootNode, MapIter, ValueOffPred, ValueType>;
372 using ValueOffCIter = ValueIter<const RootNode, MapCIter, ValueOffPred, const ValueType>;
373 using ValueAllIter = ValueIter<RootNode, MapIter, ValueAllPred, ValueType>;
374 using ValueAllCIter = ValueIter<const RootNode, MapCIter, ValueAllPred, const ValueType>;
405 void evalActiveBoundingBox(CoordBBox& bbox,
bool visitVoxels =
true)
const;
427 void setBackground(
const ValueType& value,
bool updateChildNodes);
433 bool isBackgroundTile(
const Tile&)
const;
436 bool isBackgroundTile(
const MapIter&)
const;
437 bool isBackgroundTile(
const MapCIter&)
const;
441 size_t numBackgroundTiles()
const;
444 size_t eraseBackgroundTiles();
448 bool empty()
const {
return mTable.size() == numBackgroundTiles(); }
453 bool expand(
const Coord& xyz);
456 static void getNodeLog2Dims(std::vector<Index>& dims);
462 Index getWidth()
const {
return this->getMaxIndex()[0] - this->getMinIndex()[0]; }
463 Index getHeight()
const {
return this->getMaxIndex()[1] - this->getMinIndex()[1]; }
464 Index getDepth()
const {
return this->getMaxIndex()[2] - this->getMinIndex()[2]; }
467 Coord getMinIndex()
const;
469 Coord getMaxIndex()
const;
471 void getIndexRange(CoordBBox& bbox)
const;
475 template<
typename OtherChildType>
479 template<
typename OtherChildType>
484 template<
typename OtherChildType>
491 Index32 activeTileCount()
const;
492 Index32 inactiveTileCount()
const;
495 Index64 onLeafVoxelCount()
const;
496 Index64 offLeafVoxelCount()
const;
498 void nodeCount(std::vector<Index64> &vec)
const;
500 void nodeCount(std::vector<Index32> &vec)
const;
502 bool isValueOn(
const Coord& xyz)
const;
505 bool hasActiveTiles()
const;
507 const ValueType& getValue(
const Coord& xyz)
const;
508 bool probeValue(
const Coord& xyz,
ValueType& value)
const;
513 int getValueDepth(
const Coord& xyz)
const;
516 void setActiveState(
const Coord& xyz,
bool on);
518 void setValueOnly(
const Coord& xyz,
const ValueType& value);
520 void setValueOn(
const Coord& xyz,
const ValueType& value);
522 void setValueOff(
const Coord& xyz);
524 void setValueOff(
const Coord& xyz,
const ValueType& value);
528 template<
typename ModifyOp>
529 void modifyValue(
const Coord& xyz,
const ModifyOp&
op);
531 template<
typename ModifyOp>
532 void modifyValueAndActiveState(
const Coord& xyz,
const ModifyOp& op);
543 void fill(
const CoordBBox& bbox,
const ValueType& value,
bool active =
true);
546 this->fill(bbox, value, active);
557 void denseFill(
const CoordBBox& bbox,
const ValueType& value,
bool active =
true);
567 void voxelizeActiveTiles(
bool threaded =
true);
574 template<
typename DenseT>
575 void copyToDense(
const CoordBBox& bbox, DenseT& dense)
const;
581 bool writeTopology(std::ostream&,
bool toHalf =
false)
const;
582 bool readTopology(std::istream&,
bool fromHalf =
false);
584 void writeBuffers(std::ostream&,
bool toHalf =
false)
const;
585 void readBuffers(std::istream&,
bool fromHalf =
false);
586 void readBuffers(std::istream&,
const CoordBBox&,
bool fromHalf =
false);
596 template<
typename AccessorT>
597 const ValueType& getValueAndCache(
const Coord& xyz, AccessorT&)
const;
602 template<
typename AccessorT>
603 bool isValueOnAndCache(
const Coord& xyz, AccessorT&)
const;
609 template<
typename AccessorT>
610 void setValueAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
616 template<
typename AccessorT>
617 void setValueOnlyAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
624 template<
typename ModifyOp,
typename AccessorT>
625 void modifyValueAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
631 template<
typename ModifyOp,
typename AccessorT>
632 void modifyValueAndActiveStateAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
638 template<
typename AccessorT>
639 void setValueOffAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
645 template<
typename AccessorT>
646 void setActiveStateAndCache(
const Coord& xyz,
bool on, AccessorT&);
653 template<
typename AccessorT>
654 bool probeValueAndCache(
const Coord& xyz,
ValueType& value, AccessorT&)
const;
661 template<
typename AccessorT>
662 int getValueDepthAndCache(
const Coord& xyz, AccessorT&)
const;
665 void clip(
const CoordBBox&);
680 template<
typename AccessorT>
691 template<
typename NodeT>
692 NodeT* stealNode(
const Coord& xyz,
const ValueType& value,
bool state);
699 bool addChild(ChildType* child);
703 void addTile(
const Coord& xyz,
const ValueType& value,
bool state);
708 void addTile(
Index level,
const Coord& xyz,
const ValueType& value,
bool state);
712 template<
typename AccessorT>
713 void addTileAndCache(
Index level,
const Coord& xyz,
const ValueType&,
bool state, AccessorT&);
719 bool deleteChildOrTile(
const Coord& xyz);
730 template<
typename AccessorT>
731 LeafNodeType* touchLeafAndCache(
const Coord& xyz, AccessorT& acc);
736 template <
typename NodeT>
737 NodeT* probeNode(
const Coord& xyz);
738 template <
typename NodeT>
739 const NodeT* probeNode(
const Coord& xyz)
const;
740 template <
typename NodeT>
741 const NodeT* probeConstNode(
const Coord& xyz)
const;
750 bool probe(
const Coord& xyz,
const ChildNodeType*& child,
ValueType& value,
bool& active)
const {
return this->probeConst(xyz, child, value, active); }
756 template<
typename NodeT,
typename AccessorT>
757 NodeT* probeNodeAndCache(
const Coord& xyz, AccessorT& acc);
758 template<
typename NodeT,
typename AccessorT>
759 const NodeT* probeConstNodeAndCache(
const Coord& xyz, AccessorT& acc)
const;
766 const ChildNodeType* probeConstChild(
const Coord& xyz)
const;
774 const LeafNodeType* probeConstLeaf(
const Coord& xyz)
const;
781 template<
typename AccessorT>
782 LeafNodeType* probeLeafAndCache(
const Coord& xyz, AccessorT& acc);
783 template<
typename AccessorT>
784 const LeafNodeType* probeConstLeafAndCache(
const Coord& xyz, AccessorT& acc)
const;
785 template<
typename AccessorT>
786 const LeafNodeType* probeLeafAndCache(
const Coord& xyz, AccessorT& acc)
const;
800 const ValueType& getTileValueUnsafe(
const Coord& xyz)
const;
804 bool getTileValueUnsafe(
const Coord& xyz,
ValueType& value)
const;
812 const ChildNodeType* getConstChildUnsafe(
const Coord& xyz)
const;
846 template<
typename ArrayT>
void getNodes(ArrayT& array);
847 template<
typename ArrayT>
void getNodes(ArrayT& array)
const;
874 template<
typename ArrayT>
875 void stealNodes(ArrayT& array,
const ValueType& value,
bool state);
876 template<
typename ArrayT>
905 template<
typename OtherChildType>
921 template<
typename OtherChildType>
934 template<
typename OtherChildType>
937 template<
typename CombineOp>
940 template<
typename CombineOp,
typename OtherRootNode >
941 void combine2(
const RootNode& other0,
const OtherRootNode& other1,
942 CombineOp& op,
bool prune =
false);
945 const Coord&
origin()
const {
return mOrigin; }
951 void setOrigin(
const Coord &origin);
954 Coord
coordToKey(
const Coord& xyz)
const {
return (xyz - mOrigin) & ~(ChildType::DIM - 1); }
957 bool hasKey(
const Coord& key)
const {
return mTable.find(key) != mTable.end(); }
968 void insertKeys(CoordSet&)
const;
973 MapIter findKey(
const Coord& key) {
return mTable.find(key); }
974 MapCIter findKey(
const Coord& key)
const {
return mTable.find(key); }
979 MapIter findCoord(
const Coord& xyz) {
return mTable.find(coordToKey(xyz)); }
980 MapCIter findCoord(
const Coord& xyz)
const {
return mTable.find(coordToKey(xyz)); }
985 MapIter findOrAddCoord(
const Coord& xyz);
991 template<
typename OtherChildType>
999 template<
typename OtherChildType>
1002 template<
typename CombineOp,
typename OtherRootNode >
1003 void doCombine2(
const RootNode&,
const OtherRootNode&, CombineOp&,
bool prune);
1036 template<
typename HeadT,
int HeadLevel>
1039 using Type =
typename SubtreeT::template Append<HeadT>;
1043 template<
typename HeadT>
1055 template<
typename ChildT1,
typename NodeT2>
1057 static const bool value =
false;
1060 template<
typename ChildT1,
typename ChildT2>
1062 static const bool value = ChildT1::template SameConfiguration<ChildT2>::value;
1070 template<
typename ChildT>
1079 template<
typename ChildT>
1082 : mBackground(background)
1088 template<
typename ChildT>
1089 template<
typename OtherChildType>
1093 : mBackground(backgd)
1094 , mOrigin(other.mOrigin)
1095 , mTransientData(other.mTransientData)
1099 if (mOrigin != Coord(0,0,0)) {
1103 enforceSameConfiguration(other);
1105 const Tile bgTile(backgd,
false), fgTile(foregd,
true);
1107 for (
typename OtherRootT::MapCIter i=other.mTable.begin(), e=other.mTable.end(); i != e; ++i) {
1108 mTable.emplace(i->first, OtherRootT::isTile(i)
1109 ? NodeStruct(OtherRootT::isTileOn(i) ? fgTile : bgTile)
1110 : NodeStruct(*(
new ChildT(OtherRootT::getChild(i), backgd, foregd,
TopologyCopy()))));
1115 template<
typename ChildT>
1116 template<
typename OtherChildType>
1120 : mBackground(backgd)
1121 , mOrigin(other.mOrigin)
1122 , mTransientData(other.mTransientData)
1126 if (mOrigin != Coord(0,0,0)) {
1130 enforceSameConfiguration(other);
1132 const Tile bgTile(backgd,
false), fgTile(backgd,
true);
1134 for (
typename OtherRootT::MapCIter i=other.mTable.begin(), e=other.mTable.end(); i != e; ++i) {
1135 mTable.emplace(i->first,
1136 OtherRootT::isTile(i)
1137 ? NodeStruct(OtherRootT::isTileOn(i) ? fgTile : bgTile)
1138 : NodeStruct(*(
new ChildT(OtherRootT::getChild(i), backgd,
TopologyCopy()))));
1149 template<
typename RootT,
typename OtherRootT,
bool Compatible = false>
1156 self.enforceSameConfiguration(other);
1157 self.enforceCompatibleValueTypes(other);
1159 std::ostringstream ostr;
1160 ostr <<
"cannot convert a " <<
typeid(OtherRootT).name()
1161 <<
" to a " <<
typeid(RootT).name();
1167 template<
typename RootT,
typename OtherRootT>
1172 using ValueT =
typename RootT::ValueType;
1173 using ChildT =
typename RootT::ChildNodeType;
1174 using Tile =
typename RootT::Tile;
1175 using OtherValueT =
typename OtherRootT::ValueType;
1176 using OtherMapCIter =
typename OtherRootT::MapCIter;
1177 using OtherTile =
typename OtherRootT::Tile;
1181 static inline ValueT convertValue(
const OtherValueT& val) {
return ValueT(val); }
1184 self.mBackground = Local::convertValue(other.mBackground);
1185 if (other.mOrigin != Coord(0,0,0)) {
1186 OPENVDB_THROW(
ValueError,
"RootNodeCopyHelper::copyWithValueConversion: non-zero offsets are currently not supported");
1188 self.mOrigin = other.mOrigin;
1189 self.mTransientData = other.mTransientData;
1193 for (OtherMapCIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
1194 if (other.isTile(i)) {
1196 const OtherTile& otherTile = other.getTile(i);
1197 self.mTable.emplace(i->first,
1198 Tile(Local::convertValue(otherTile.value), otherTile.active));
1201 self.mTable.emplace(i->first, *(
new ChildT(other.getChild(i))));
1209 template<
typename ChildT>
1213 if (&other !=
this) {
1214 mBackground = other.mBackground;
1215 mOrigin = other.mOrigin;
1216 if (mOrigin != Coord(0,0,0)) {
1219 mTransientData = other.mTransientData;
1223 for (MapCIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
1224 mTable.emplace(i->first,
1225 isTile(i) ? NodeStruct(getTile(i)) : NodeStruct(*(
new ChildT(getChild(i)))));
1232 template<
typename ChildT>
1233 template<
typename OtherChildType>
1238 using OtherValueT =
typename OtherRootT::ValueType;
1248 template<
typename ChildT>
1254 if (updateChildNodes) {
1257 for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
1258 ChildT *child = iter->second.child;
1260 child->resetBackground(mBackground, background);
1262 Tile& tile = getTile(iter);
1263 if (tile.active)
continue;
1275 template<
typename ChildT>
1282 template<
typename ChildT>
1289 template<
typename ChildT>
1297 template<
typename ChildT>
1302 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1309 template<
typename ChildT>
1313 std::set<Coord> keysToErase;
1314 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1317 for (std::set<Coord>::iterator i = keysToErase.begin(), e = keysToErase.end(); i != e; ++i) {
1320 return keysToErase.size();
1327 template<
typename ChildT>
1331 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1332 keys.insert(i->first);
1337 template<
typename ChildT>
1338 inline typename RootNode<ChildT>::MapIter
1342 std::pair<MapIter, bool> result = mTable.try_emplace(key,
1343 Tile(mBackground,
false));
1344 return result.first;
1348 template<
typename ChildT>
1353 std::pair<MapIter, bool> result = mTable.try_emplace(key,
1354 Tile(mBackground,
false));
1355 return result.second;
1362 template<
typename ChildT>
1367 ChildT::getNodeLog2Dims(dims);
1371 template<
typename ChildT>
1375 return mTable.empty() ? Coord(0) : mTable.begin()->first;
1378 template<
typename ChildT>
1382 return mTable.empty() ? Coord(0) : mTable.rbegin()->first + Coord(ChildT::DIM - 1);
1386 template<
typename ChildT>
1398 template<
typename ChildT>
1399 template<
typename OtherChildType>
1404 using OtherMapT =
typename OtherRootT::MapType;
1405 using OtherIterT =
typename OtherRootT::MapIter;
1406 using OtherCIterT =
typename OtherRootT::MapCIter;
1411 OtherMapT copyOfOtherTable = other.mTable;
1414 for (MapCIter thisIter = mTable.begin(); thisIter != mTable.end(); ++thisIter) {
1418 OtherCIterT otherIter = other.findKey(thisIter->first);
1419 if (otherIter == other.mTable.end())
return false;
1422 if (isChild(thisIter)) {
1423 if (OtherRootT::isTile(otherIter))
return false;
1425 if (!getChild(thisIter).hasSameTopology(&OtherRootT::getChild(otherIter)))
return false;
1427 if (OtherRootT::isChild(otherIter))
return false;
1428 if (getTile(thisIter).active != OtherRootT::getTile(otherIter).active)
return false;
1435 copyOfOtherTable.erase(otherIter->first);
1438 for (OtherIterT i = copyOfOtherTable.begin(), e = copyOfOtherTable.end(); i != e; ++i) {
1445 template<
typename ChildT>
1446 template<
typename OtherChildType>
1450 std::vector<Index> thisDims, otherDims;
1453 return (thisDims == otherDims);
1457 template<
typename ChildT>
1458 template<
typename OtherChildType>
1462 std::vector<Index> thisDims, otherDims;
1465 if (thisDims != otherDims) {
1466 std::ostringstream ostr;
1467 ostr <<
"grids have incompatible configurations (" << thisDims[0];
1468 for (
size_t i = 1, N = thisDims.size(); i < N; ++i) ostr <<
" x " << thisDims[i];
1469 ostr <<
" vs. " << otherDims[0];
1470 for (
size_t i = 1, N = otherDims.size(); i < N; ++i) ostr <<
" x " << otherDims[i];
1477 template<
typename ChildT>
1478 template<
typename OtherChildType>
1482 using OtherValueType =
typename OtherChildType::ValueType;
1487 template<
typename ChildT>
1488 template<
typename OtherChildType>
1492 using OtherValueType =
typename OtherChildType::ValueType;
1494 std::ostringstream ostr;
1495 ostr <<
"values of type " << typeNameAsString<OtherValueType>()
1496 <<
" cannot be converted to type " << typeNameAsString<ValueType>();
1505 template<
typename ChildT>
1510 for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
1511 if (
const ChildT *child = iter->second.child) {
1512 sum += child->memUsage();
1519 template<
typename ChildT>
1523 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1524 delete i->second.child;
1530 template<
typename ChildT>
1534 for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
1535 if (
const ChildT *child = iter->second.child) {
1536 child->evalActiveBoundingBox(bbox, visitVoxels);
1537 }
else if (isTileOn(iter)) {
1538 bbox.expand(iter->first, ChildT::DIM);
1544 template<
typename ChildT>
1549 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1550 if (isChild(i)) sum += getChild(i).leafCount();
1556 template<
typename ChildT>
1561 if (ChildT::LEVEL != 0) {
1562 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1563 if (isChild(i)) sum += getChild(i).nonLeafCount();
1570 template<
typename ChildT>
1575 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1576 if (isChild(i)) ++sum;
1582 template<
typename ChildT>
1587 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1588 if (isTile(i)) ++sum;
1594 template<
typename ChildT>
1599 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1600 if (isTileOn(i)) ++sum;
1606 template<
typename ChildT>
1611 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1612 if (isTileOff(i)) ++sum;
1618 template<
typename ChildT>
1623 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1625 sum += getChild(i).onVoxelCount();
1626 }
else if (isTileOn(i)) {
1627 sum += ChildT::NUM_VOXELS;
1634 template<
typename ChildT>
1639 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1641 sum += getChild(i).offVoxelCount();
1643 sum += ChildT::NUM_VOXELS;
1650 template<
typename ChildT>
1655 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1656 if (isChild(i)) sum += getChild(i).onLeafVoxelCount();
1662 template<
typename ChildT>
1667 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1668 if (isChild(i)) sum += getChild(i).offLeafVoxelCount();
1673 template<
typename ChildT>
1678 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1680 sum += getChild(i).onTileCount();
1681 }
else if (isTileOn(i)) {
1688 template<
typename ChildT>
1694 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1697 getChild(i).nodeCount(vec);
1701 vec[ChildNodeType::LEVEL] = sum;
1704 template<
typename ChildT>
1710 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1714 getChild(i).nodeCount(vec);
1719 vec[ChildNodeType::LEVEL] = sum;
1725 template<
typename ChildT>
1729 MapCIter iter = this->findCoord(xyz);
1730 if (iter == mTable.end() || isTileOff(iter))
return false;
1731 return isTileOn(iter) ?
true : getChild(iter).isValueOn(xyz);
1734 template<
typename ChildT>
1738 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1739 if (isChild(i) ? getChild(i).hasActiveTiles() : getTile(i).active)
return true;
1744 template<
typename ChildT>
1745 template<
typename AccessorT>
1749 MapCIter iter = this->findCoord(xyz);
1750 if (iter == mTable.end() || isTileOff(iter))
return false;
1751 if (isTileOn(iter))
return true;
1752 acc.insert(xyz, &getChild(iter));
1753 return getChild(iter).isValueOnAndCache(xyz, acc);
1757 template<
typename ChildT>
1758 inline const typename ChildT::ValueType&
1761 MapCIter iter = this->findCoord(xyz);
1762 return iter == mTable.end() ? mBackground
1763 : (isTile(iter) ? getTile(iter).value : getChild(iter).getValue(xyz));
1766 template<
typename ChildT>
1767 template<
typename AccessorT>
1768 inline const typename ChildT::ValueType&
1771 MapCIter iter = this->findCoord(xyz);
1772 if (iter == mTable.end())
return mBackground;
1773 if (isChild(iter)) {
1774 acc.insert(xyz, &getChild(iter));
1775 return getChild(iter).getValueAndCache(xyz, acc);
1777 return getTile(iter).value;
1781 template<
typename ChildT>
1785 MapCIter iter = this->findCoord(xyz);
1786 return iter == mTable.end() ? -1
1787 : (isTile(iter) ? 0 : int(LEVEL) - int(getChild(iter).getValueLevel(xyz)));
1790 template<
typename ChildT>
1791 template<
typename AccessorT>
1795 MapCIter iter = this->findCoord(xyz);
1796 if (iter == mTable.end())
return -1;
1797 if (isTile(iter))
return 0;
1798 acc.insert(xyz, &getChild(iter));
1799 return int(LEVEL) - int(getChild(iter).getValueLevelAndCache(xyz, acc));
1803 template<
typename ChildT>
1807 MapIter iter = this->findCoord(xyz);
1808 if (iter != mTable.end() && !isTileOff(iter)) {
1809 if (isTileOn(iter)) {
1810 setChild(iter, *
new ChildT(xyz, getTile(iter).value,
true));
1812 getChild(iter).setValueOff(xyz);
1817 template<
typename ChildT>
1821 ChildT* child =
nullptr;
1823 MapIter iter = this->findKey(key);
1824 if (iter == mTable.end()) {
1826 child =
new ChildT(xyz, mBackground);
1827 mTable.emplace(key, *child);
1831 }
else if (isChild(iter)) {
1832 child = &getChild(iter);
1833 }
else if (on != getTile(iter).active) {
1834 child =
new ChildT(xyz, getTile(iter).value, !on);
1835 setChild(iter, *child);
1837 if (child) child->setActiveState(xyz, on);
1840 template<
typename ChildT>
1841 template<
typename AccessorT>
1845 ChildT* child =
nullptr;
1847 MapIter iter = this->findKey(key);
1848 if (iter == mTable.end()) {
1850 child =
new ChildT(xyz, mBackground);
1851 mTable.emplace(key, *child);
1855 }
else if (isChild(iter)) {
1856 child = &getChild(iter);
1857 }
else if (on != getTile(iter).active) {
1858 child =
new ChildT(xyz, getTile(iter).value, !on);
1859 setChild(iter, *child);
1862 acc.insert(xyz, child);
1863 child->setActiveStateAndCache(xyz, on, acc);
1868 template<
typename ChildT>
1872 ChildT* child =
nullptr;
1874 MapIter iter = this->findKey(key);
1875 if (iter == mTable.end()) {
1877 child =
new ChildT(xyz, mBackground);
1878 mTable.emplace(key, *child);
1880 }
else if (isChild(iter)) {
1881 child = &getChild(iter);
1883 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1884 setChild(iter, *child);
1886 if (child) child->setValueOff(xyz, value);
1889 template<
typename ChildT>
1890 template<
typename AccessorT>
1894 ChildT* child =
nullptr;
1896 MapIter iter = this->findKey(key);
1897 if (iter == mTable.end()) {
1899 child =
new ChildT(xyz, mBackground);
1900 mTable.emplace(key, *child);
1902 }
else if (isChild(iter)) {
1903 child = &getChild(iter);
1905 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1906 setChild(iter, *child);
1909 acc.insert(xyz, child);
1910 child->setValueOffAndCache(xyz, value, acc);
1915 template<
typename ChildT>
1919 ChildT* child =
nullptr;
1921 MapIter iter = this->findKey(key);
1922 if (iter == mTable.end()) {
1923 child =
new ChildT(xyz, mBackground);
1924 mTable.emplace(key, *child);
1925 }
else if (isChild(iter)) {
1926 child = &getChild(iter);
1928 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1929 setChild(iter, *child);
1931 if (child) child->setValueOn(xyz, value);
1934 template<
typename ChildT>
1935 template<
typename AccessorT>
1939 ChildT* child =
nullptr;
1941 MapIter iter = this->findKey(key);
1942 if (iter == mTable.end()) {
1943 child =
new ChildT(xyz, mBackground);
1944 mTable.emplace(key, *child);
1945 }
else if (isChild(iter)) {
1946 child = &getChild(iter);
1948 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1949 setChild(iter, *child);
1952 acc.insert(xyz, child);
1953 child->setValueAndCache(xyz, value, acc);
1958 template<
typename ChildT>
1962 ChildT* child =
nullptr;
1964 MapIter iter = this->findKey(key);
1965 if (iter == mTable.end()) {
1966 child =
new ChildT(xyz, mBackground);
1967 mTable.emplace(key, *child);
1968 }
else if (isChild(iter)) {
1969 child = &getChild(iter);
1971 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1972 setChild(iter, *child);
1974 if (child) child->setValueOnly(xyz, value);
1977 template<
typename ChildT>
1978 template<
typename AccessorT>
1982 ChildT* child =
nullptr;
1984 MapIter iter = this->findKey(key);
1985 if (iter == mTable.end()) {
1986 child =
new ChildT(xyz, mBackground);
1987 mTable.emplace(key, *child);
1988 }
else if (isChild(iter)) {
1989 child = &getChild(iter);
1991 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1992 setChild(iter, *child);
1995 acc.insert(xyz, child);
1996 child->setValueOnlyAndCache(xyz, value, acc);
2001 template<
typename ChildT>
2002 template<
typename ModifyOp>
2006 ChildT* child =
nullptr;
2008 MapIter iter = this->findKey(key);
2009 if (iter == mTable.end()) {
2010 child =
new ChildT(xyz, mBackground);
2011 mTable.emplace(key, *child);
2012 }
else if (isChild(iter)) {
2013 child = &getChild(iter);
2017 bool createChild = isTileOff(iter);
2021 const ValueType& tileVal = getTile(iter).value;
2027 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2028 setChild(iter, *child);
2031 if (child) child->modifyValue(xyz, op);
2034 template<
typename ChildT>
2035 template<
typename ModifyOp,
typename AccessorT>
2039 ChildT* child =
nullptr;
2041 MapIter iter = this->findKey(key);
2042 if (iter == mTable.end()) {
2043 child =
new ChildT(xyz, mBackground);
2044 mTable.emplace(key, *child);
2045 }
else if (isChild(iter)) {
2046 child = &getChild(iter);
2050 bool createChild = isTileOff(iter);
2054 const ValueType& tileVal = getTile(iter).value;
2060 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2061 setChild(iter, *child);
2065 acc.insert(xyz, child);
2066 child->modifyValueAndCache(xyz, op, acc);
2071 template<
typename ChildT>
2072 template<
typename ModifyOp>
2076 ChildT* child =
nullptr;
2078 MapIter iter = this->findKey(key);
2079 if (iter == mTable.end()) {
2080 child =
new ChildT(xyz, mBackground);
2081 mTable.emplace(key, *child);
2082 }
else if (isChild(iter)) {
2083 child = &getChild(iter);
2085 const Tile& tile = getTile(iter);
2086 bool modifiedState = tile.active;
2088 op(modifiedVal, modifiedState);
2092 child =
new ChildT(xyz, tile.value, tile.active);
2093 setChild(iter, *child);
2096 if (child) child->modifyValueAndActiveState(xyz, op);
2099 template<
typename ChildT>
2100 template<
typename ModifyOp,
typename AccessorT>
2103 const Coord& xyz,
const ModifyOp& op, AccessorT& acc)
2105 ChildT* child =
nullptr;
2107 MapIter iter = this->findKey(key);
2108 if (iter == mTable.end()) {
2109 child =
new ChildT(xyz, mBackground);
2110 mTable.emplace(key, *child);
2111 }
else if (isChild(iter)) {
2112 child = &getChild(iter);
2114 const Tile& tile = getTile(iter);
2115 bool modifiedState = tile.active;
2117 op(modifiedVal, modifiedState);
2121 child =
new ChildT(xyz, tile.value, tile.active);
2122 setChild(iter, *child);
2126 acc.insert(xyz, child);
2127 child->modifyValueAndActiveStateAndCache(xyz, op, acc);
2132 template<
typename ChildT>
2136 MapCIter iter = this->findCoord(xyz);
2137 if (iter == mTable.end()) {
2138 value = mBackground;
2140 }
else if (isChild(iter)) {
2141 return getChild(iter).probeValue(xyz, value);
2143 value = getTile(iter).value;
2144 return isTileOn(iter);
2147 template<
typename ChildT>
2148 template<
typename AccessorT>
2152 MapCIter iter = this->findCoord(xyz);
2153 if (iter == mTable.end()) {
2154 value = mBackground;
2156 }
else if (isChild(iter)) {
2157 acc.insert(xyz, &getChild(iter));
2158 return getChild(iter).probeValueAndCache(xyz, value, acc);
2160 value = getTile(iter).value;
2161 return isTileOn(iter);
2168 template<
typename ChildT>
2172 if (bbox.empty())
return;
2177 for (
int x = bbox.min().x(); x <= bbox.max().x(); x = tileMax.x() + 1) {
2179 for (
int y = bbox.min().y(); y <= bbox.max().y(); y = tileMax.y() + 1) {
2181 for (
int z = bbox.min().z(); z <= bbox.max().z(); z = tileMax.z() + 1) {
2186 tileMax = tileMin.offsetBy(ChildT::DIM - 1);
2188 if (xyz != tileMin || Coord::lessThan(bbox.max(), tileMax)) {
2192 ChildT* child =
nullptr;
2193 MapIter iter = this->findKey(tileMin);
2194 if (iter == mTable.end()) {
2197 child =
new ChildT(xyz, mBackground);
2198 mTable.emplace(tileMin, *child);
2199 }
else if (isTile(iter)) {
2202 const Tile& tile = getTile(iter);
2203 child =
new ChildT(xyz, tile.value, tile.active);
2204 setChild(iter, *child);
2205 }
else if (isChild(iter)) {
2206 child = &getChild(iter);
2211 child->fill(CoordBBox(xyz, tmp), value, active);
2217 MapIter iter = this->findOrAddCoord(tileMin);
2218 setTile(iter, Tile(value, active));
2226 template<
typename ChildT>
2230 if (bbox.empty())
return;
2232 if (active && mTable.empty()) {
2242 Coord xyz, tileMin, tileMax;
2243 for (
int x = bbox.min().x(); x <= bbox.max().x(); x = tileMax.x() + 1) {
2245 for (
int y = bbox.min().y(); y <= bbox.max().y(); y = tileMax.y() + 1) {
2247 for (
int z = bbox.min().z(); z <= bbox.max().z(); z = tileMax.z() + 1) {
2252 tileMax = tileMin.offsetBy(ChildT::DIM - 1);
2256 const auto iter = findOrAddCoord(tileMin);
2261 const auto& tile = getTile(iter);
2262 auto* child =
new ChildT{tileMin, tile.value, tile.active};
2263 setChild(iter, *child);
2266 getChild(iter).denseFill(bbox, value, active);
2276 template<
typename ChildT>
2284 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2285 if (this->isTileOff(i))
continue;
2286 ChildT* child = i->second.child;
2287 if (child ==
nullptr) {
2290 child =
new ChildT{i->first, this->getTile(i).value,
true};
2291 i->second.child = child;
2293 child->voxelizeActiveTiles(threaded);
2301 template<
typename ChildT>
2302 template<
typename DenseT>
2306 using DenseValueType =
typename DenseT::ValueType;
2308 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
2309 const Coord&
min = dense.bbox().min();
2311 for (Coord xyz = bbox.min(); xyz[0] <= bbox.max()[0]; xyz[0] = nodeBBox.max()[0] + 1) {
2312 for (xyz[1] = bbox.min()[1]; xyz[1] <= bbox.max()[1]; xyz[1] = nodeBBox.max()[1] + 1) {
2313 for (xyz[2] = bbox.min()[2]; xyz[2] <= bbox.max()[2]; xyz[2] = nodeBBox.max()[2] + 1) {
2316 nodeBBox = CoordBBox::createCube(
coordToKey(xyz), ChildT::DIM);
2321 MapCIter iter = this->findKey(nodeBBox.min());
2322 if (iter != mTable.end() && isChild(iter)) {
2323 getChild(iter).copyToDense(sub, dense);
2325 const ValueType value = iter==mTable.end() ? mBackground : getTile(iter).value;
2326 sub.translate(-min);
2327 DenseValueType* a0 = dense.data() + zStride*sub.min()[2];
2328 for (
Int32 x=sub.min()[0], ex=sub.max()[0]+1; x<ex; ++x) {
2329 DenseValueType* a1 = a0 + x*xStride;
2330 for (
Int32 y=sub.min()[1], ey=sub.max()[1]+1; y<ey; ++y) {
2331 DenseValueType* a2 = a1 + y*yStride;
2332 for (
Int32 z=sub.min()[2], ez=sub.max()[2]+1; z<ez; ++z, a2 += zStride) {
2333 *a2 = DenseValueType(value);
2346 template<
typename ChildT>
2351 os.write(reinterpret_cast<const char*>(&mBackground),
sizeof(
ValueType));
2354 os.write(reinterpret_cast<const char*>(&truncatedVal),
sizeof(
ValueType));
2359 os.write(reinterpret_cast<const char*>(&numTiles),
sizeof(
Index));
2360 os.write(reinterpret_cast<const char*>(&numChildren),
sizeof(
Index));
2362 if (numTiles == 0 && numChildren == 0)
return false;
2365 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2366 if (isChild(i))
continue;
2367 os.write(reinterpret_cast<const char*>(i->first.asPointer()), 3 *
sizeof(
Int32));
2368 os.write(reinterpret_cast<const char*>(&getTile(i).value),
sizeof(
ValueType));
2369 os.write(reinterpret_cast<const char*>(&getTile(i).active),
sizeof(
bool));
2372 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2373 if (isTile(i))
continue;
2374 os.write(reinterpret_cast<const char*>(i->first.asPointer()), 3 *
sizeof(
Int32));
2375 getChild(i).writeTopology(os, toHalf);
2382 template<
typename ChildT>
2394 is.read(reinterpret_cast<char*>(&mBackground),
sizeof(
ValueType));
2396 is.read(reinterpret_cast<char*>(&inside),
sizeof(
ValueType));
2401 Coord rangeMin, rangeMax;
2402 is.read(reinterpret_cast<char*>(rangeMin.asPointer()), 3 *
sizeof(
Int32));
2403 is.read(reinterpret_cast<char*>(rangeMax.asPointer()), 3 *
sizeof(
Int32));
2405 Index tableSize = 0, log2Dim[4] = { 0, 0, 0, 0 };
2407 for (
int i = 0; i < 3; ++i) {
2408 offset[i] = rangeMin[i] >> ChildT::TOTAL;
2409 rangeMin[i] = offset[i] << ChildT::TOTAL;
2411 tableSize += log2Dim[i];
2412 rangeMax[i] = (((1 << log2Dim[i]) + offset[i]) << ChildT::TOTAL) - 1;
2414 log2Dim[3] = log2Dim[1] + log2Dim[2];
2415 tableSize = 1U << tableSize;
2423 for (
Index i = 0; i < tableSize; ++i) {
2427 origin[0] = (n >> log2Dim[3]) + offset[0];
2428 n &= (1U << log2Dim[3]) - 1;
2429 origin[1] = (n >> log2Dim[2]) + offset[1];
2430 origin[2] = (n & ((1U << log2Dim[2]) - 1)) + offset[1];
2431 origin <<= ChildT::TOTAL;
2433 if (childMask.isOn(i)) {
2435 ChildT* child =
new ChildT(
PartialCreate(), origin, mBackground);
2436 child->readTopology(is);
2437 mTable.emplace(origin, *child);
2442 is.read(reinterpret_cast<char*>(&value),
sizeof(
ValueType));
2444 mTable.emplace(origin, Tile(value, valueMask.
isOn(i)));
2453 is.read(reinterpret_cast<char*>(&mBackground),
sizeof(
ValueType));
2456 Index numTiles = 0, numChildren = 0;
2457 is.read(reinterpret_cast<char*>(&numTiles),
sizeof(
Index));
2458 is.read(reinterpret_cast<char*>(&numChildren),
sizeof(
Index));
2460 if (numTiles == 0 && numChildren == 0)
return false;
2467 for (
Index n = 0; n < numTiles; ++n) {
2468 is.read(reinterpret_cast<char*>(vec), 3 *
sizeof(
Int32));
2469 is.read(reinterpret_cast<char*>(&value),
sizeof(
ValueType));
2470 is.read(reinterpret_cast<char*>(&active),
sizeof(
bool));
2471 mTable.emplace(Coord(vec), Tile(value, active));
2475 for (
Index n = 0; n < numChildren; ++n) {
2476 is.read(reinterpret_cast<char*>(vec), 3 *
sizeof(
Int32));
2478 ChildT* child =
new ChildT(
PartialCreate(), origin, mBackground);
2479 child->readTopology(is, fromHalf);
2480 mTable.emplace(Coord(vec), *child);
2487 template<
typename ChildT>
2491 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2492 if (isChild(i)) getChild(i).writeBuffers(os, toHalf);
2497 template<
typename ChildT>
2501 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2502 if (isChild(i)) getChild(i).readBuffers(is, fromHalf);
2507 template<
typename ChildT>
2511 const Tile bgTile(mBackground,
false);
2513 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2519 ChildT& child = getChild(i);
2520 child.readBuffers(is, clipBBox, fromHalf);
2524 this->
clip(clipBBox);
2531 template<
typename ChildT>
2535 const Tile bgTile(mBackground,
false);
2539 MapType copyOfTable(mTable);
2540 for (MapIter i = copyOfTable.begin(), e = copyOfTable.end(); i != e; ++i) {
2541 const Coord& xyz = i->first;
2542 CoordBBox tileBBox(xyz, xyz.offsetBy(ChildT::DIM - 1));
2543 if (!clipBBox.hasOverlap(tileBBox)) {
2545 setTile(this->findCoord(xyz), bgTile);
2547 }
else if (!clipBBox.isInside(tileBBox)) {
2551 getChild(i).clip(clipBBox, mBackground);
2555 tileBBox.intersect(clipBBox);
2556 const Tile& origTile = getTile(i);
2557 setTile(this->findCoord(xyz), bgTile);
2558 this->
sparseFill(tileBBox, origTile.value, origTile.active);
2571 template<
typename ChildT>
2577 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2578 if (this->isTile(i))
continue;
2579 this->getChild(i).prune(tolerance);
2580 if (this->getChild(i).isConstant(value, state, tolerance)) {
2581 this->setTile(i, Tile(value, state));
2591 template<
typename ChildT>
2592 template<
typename NodeT>
2596 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
2597 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2599 MapIter iter = this->findCoord(xyz);
2600 if (iter == mTable.end() || isTile(iter))
return nullptr;
2601 return (std::is_same<NodeT, ChildT>::value)
2602 ?
reinterpret_cast<NodeT*
>(&stealChild(iter, Tile(value, state)))
2603 : getChild(iter).template stealNode<NodeT>(xyz, value, state);
2611 template<
typename ChildT>
2615 if (leaf ==
nullptr)
return;
2616 ChildT* child =
nullptr;
2617 const Coord& xyz = leaf->origin();
2619 MapIter iter = this->findKey(key);
2620 if (iter == mTable.end()) {
2621 if (ChildT::LEVEL>0) {
2622 child =
new ChildT(xyz, mBackground,
false);
2624 child =
reinterpret_cast<ChildT*
>(leaf);
2626 mTable.emplace(key, *child);
2627 }
else if (isChild(iter)) {
2628 if (ChildT::LEVEL>0) {
2629 child = &getChild(iter);
2631 child =
reinterpret_cast<ChildT*
>(leaf);
2632 setChild(iter, *child);
2635 if (ChildT::LEVEL>0) {
2636 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2638 child =
reinterpret_cast<ChildT*
>(leaf);
2640 setChild(iter, *child);
2642 child->addLeaf(leaf);
2646 template<
typename ChildT>
2647 template<
typename AccessorT>
2651 if (leaf ==
nullptr)
return;
2652 ChildT* child =
nullptr;
2653 const Coord& xyz = leaf->origin();
2655 MapIter iter = this->findKey(key);
2656 if (iter == mTable.end()) {
2657 if (ChildT::LEVEL>0) {
2658 child =
new ChildT(xyz, mBackground,
false);
2660 child =
reinterpret_cast<ChildT*
>(leaf);
2662 mTable.emplace(key, *child);
2663 }
else if (isChild(iter)) {
2664 if (ChildT::LEVEL>0) {
2665 child = &getChild(iter);
2667 child =
reinterpret_cast<ChildT*
>(leaf);
2668 setChild(iter, *child);
2671 if (ChildT::LEVEL>0) {
2672 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2674 child =
reinterpret_cast<ChildT*
>(leaf);
2676 setChild(iter, *child);
2678 acc.insert(xyz, child);
2679 child->addLeafAndCache(leaf, acc);
2682 template<
typename ChildT>
2686 if (!child)
return false;
2687 const Coord& xyz = child->origin();
2689 MapIter iter = this->findKey(key);
2690 if (iter == mTable.end()) {
2691 mTable.emplace(key, *child);
2693 setChild(iter, *child);
2698 template<
typename ChildT>
2702 if (origin != Coord(0,0,0)) {
2708 template<
typename ChildT>
2713 MapIter iter = this->findKey(key);
2714 if (iter == mTable.end()) {
2715 mTable.emplace(key, Tile(value, state));
2717 setTile(iter, Tile(value, state));
2721 template<
typename ChildT>
2726 if (LEVEL >= level) {
2728 MapIter iter = this->findKey(key);
2729 if (iter == mTable.end()) {
2730 if (LEVEL > level) {
2731 ChildT* child =
new ChildT(xyz, mBackground,
false);
2732 mTable.emplace(key, *child);
2733 child->addTile(level, xyz, value, state);
2735 mTable.emplace(key, Tile(value, state));
2737 }
else if (isChild(iter)) {
2738 if (LEVEL > level) {
2739 getChild(iter).addTile(level, xyz, value, state);
2741 setTile(iter, Tile(value, state));
2744 if (LEVEL > level) {
2745 ChildT* child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2746 setChild(iter, *child);
2747 child->addTile(level, xyz, value, state);
2749 setTile(iter, Tile(value, state));
2756 template<
typename ChildT>
2757 template<
typename AccessorT>
2760 bool state, AccessorT& acc)
2762 if (LEVEL >= level) {
2764 MapIter iter = this->findKey(key);
2765 if (iter == mTable.end()) {
2766 if (LEVEL > level) {
2767 ChildT* child =
new ChildT(xyz, mBackground,
false);
2768 acc.insert(xyz, child);
2769 mTable.emplace(key, *child);
2770 child->addTileAndCache(level, xyz, value, state, acc);
2772 mTable.emplace(key, Tile(value, state));
2774 }
else if (isChild(iter)) {
2775 if (LEVEL > level) {
2776 ChildT* child = &getChild(iter);
2777 acc.insert(xyz, child);
2778 child->addTileAndCache(level, xyz, value, state, acc);
2780 setTile(iter, Tile(value, state));
2783 if (LEVEL > level) {
2784 ChildT* child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2785 acc.insert(xyz, child);
2786 setChild(iter, *child);
2787 child->addTileAndCache(level, xyz, value, state, acc);
2789 setTile(iter, Tile(value, state));
2796 template<
typename ChildT>
2801 MapIter iter = this->findKey(key);
2802 if (iter != mTable.end()) {
2804 if (isChild(iter))
delete iter->second.child;
2815 template<
typename ChildT>
2816 inline typename ChildT::LeafNodeType*
2819 ChildT* child =
nullptr;
2821 MapIter iter = this->findKey(key);
2822 if (iter == mTable.end()) {
2823 child =
new ChildT(xyz, mBackground,
false);
2824 mTable.emplace(key, *child);
2825 }
else if (isChild(iter)) {
2826 child = &getChild(iter);
2828 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2829 setChild(iter, *child);
2831 return child->touchLeaf(xyz);
2835 template<
typename ChildT>
2836 template<
typename AccessorT>
2837 inline typename ChildT::LeafNodeType*
2840 ChildT* child =
nullptr;
2842 MapIter iter = this->findKey(key);
2843 if (iter == mTable.end()) {
2844 child =
new ChildT(xyz, mBackground,
false);
2845 mTable.emplace(key, *child);
2846 }
else if (isChild(iter)) {
2847 child = &getChild(iter);
2849 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2850 setChild(iter, *child);
2852 acc.insert(xyz, child);
2853 return child->touchLeafAndCache(xyz, acc);
2860 template<
typename ChildT>
2861 template<
typename NodeT>
2865 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
2866 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2868 MapIter iter = this->findCoord(xyz);
2869 if (iter == mTable.end() || isTile(iter))
return nullptr;
2870 ChildT* child = &getChild(iter);
2871 return (std::is_same<NodeT, ChildT>::value)
2872 ?
reinterpret_cast<NodeT*
>(child)
2873 : child->template probeNode<NodeT>(xyz);
2878 template<
typename ChildT>
2879 template<
typename NodeT>
2883 return this->
template probeConstNode<NodeT>(xyz);
2887 template<
typename ChildT>
2888 template<
typename NodeT>
2892 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
2893 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2895 MapCIter iter = this->findCoord(xyz);
2896 if (iter == mTable.end() || isTile(iter))
return nullptr;
2897 const ChildT* child = &getChild(iter);
2898 return (std::is_same<NodeT, ChildT>::value)
2899 ?
reinterpret_cast<const NodeT*
>(child)
2900 : child->template probeConstNode<NodeT>(xyz);
2905 template<
typename ChildT>
2909 MapIter iter = this->findCoord(xyz);
2910 if (iter == mTable.end()) {
2913 }
else if (isChild(iter)) {
2914 child = &getChild(iter);
2917 const Tile& tile = getTile(iter);
2920 active = tile.active;
2925 template<
typename ChildT>
2929 MapCIter iter = this->findCoord(xyz);
2930 if (iter == mTable.end()) {
2933 }
else if (isChild(iter)) {
2934 child = &getChild(iter);
2937 const Tile& tile = getTile(iter);
2940 active = tile.active;
2945 template<
typename ChildT>
2949 return this->
template probeNode<ChildT>(xyz);
2953 template<
typename ChildT>
2954 inline const ChildT*
2957 return this->
template probeConstNode<ChildT>(xyz);
2961 template<
typename ChildT>
2962 inline typename ChildT::LeafNodeType*
2965 return this->
template probeNode<LeafNodeType>(xyz);
2969 template<
typename ChildT>
2970 inline const typename ChildT::LeafNodeType*
2973 return this->
template probeConstNode<LeafNodeType>(xyz);
2977 template<
typename ChildT>
2978 template<
typename AccessorT>
2979 inline typename ChildT::LeafNodeType*
2982 return this->
template probeNodeAndCache<LeafNodeType>(xyz, acc);
2986 template<
typename ChildT>
2987 template<
typename AccessorT>
2988 inline const typename ChildT::LeafNodeType*
2991 return this->
template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
2995 template<
typename ChildT>
2996 template<
typename AccessorT>
2997 inline const typename ChildT::LeafNodeType*
3004 template<
typename ChildT>
3005 template<
typename NodeT,
typename AccessorT>
3009 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
3010 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
3012 MapIter iter = this->findCoord(xyz);
3013 if (iter == mTable.end() || isTile(iter))
return nullptr;
3014 ChildT* child = &getChild(iter);
3015 acc.insert(xyz, child);
3016 return (std::is_same<NodeT, ChildT>::value)
3017 ?
reinterpret_cast<NodeT*
>(child)
3018 : child->template probeNodeAndCache<NodeT>(xyz, acc);
3023 template<
typename ChildT>
3024 template<
typename NodeT,
typename AccessorT>
3028 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
3029 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
3031 MapCIter iter = this->findCoord(xyz);
3032 if (iter == mTable.end() || isTile(iter))
return nullptr;
3033 const ChildT* child = &getChild(iter);
3034 acc.insert(xyz, child);
3035 return (std::is_same<NodeT, ChildT>::value)
3036 ?
reinterpret_cast<const NodeT*
>(child)
3037 : child->template probeConstNodeAndCache<NodeT>(xyz, acc);
3045 template<
typename ChildT>
3046 inline const typename ChildT::ValueType&
3049 MapCIter iter = this->findCoord(xyz);
3052 return getTile(iter).value;
3056 template<
typename ChildT>
3060 MapCIter iter = this->findCoord(xyz);
3063 const Tile& tile = getTile(iter);
3069 template<
typename ChildT>
3073 MapIter iter = this->findCoord(xyz);
3076 return &getChild(iter);
3080 template<
typename ChildT>
3081 inline const ChildT*
3084 MapCIter iter = this->findCoord(xyz);
3087 return &getChild(iter);
3091 template<
typename ChildT>
3092 inline const ChildT*
3102 template<
typename ChildT>
3103 template<
typename ArrayT>
3107 using NodePtr =
typename ArrayT::value_type;
3108 static_assert(std::is_pointer<NodePtr>::value,
3109 "argument to getNodes() must be a pointer array");
3110 using NodeType =
typename std::remove_pointer<NodePtr>::type;
3111 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
3112 static_assert(NodeChainType::template Contains<NonConstNodeType>,
3113 "can't extract non-const nodes from a const tree");
3114 using ArrayChildT =
typename std::conditional<
3115 std::is_const<NodeType>::value,
const ChildT, ChildT>::type;
3117 for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
3118 if (ChildT* child = iter->second.child) {
3120 if (std::is_same<NodePtr, ArrayChildT*>::value) {
3121 array.push_back(reinterpret_cast<NodePtr>(iter->second.child));
3123 child->getNodes(array);
3130 template<
typename ChildT>
3131 template<
typename ArrayT>
3135 using NodePtr =
typename ArrayT::value_type;
3136 static_assert(std::is_pointer<NodePtr>::value,
3137 "argument to getNodes() must be a pointer array");
3138 using NodeType =
typename std::remove_pointer<NodePtr>::type;
3139 static_assert(std::is_const<NodeType>::value,
3140 "argument to getNodes() must be an array of const node pointers");
3141 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
3142 static_assert(NodeChainType::template Contains<NonConstNodeType>,
3143 "can't extract non-const nodes from a const tree");
3145 for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
3148 if (std::is_same<NodePtr, const ChildT*>::value) {
3149 array.push_back(reinterpret_cast<NodePtr>(iter->second.child));
3151 child->getNodes(array);
3160 template<
typename ChildT>
3161 template<
typename ArrayT>
3165 using NodePtr =
typename ArrayT::value_type;
3166 static_assert(std::is_pointer<NodePtr>::value,
3167 "argument to stealNodes() must be a pointer array");
3168 using NodeType =
typename std::remove_pointer<NodePtr>::type;
3169 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
3170 static_assert(NodeChainType::template Contains<NonConstNodeType>,
3171 "can't extract non-const nodes from a const tree");
3172 using ArrayChildT =
typename std::conditional<
3173 std::is_const<NodeType>::value,
const ChildT, ChildT>::type;
3175 for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
3176 if (ChildT* child = iter->second.child) {
3178 if (std::is_same<NodePtr, ArrayChildT*>::value) {
3179 array.push_back(reinterpret_cast<NodePtr>(&stealChild(iter, Tile(value, state))));
3181 child->stealNodes(array, value, state);
3192 template<
typename ChildT>
3193 template<MergePolicy Policy>
3203 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3204 MapIter j = mTable.find(i->first);
3205 if (other.isChild(i)) {
3206 if (j == mTable.end()) {
3207 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3208 child.resetBackground(other.mBackground, mBackground);
3209 mTable.emplace(i->first, child);
3210 }
else if (isTile(j)) {
3212 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3213 child.resetBackground(other.mBackground, mBackground);
3217 getChild(j).template merge<MERGE_ACTIVE_STATES>(getChild(i),
3218 other.mBackground, mBackground);
3220 }
else if (other.isTileOn(i)) {
3221 if (j == mTable.end()) {
3222 mTable.emplace(i->first, i->second);
3223 }
else if (!isTileOn(j)) {
3225 setTile(j, Tile(other.getTile(i).value,
true));
3232 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3233 MapIter j = mTable.find(i->first);
3234 if (other.isChild(i)) {
3235 if (j == mTable.end()) {
3236 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3237 child.resetBackground(other.mBackground, mBackground);
3238 mTable.emplace(i->first, child);
3239 }
else if (isTile(j)) {
3240 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3241 child.resetBackground(other.mBackground, mBackground);
3244 getChild(j).template merge<MERGE_NODES>(
3245 getChild(i), other.mBackground, mBackground);
3252 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3253 MapIter j = mTable.find(i->first);
3254 if (other.isChild(i)) {
3255 if (j == mTable.end()) {
3257 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3258 child.resetBackground(other.mBackground, mBackground);
3259 mTable.emplace(i->first, child);
3260 }
else if (isTile(j)) {
3262 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3263 child.resetBackground(other.mBackground, mBackground);
3264 const Tile tile = getTile(j);
3268 child.template merge<MERGE_ACTIVE_STATES_AND_NODES>(
3269 tile.value, tile.active);
3273 getChild(j).template merge<MERGE_ACTIVE_STATES_AND_NODES>(getChild(i),
3274 other.mBackground, mBackground);
3276 }
else if (other.isTileOn(i)) {
3277 if (j == mTable.end()) {
3279 mTable.emplace(i->first, i->second);
3280 }
else if (isTileOff(j)) {
3282 setTile(j, Tile(other.getTile(i).value,
true));
3283 }
else if (isChild(j)) {
3285 const Tile& tile = getTile(i);
3286 getChild(j).template merge<MERGE_ACTIVE_STATES_AND_NODES>(
3287 tile.value, tile.active);
3304 template<
typename ChildT>
3305 template<
typename OtherChildType>
3310 using OtherCIterT =
typename OtherRootT::MapCIter;
3312 enforceSameConfiguration(other);
3314 for (OtherCIterT i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3315 MapIter j = mTable.find(i->first);
3316 if (other.isChild(i)) {
3317 if (j == mTable.end()) {
3318 mTable.emplace(i->first,
3319 *(
new ChildT(other.getChild(i), mBackground,
TopologyCopy())));
3320 }
else if (this->isChild(j)) {
3321 this->getChild(j).topologyUnion(other.getChild(i), preserveTiles);
3323 if (!preserveTiles || this->isTileOff(j)) {
3324 ChildT* child =
new ChildT(
3325 other.getChild(i), this->getTile(j).value,
TopologyCopy());
3326 if (this->isTileOn(j)) child->setValuesOn();
3327 this->setChild(j, *child);
3330 }
else if (other.isTileOn(i)) {
3331 if (j == mTable.end()) {
3332 mTable.emplace(i->first, Tile(mBackground,
true));
3333 }
else if (this->isChild(j)) {
3334 this->getChild(j).setValuesOn();
3335 }
else if (this->isTileOff(j)) {
3336 this->setTile(j, Tile(this->getTile(j).value,
true));
3342 template<
typename ChildT>
3343 template<
typename OtherChildType>
3348 using OtherCIterT =
typename OtherRootT::MapCIter;
3350 enforceSameConfiguration(other);
3352 std::set<Coord> tmp;
3353 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
3354 OtherCIterT j = other.mTable.find(i->first);
3355 if (this->isChild(i)) {
3356 if (j == other.mTable.end() || other.isTileOff(j)) {
3357 tmp.insert(i->first);
3358 }
else if (other.isChild(j)) {
3359 this->getChild(i).topologyIntersection(other.getChild(j), mBackground);
3361 }
else if (this->isTileOn(i)) {
3362 if (j == other.mTable.end() || other.isTileOff(j)) {
3363 this->setTile(i, Tile(this->getTile(i).value,
false));
3364 }
else if (other.isChild(j)) {
3366 new ChildT(other.getChild(j), this->getTile(i).value,
TopologyCopy());
3367 this->setChild(i, *child);
3371 for (std::set<Coord>::iterator i = tmp.begin(), e = tmp.end(); i != e; ++i) {
3372 MapIter it = this->findCoord(*i);
3373 setTile(it, Tile());
3378 template<
typename ChildT>
3379 template<
typename OtherChildType>
3384 using OtherCIterT =
typename OtherRootT::MapCIter;
3386 enforceSameConfiguration(other);
3388 for (OtherCIterT i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3389 MapIter j = mTable.find(i->first);
3390 if (other.isChild(i)) {
3391 if (j == mTable.end() || this->isTileOff(j)) {
3393 }
else if (this->isChild(j)) {
3394 this->getChild(j).topologyDifference(other.getChild(i), mBackground);
3395 }
else if (this->isTileOn(j)) {
3397 ChildT* child =
new ChildT(j->first, this->getTile(j).value,
true);
3398 child->topologyDifference(other.getChild(i), mBackground);
3399 this->setChild(j, *child);
3401 }
else if (other.isTileOn(i)) {
3402 if (j == mTable.end() || this->isTileOff(j)) {
3404 }
else if (this->isChild(j)) {
3407 }
else if (this->isTileOn(j)) {
3408 this->setTile(j, Tile(this->getTile(j).value,
false));
3417 template<
typename ChildT>
3418 template<
typename CombineOp>
3425 this->insertKeys(keys);
3426 other.insertKeys(keys);
3428 for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3429 MapIter iter = findOrAddCoord(*i), otherIter = other.findOrAddCoord(*i);
3430 if (isTile(iter) && isTile(otherIter)) {
3434 .setAIsActive(isTileOn(iter))
3435 .setBRef(getTile(otherIter).value)
3436 .setBIsActive(isTileOn(otherIter)));
3439 }
else if (isChild(iter) && isTile(otherIter)) {
3441 ChildT& child = getChild(iter);
3442 child.combine(getTile(otherIter).value, isTileOn(otherIter), op);
3444 }
else if (isTile(iter) && isChild(otherIter)) {
3449 ChildT& child = getChild(otherIter);
3450 child.combine(getTile(iter).value, isTileOn(iter), swappedOp);
3453 setChild(iter, stealChild(otherIter, Tile()));
3457 ChildT &child = getChild(iter), &otherChild = getChild(otherIter);
3458 child.combine(otherChild, op);
3460 if (prune && isChild(iter)) getChild(iter).prune();
3464 op(args.
setARef(mBackground).setBRef(other.mBackground));
3465 mBackground = args.
result();
3477 template<
typename CombineOp,
typename RootT,
typename OtherRootT,
bool Compatible = false>
3480 static inline void combine2(RootT&
self,
const RootT&,
const OtherRootT& other1,
3485 self.enforceSameConfiguration(other1);
3486 self.enforceCompatibleValueTypes(other1);
3488 std::ostringstream ostr;
3489 ostr <<
"cannot combine a " <<
typeid(OtherRootT).name()
3490 <<
" into a " <<
typeid(RootT).name();
3496 template<
typename CombineOp,
typename RootT,
typename OtherRootT>
3499 static inline void combine2(RootT&
self,
const RootT& other0,
const OtherRootT& other1,
3500 CombineOp& op,
bool prune)
3502 self.doCombine2(other0, other1, op, prune);
3507 template<
typename ChildT>
3508 template<
typename CombineOp,
typename OtherRootNode>
3511 CombineOp& op,
bool prune)
3513 using OtherValueType =
typename OtherRootNode::ValueType;
3517 *
this, other0, other1, op, prune);
3521 template<
typename ChildT>
3522 template<
typename CombineOp,
typename OtherRootNode>
3525 CombineOp& op,
bool prune)
3527 enforceSameConfiguration(other1);
3529 using OtherValueT =
typename OtherRootNode::ValueType;
3530 using OtherTileT =
typename OtherRootNode::Tile;
3531 using OtherNodeStructT =
typename OtherRootNode::NodeStruct;
3532 using OtherMapCIterT =
typename OtherRootNode::MapCIter;
3537 other0.insertKeys(keys);
3538 other1.insertKeys(keys);
3540 const NodeStruct bg0(Tile(other0.mBackground,
false));
3541 const OtherNodeStructT bg1(OtherTileT(other1.mBackground,
false));
3543 for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3544 MapIter thisIter = this->findOrAddCoord(*i);
3545 MapCIter iter0 = other0.findKey(*i);
3546 OtherMapCIterT iter1 = other1.findKey(*i);
3547 const NodeStruct& ns0 = (iter0 != other0.mTable.end()) ? iter0->second : bg0;
3548 const OtherNodeStructT& ns1 = (iter1 != other1.mTable.end()) ? iter1->second : bg1;
3549 if (ns0.isTile() && ns1.isTile()) {
3553 .setAIsActive(ns0.isTileOn())
3554 .setBRef(ns1.tile.value)
3555 .setBIsActive(ns1.isTileOn()));
3558 if (!isChild(thisIter)) {
3560 const Coord& childOrigin =
3561 ns0.isChild() ? ns0.child->origin() : ns1.child->origin();
3562 setChild(thisIter, *(
new ChildT(childOrigin, getTile(thisIter).value)));
3564 ChildT& child = getChild(thisIter);
3569 child.combine2(ns0.tile.value, *ns1.child, ns0.isTileOn(),
op);
3570 }
else if (ns1.isTile()) {
3573 child.combine2(*ns0.child, ns1.tile.value, ns1.isTileOn(),
op);
3577 child.combine2(*ns0.child, *ns1.child, op);
3580 if (prune && isChild(thisIter)) getChild(thisIter).prune();
3584 op(args.
setARef(other0.mBackground).setBRef(other1.mBackground));
3585 mBackground = args.
result();
3593 #endif // OPENVDB_TREE_ROOTNODE_HAS_BEEN_INCLUDED bool isValueOn(const Coord &xyz) const
Definition: RootNode.h:1727
const ValueType & getValue(const Coord &xyz) const
Definition: RootNode.h:1759
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:443
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
Definition: RootNode.h:3105
RootNode(const RootNode< OtherChildType > &other)
Construct a new tree that reproduces the topology and active states of a tree of a different ValueTyp...
Definition: RootNode.h:85
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
Definition: version.h.in:252
void denseFill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value and ensure that those voxels are a...
Definition: RootNode.h:2228
Index32 inactiveTileCount() const
Definition: RootNode.h:1608
static CoordBBox getNodeBoundingBox()
Return the bounding box of this RootNode, i.e., an infinite bounding box.
Definition: RootNode.h:408
ChildNodeType * getChildUnsafe(const Coord &xyz)
Return the child node at the given coordinate.
Definition: RootNode.h:3071
size_t eraseBackgroundTiles()
Remove all background tiles.
Definition: RootNode.h:1311
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:568
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
Definition: RootNode.h:2278
ValueAllCIter cbeginValueAll() const
Definition: RootNode.h:389
static void combine2(RootT &self, const RootT &, const OtherRootT &other1, CombineOp &, bool)
Definition: RootNode.h:3480
ChildOffCIter cbeginChildOff() const
Definition: RootNode.h:378
void copyToDense(const CoordBBox &bbox, DenseT &dense) const
Copy into a dense grid the values of all voxels, both active and inactive, that intersect a given bou...
Definition: RootNode.h:2304
bool probe(const Coord &xyz, ChildNodeType *&child, ValueType &value, bool &active)
Return a pointer to the root child node that contains voxel (x, y, z). If no such node exists...
Definition: RootNode.h:2907
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
ValueOnCIter cbeginValueOn() const
Definition: RootNode.h:387
Coord getMinIndex() const
Return the smallest index of the current tree.
Definition: RootNode.h:1373
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
const LeafNodeType * probeLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return nullptr.
Definition: RootNode.h:775
CanConvertType<FromType, ToType>::value is true if a value of type ToType can be constructed from a v...
Definition: Types.h:403
const ChildNodeType * probeConstChild(const Coord &xyz) const
Return a pointer to the root child node that contains voxel (x, y, z). If no such node exists...
Definition: RootNode.h:2955
ValueIter< const RootNode, MapCIter, ChildOffPred, ValueType > ChildOffCIter
Definition: RootNode.h:365
ValueOnCIter beginValueOn() const
Definition: RootNode.h:390
uint64_t Index64
Definition: Types.h:53
bool resultIsActive() const
Definition: Types.h:632
Index32 childCount() const
Definition: RootNode.h:1572
ValueIter< RootNode, MapIter, ValueOnPred, ValueType > ValueOnIter
Definition: RootNode.h:369
LeafNodeType * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return nullptr.
Definition: RootNode.h:2963
static const Index LEVEL
Definition: RootNode.h:47
void setBackground(const ValueType &value, bool updateChildNodes)
Change inactive tiles or voxels with a value equal to +/- the old background to the specified value (...
Definition: RootNode.h:1250
A list of types (not necessarily unique)
Definition: TypeList.h:577
static void combine2(RootT &self, const RootT &other0, const OtherRootT &other1, CombineOp &op, bool prune)
Definition: RootNode.h:3499
bool writeTopology(std::ostream &, bool toHalf=false) const
Definition: RootNode.h:2348
Index32 tileCount() const
Definition: RootNode.h:1584
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
Definition: RootNode.h:2004
ValueAllCIter beginValueAll() const
Definition: RootNode.h:392
Index getTableSize() const
Return the number of entries in this node's table.
Definition: RootNode.h:460
typename ChildType::ValueType ValueType
Definition: RootNode.h:44
Index getHeight() const
Definition: RootNode.h:463
Index64 onLeafVoxelCount() const
Definition: RootNode.h:1652
void addLeafAndCache(LeafNodeType *leaf, AccessorT &)
Same as addLeaf() but, if necessary, update the given accessor with pointers to the nodes along the p...
Definition: RootNode.h:2649
bool isApproxEqual(const Type &a, const Type &b, const Type &tolerance)
Return true if a is equal to b to within the given tolerance.
Definition: Math.h:406
void sparseFill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value.
Definition: RootNode.h:544
ChildOnCIter beginChildOn() const
Definition: RootNode.h:380
void modifyValueAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: RootNode.h:2037
Index32 FindHighestOn(Index32 v)
Return the most significant on bit of the given 32-bit value.
Definition: NodeMasks.h:159
int32_t Int32
Definition: Types.h:56
DenseIter< const RootNode, MapCIter, const ChildType, const ValueType > ChildAllCIter
Definition: RootNode.h:367
Index32 Index
Definition: Types.h:54
bool hasKey(const Coord &key) const
Return true if this node's mTable contains the given key.
Definition: RootNode.h:957
void writeBuffers(std::ostream &, bool toHalf=false) const
Definition: RootNode.h:2489
const ValueType & getTileValueUnsafe(const Coord &xyz) const
Return the tile value at the given coordinate.
Definition: RootNode.h:3047
ValueConverter<T>::Type is the type of a RootNode having the same child hierarchy as this node but a ...
Definition: RootNode.h:57
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: RootNode.h:2074
NodeT * probeNodeAndCache(const Coord &xyz, AccessorT &acc)
Same as probeNode() but, if necessary, update the given accessor with pointers to the nodes along the...
Definition: RootNode.h:3007
ChildOnCIter cbeginChildOn() const
Definition: RootNode.h:377
LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as probeLeaf() but, if necessary, update the given accessor with pointers to the nodes along the...
void combine2(const RootNode &other0, const OtherRootNode &other1, CombineOp &op, bool prune=false)
Definition: RootNode.h:3510
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates but don't change its active state.
Definition: RootNode.h:1960
Definition: RootNode.h:33
Mat3< typename promote< T0, T1 >::type > operator*(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Multiply m0 by m1 and return the resulting matrix.
Definition: Mat3.h:597
ChildIter< const RootNode, MapCIter, ChildOnPred, const ChildType > ChildOnCIter
Definition: RootNode.h:363
void stealNodes(ArrayT &array, const ValueType &value, bool state)
Steals all nodes of a certain type from the tree and adds them to a container with the following API:...
Definition: RootNode.h:3163
void evalActiveBoundingBox(CoordBBox &bbox, bool visitVoxels=true) const
Expand the specified bbox so it includes the active tiles of this root node as well as all the active...
Definition: RootNode.h:1532
Definition: Exceptions.h:65
static bool hasSameConfiguration(const RootNode< OtherChildType > &other)
Return false if the other node's dimensions don't match this node's.
Definition: RootNode.h:1448
static Index getChildDim()
Definition: RootNode.h:457
void setTransientData(Index32 transientData)
Set the transient data value.
Definition: RootNode.h:413
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:474
RootNode()
Construct a new tree with a background value of 0.
Definition: RootNode.h:1072
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:128
size_t numBackgroundTiles() const
Return the number of background tiles.
Definition: RootNode.h:1299
void topologyIntersection(const RootNode< OtherChildType > &other)
Intersects this tree's set of active values with the active values of the other tree, whose ValueType may be different.
Definition: RootNode.h:3345
ChildOffIter beginChildOff()
Definition: RootNode.h:384
LeafNodeType * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, create one that preserves the values and active states of all voxels.
Definition: RootNode.h:2817
void setValueOn(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: RootNode.h:1917
void readBuffers(std::istream &, bool fromHalf=false)
Definition: RootNode.h:2499
bool readTopology(std::istream &, bool fromHalf=false)
Definition: RootNode.h:2384
Index64 onVoxelCount() const
Definition: RootNode.h:1620
ChildOffCIter beginChildOff() const
Definition: RootNode.h:381
const AValueType & result() const
Get the output value.
Definition: Types.h:613
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition: Types.h:621
bool probe(const Coord &xyz, const ChildNodeType *&child, ValueType &value, bool &active) const
Return a pointer to the root child node that contains voxel (x, y, z). If no such node exists...
Definition: RootNode.h:750
const ChildNodeType * getConstChildUnsafe(const Coord &xyz) const
Return the child node at the given coordinate.
Definition: RootNode.h:3082
Definition: RootNode.h:34
bool isBackgroundTile(const Tile &) const
Return true if the given tile is inactive and has the background value.
Definition: RootNode.h:1277
Index64 offVoxelCount() const
Definition: RootNode.h:1636
void fill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value.
Definition: RootNode.h:2170
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return nullptr.
Definition: RootNode.h:2971
bool probeValue(const Coord &xyz, ValueType &value) const
Definition: RootNode.h:2134
const NodeT * probeConstNode(const Coord &xyz) const
Return a pointer to the node that contains voxel (x, y, z). If no such node exists, return nullptr.
Definition: RootNode.h:2890
T truncateRealToHalf(const T &val)
Return the given value truncated to 16-bit float precision.
Definition: Compression.h:217
static Index getLevel()
Definition: RootNode.h:455
bool addChild(ChildType *child)
Add the given child node at the root level. If a child node with the same origin already exists...
Definition: RootNode.h:2684
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: RootNode.h:1892
void setValueAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: RootNode.h:1937
const ChildNodeType * probeChild(const Coord &xyz) const
Return a pointer to the root child node that contains voxel (x, y, z). If no such node exists...
Definition: RootNode.h:767
bool isOn(Index32 i) const
Definition: NodeMasks.h:1331
int getValueDepthAndCache(const Coord &xyz, AccessorT &) const
Definition: RootNode.h:1793
void addLeaf(LeafNodeType *leaf)
Add the given leaf node to this tree, creating a new branch if necessary. If a leaf node with the sam...
Definition: RootNode.h:2613
void merge(RootNode &other)
Efficiently merge another tree into this tree using one of several schemes.
Definition: RootNode.h:3195
bool expand(const Coord &xyz)
Expand this node's table so that (x, y, z) is included in the index range.
Definition: RootNode.h:1350
Definition: Exceptions.h:13
ChildOnIter beginChildOn()
Definition: RootNode.h:383
ChildAllCIter cbeginChildAll() const
Definition: RootNode.h:379
int getValueDepth(const Coord &xyz) const
Return the tree depth (0 = root) at which the value of voxel (x, y, z) resides.
Definition: RootNode.h:1783
Index64 offLeafVoxelCount() const
Definition: RootNode.h:1664
bool deleteChildOrTile(const Coord &xyz)
Delete any child or tile containing voxel (x, y, z) at the root level. Do nothing if no child or tile...
Definition: RootNode.h:2798
RootNode & operator=(const RootNode &other)
Copy a root node of the same type as this node.
Definition: RootNode.h:1211
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition: Math.h:70
Index32 transientData() const
Return the transient data value.
Definition: RootNode.h:411
Index getDepth() const
Definition: RootNode.h:464
NodeT * probeNode(const Coord &xyz)
Return a pointer to the node that contains voxel (x, y, z). If no such node exists, return nullptr.
Definition: RootNode.h:2863
ValueIter< RootNode, MapIter, ChildOffPred, const ValueType > ChildOffIter
Definition: RootNode.h:364
NodeChain<RootNodeType, RootNodeType::LEVEL>::Type is a openvdb::TypeList that lists the types of the...
Definition: RootNode.h:32
void nodeCount(std::vector< Index64 > &vec) const
Definition: RootNode.h:1690
ValueOffCIter beginValueOff() const
Definition: RootNode.h:391
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: RootNode.h:2102
typename ChildType::BuildType BuildType
Definition: RootNode.h:45
Coord coordToKey(const Coord &xyz) const
Return a MapType key for the given coordinates, offset by the mOrigin.
Definition: RootNode.h:954
Index32 activeTileCount() const
Definition: RootNode.h:1596
void stealNodes(ArrayT &array)
Steals all nodes of a certain type from the tree and adds them to a container with the following API:...
Definition: RootNode.h:877
ValueIter< RootNode, MapIter, ValueAllPred, ValueType > ValueAllIter
Definition: RootNode.h:373
void setValueOnlyAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: RootNode.h:1980
ValueIter< const RootNode, MapCIter, ValueAllPred, const ValueType > ValueAllCIter
Definition: RootNode.h:374
Definition: RootNode.h:39
static void copyWithValueConversion(RootT &self, const OtherRootT &other)
Definition: RootNode.h:1152
NodeT * stealNode(const Coord &xyz, const ValueType &value, bool state)
Return a pointer to the node of type NodeT that contains voxel (x, y, z) and replace it with a tile o...
Definition: RootNode.h:2594
void prune(const ValueType &tolerance=zeroVal< ValueType >())
Reduce the memory footprint of this tree by replacing with tiles any nodes whose values are all the s...
Definition: RootNode.h:2573
const ValueType & background() const
Return this node's background value.
Definition: RootNode.h:430
RootNode(const RootNode &other)
Definition: RootNode.h:76
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Definition: RootNode.h:1843
ValueOffCIter cbeginValueOff() const
Definition: RootNode.h:388
uint32_t Index32
Definition: Types.h:52
Index64 onTileCount() const
Definition: RootNode.h:1675
bool empty() const
Return true if this node's table is either empty or contains only background tiles.
Definition: RootNode.h:448
ChildType ChildNodeType
Definition: RootNode.h:42
typename SubtreeT::template Append< HeadT > Type
Definition: RootNode.h:1039
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition: RootNode.h:1805
Index64 nonLeafCount() const
Definition: RootNode.h:1558
bool probeConst(const Coord &xyz, const ChildNodeType *&child, ValueType &value, bool &active) const
Return a pointer to the root child node that contains voxel (x, y, z). If no such node exists...
Definition: RootNode.h:2927
Coord getMaxIndex() const
Return the largest index of the current tree.
Definition: RootNode.h:1380
static void copyWithValueConversion(RootT &self, const OtherRootT &other)
Definition: RootNode.h:1170
void clear()
Definition: RootNode.h:1521
DenseIter< RootNode, MapIter, ChildType, ValueType > ChildAllIter
Definition: RootNode.h:366
LeafNodeType * touchLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as touchLeaf() but, if necessary, update the given accessor with pointers to the nodes along the...
ValueIter< const RootNode, MapCIter, ValueOffPred, const ValueType > ValueOffCIter
Definition: RootNode.h:372
Index64 memUsage() const
Return the total amount of memory in bytes occupied by this node and its children.
Definition: RootNode.h:1507
void topologyDifference(const RootNode< OtherChildType > &other)
Difference this tree's set of active values with the active values of the other tree, whose ValueType may be different. So a resulting voxel will be active only if the original voxel is active in this tree and inactive in the other tree.
Definition: RootNode.h:3381
ValueOnIter beginValueOn()
Definition: RootNode.h:393
bool hasActiveTiles() const
Return true if this root node, or any of its child nodes, have active tiles.
Definition: RootNode.h:1736
static void getNodeLog2Dims(std::vector< Index > &dims)
Definition: RootNode.h:1364
Definition: NodeMasks.h:1066
const LeafNodeType * probeConstLeafAndCache(const Coord &xyz, AccessorT &acc) const
Same as probeLeaf() but, if necessary, update the given accessor with pointers to the nodes along the...
Definition: Exceptions.h:64
ChildNodeType * probeChild(const Coord &xyz)
Return a pointer to the root child node that contains voxel (x, y, z). If no such node exists...
Definition: RootNode.h:2947
Index getWidth() const
Definition: RootNode.h:462
void load(std::istream &is)
Definition: NodeMasks.h:1372
typename NodeChain< RootNode, LEVEL >::Type NodeChainType
NodeChainType is a list of this tree's node types, from LeafNodeType to RootNode. ...
Definition: RootNode.h:50
void addTile(const Coord &xyz, const ValueType &value, bool state)
Add a tile containing voxel (x, y, z) at the root level, deleting the existing branch if necessary...
Definition: RootNode.h:2710
SameConfiguration<OtherNodeType>::value is true if and only if OtherNodeType is the type of a RootNod...
Definition: RootNode.h:65
Index64 leafCount() const
Definition: RootNode.h:1546
void setOrigin(const Coord &origin)
change the origin on this root node
Definition: RootNode.h:2700
const NodeT * probeConstNodeAndCache(const Coord &xyz, AccessorT &acc) const
Return a pointer to the root child node that contains voxel (x, y, z). If no such node exists...
Definition: RootNode.h:3026
OPENVDB_API uint32_t getFormatVersion(std::ios_base &)
Return the file format version number associated with the given input stream.
ValueAllIter beginValueAll()
Definition: RootNode.h:395
Vec2< T > minComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise minimum of the two vectors.
Definition: Vec2.h:504
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:683
void addTileAndCache(Index level, const Coord &xyz, const ValueType &, bool state, AccessorT &)
Same as addTile() but, if necessary, update the given accessor with pointers to the nodes along the p...
Definition: RootNode.h:2759
static bool hasCompatibleValueType(const RootNode< OtherChildType > &other)
Definition: RootNode.h:1480
ValueIter< RootNode, MapIter, ValueOffPred, ValueType > ValueOffIter
Definition: RootNode.h:371
void combine(RootNode &other, CombineOp &, bool prune=false)
Definition: RootNode.h:3420
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
bool hasSameTopology(const RootNode< OtherChildType > &other) const
Return true if the given tree has the same node and active value topology as this tree (but possibly ...
Definition: RootNode.h:1401
ChildAllIter beginChildAll()
Definition: RootNode.h:385
typename NodeChain< typename HeadT::ChildNodeType, HeadLevel-1 >::Type SubtreeT
Definition: RootNode.h:1038
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates but don't change its value.
Definition: RootNode.h:1819
ValueType combine(const ValueType &v0, const ValueType &v1, const ValueType &v2, const openvdb::Vec3d &w)
Combine different value types.
Definition: AttributeTransferUtil.h:141
void topologyUnion(const RootNode< OtherChildType > &other, const bool preserveTiles=false)
Union this tree's set of active values with the active values of the other tree, whose ValueType may ...
Definition: RootNode.h:3307
~RootNode()
Definition: RootNode.h:124
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Definition: RootNode.h:1747
OPENVDB_API void setGridBackgroundValuePtr(std::ios_base &, const void *background)
Specify (a pointer to) the background value of the grid currently being read from or written to the g...
ChildIter< RootNode, MapIter, ChildOnPred, ChildType > ChildOnIter
Definition: RootNode.h:362
void getIndexRange(CoordBBox &bbox) const
Return the current index range. Both min and max are inclusive.
Definition: RootNode.h:1388
bool operator!=(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Inequality operator, does exact floating point comparisons.
Definition: Vec3.h:482
void clip(const CoordBBox &)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition: RootNode.h:2533
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218
ValueOffIter beginValueOff()
Definition: RootNode.h:394
Tag dispatch class that distinguishes constructors during file input.
Definition: Types.h:689
ChildAllCIter beginChildAll() const
Definition: RootNode.h:382
typename ChildType::LeafNodeType LeafNodeType
Definition: RootNode.h:43
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition: RootNode.h:945
Definition: RootNode.h:35
ValueIter< const RootNode, MapCIter, ValueOnPred, const ValueType > ValueOnCIter
Definition: RootNode.h:370
bool probeValueAndCache(const Coord &xyz, ValueType &value, AccessorT &) const
Definition: RootNode.h:2150