8#ifndef OPENVDB_TREE_ROOTNODE_HAS_BEEN_INCLUDED
9#define OPENVDB_TREE_ROOTNODE_HAS_BEEN_INCLUDED
17#include <openvdb/version.h>
18#include <tbb/parallel_for.h>
31template<
typename HeadType,
int HeadLevel>
struct NodeChain;
32template<
typename,
typename>
struct SameRootConfig;
33template<
typename,
typename,
bool>
struct RootNodeCopyHelper;
34template<
typename,
typename,
typename,
bool>
struct RootNodeCombineHelper;
37template<
typename ChildType>
50 static_assert(NodeChainType::Size ==
LEVEL + 1,
51 "wrong number of entries in RootNode node chain");
55 template<
typename OtherValueType>
63 template<
typename OtherNodeType>
83 template<
typename OtherChildType>
94 template<
typename OtherChildType>
108 template<
typename OtherChildType>
120 template<
typename OtherChildType>
127 Tile(): value(
zeroVal<ValueType>()), active(false) {}
128 Tile(
const ValueType& v,
bool b): value(v), active(b) {}
138 NodeStruct(): child(nullptr) {}
139 NodeStruct(ChildType& c): child(&c) {}
140 NodeStruct(
const Tile& t): child(nullptr), tile(t) {}
141 NodeStruct(
const NodeStruct&) =
default;
142 NodeStruct(NodeStruct&&) noexcept = default;
143 NodeStruct& operator=(const NodeStruct&) = default;
146 bool isChild()
const {
return child !=
nullptr; }
147 bool isTile()
const {
return child ==
nullptr; }
148 bool isTileOff()
const {
return isTile() && !tile.active; }
149 bool isTileOn()
const {
return isTile() && tile.active; }
151 void set(ChildType& c) {
delete child; child = &c; }
152 void set(
const Tile& t) {
delete child; child =
nullptr; tile = t; }
153 ChildType& steal(
const Tile& t) { ChildType* c=child; child=
nullptr; tile=t;
return *c; }
156 using MapType = std::map<Coord, NodeStruct>;
157 using MapIter =
typename MapType::iterator;
158 using MapCIter =
typename MapType::const_iterator;
160 using CoordSet = std::set<Coord>;
161 using CoordSetIter =
typename CoordSet::iterator;
162 using CoordSetCIter =
typename CoordSet::const_iterator;
164 static void setTile(
const MapIter& i,
const Tile& t) { i->second.set(t); }
165 static void setChild(
const MapIter& i, ChildType& c) { i->second.set(c); }
166 static Tile& getTile(
const MapIter& i) {
return i->second.tile; }
167 static const Tile& getTile(
const MapCIter& i) {
return i->second.tile; }
168 static ChildType& getChild(
const MapIter& i) {
return *(i->second.child); }
169 static const ChildType& getChild(
const MapCIter& i) {
return *(i->second.child); }
170 static ChildType& stealChild(
const MapIter& i,
const Tile& t) {
return i->second.steal(t);}
171 static const ChildType& stealChild(
const MapCIter& i,
const Tile& t) {
return i->second.steal(t);}
173 static bool isChild(
const MapCIter& i) {
return i->second.isChild(); }
174 static bool isChild(
const MapIter& i) {
return i->second.isChild(); }
175 static bool isTile(
const MapCIter& i) {
return i->second.isTile(); }
176 static bool isTile(
const MapIter& i) {
return i->second.isTile(); }
177 static bool isTileOff(
const MapCIter& i) {
return i->second.isTileOff(); }
178 static bool isTileOff(
const MapIter& i) {
return i->second.isTileOff(); }
179 static bool isTileOn(
const MapCIter& i) {
return i->second.isTileOn(); }
180 static bool isTileOn(
const MapIter& i) {
return i->second.isTileOn(); }
183 static inline bool test(
const MapIter&) {
return true; }
184 static inline bool test(
const MapCIter&) {
return true; }
187 static inline bool test(
const MapIter& i) {
return isTileOn(i); }
188 static inline bool test(
const MapCIter& i) {
return isTileOn(i); }
190 struct ValueOffPred {
191 static inline bool test(
const MapIter& i) {
return isTileOff(i); }
192 static inline bool test(
const MapCIter& i) {
return isTileOff(i); }
194 struct ValueAllPred {
195 static inline bool test(
const MapIter& i) {
return isTile(i); }
196 static inline bool test(
const MapCIter& i) {
return isTile(i); }
199 static inline bool test(
const MapIter& i) {
return isChild(i); }
200 static inline bool test(
const MapCIter& i) {
return isChild(i); }
202 struct ChildOffPred {
203 static inline bool test(
const MapIter& i) {
return isTile(i); }
204 static inline bool test(
const MapCIter& i) {
return isTile(i); }
207 template<
typename _RootNodeT,
typename _MapIterT,
typename FilterPredT>
211 using RootNodeT = _RootNodeT;
212 using MapIterT = _MapIterT;
216 return (mParentNode == other.mParentNode) && (mIter == other.mIter);
218 bool operator!=(
const BaseIter& other)
const {
return !(*
this == other); }
220 RootNodeT* getParentNode()
const {
return mParentNode; }
222 RootNodeT& parent()
const
224 if (!mParentNode)
OPENVDB_THROW(ValueError,
"iterator references a null parent node");
228 bool test()
const {
OPENVDB_ASSERT(mParentNode);
return mIter != mParentNode->mTable.end(); }
229 operator bool()
const {
return this->test(); }
231 void increment() {
if (this->test()) { ++mIter; } this->skip(); }
232 bool next() { this->increment();
return this->test(); }
233 void increment(Index n) {
for (Index i = 0; i < n && this->next(); ++i) {} }
239 return !mParentNode ? 0U :
Index(std::distance(mParentNode->mTable.begin(), mIter));
242 bool isValueOn()
const {
return RootNodeT::isTileOn(mIter); }
243 bool isValueOff()
const {
return RootNodeT::isTileOff(mIter); }
244 void setValueOn(
bool on =
true)
const { mIter->second.tile.active = on; }
245 void setValueOff()
const { mIter->second.tile.active =
false; }
248 Coord getCoord()
const {
return mIter->first; }
250 void getCoord(Coord& xyz)
const { xyz = this->getCoord(); }
253 BaseIter(): mParentNode(nullptr) {}
254 BaseIter(RootNodeT& parent,
const MapIterT& iter): mParentNode(&parent), mIter(iter) {}
256 void skip() {
while (this->test() && !FilterPredT::test(mIter)) ++mIter; }
258 RootNodeT* mParentNode;
262 template<
typename RootNodeT,
typename MapIterT,
typename FilterPredT,
typename ChildNodeT>
263 class ChildIter:
public BaseIter<RootNodeT, MapIterT, FilterPredT>
266 using BaseT = BaseIter<RootNodeT, MapIterT, FilterPredT>;
267 using NodeType = RootNodeT;
268 using ValueType = NodeType;
269 using ChildNodeType = ChildNodeT;
270 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
271 using NonConstValueType =
typename std::remove_const<ValueType>::type;
272 using NonConstChildNodeType =
typename std::remove_const<ChildNodeType>::type;
276 ChildIter(RootNodeT& parent,
const MapIterT& iter): BaseT(parent, iter) { BaseT::skip(); }
278 ChildIter& operator++() { BaseT::increment();
return *
this; }
280 ChildNodeT& getValue()
const {
return getChild(mIter); }
281 ChildNodeT&
operator*()
const {
return this->getValue(); }
282 ChildNodeT* operator->()
const {
return &this->getValue(); }
285 template<
typename RootNodeT,
typename MapIterT,
typename FilterPredT,
typename ValueT>
286 class ValueIter:
public BaseIter<RootNodeT, MapIterT, FilterPredT>
289 using BaseT = BaseIter<RootNodeT, MapIterT, FilterPredT>;
290 using NodeType = RootNodeT;
291 using ValueType = ValueT;
292 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
293 using NonConstValueType =
typename std::remove_const<ValueT>::type;
297 ValueIter(RootNodeT& parent,
const MapIterT& iter): BaseT(parent, iter) { BaseT::skip(); }
299 ValueIter& operator++() { BaseT::increment();
return *
this; }
301 ValueT& getValue()
const {
return getTile(mIter).value; }
302 ValueT&
operator*()
const {
return this->getValue(); }
303 ValueT* operator->()
const {
return &(this->getValue()); }
305 void setValue(
const ValueT& v)
const {
OPENVDB_ASSERT(isTile(mIter)); getTile(mIter).value = v; }
307 template<
typename ModifyOp>
308 void modifyValue(
const ModifyOp& op)
const
311 op(getTile(mIter).value);
315 template<
typename RootNodeT,
typename MapIterT,
typename ChildNodeT,
typename ValueT>
316 class DenseIter:
public BaseIter<RootNodeT, MapIterT, NullPred>
319 using BaseT = BaseIter<RootNodeT, MapIterT, NullPred>;
320 using NodeType = RootNodeT;
321 using ValueType = ValueT;
322 using ChildNodeType = ChildNodeT;
323 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
324 using NonConstValueType =
typename std::remove_const<ValueT>::type;
325 using NonConstChildNodeType =
typename std::remove_const<ChildNodeT>::type;
329 DenseIter(RootNodeT& parent,
const MapIterT& iter): BaseT(parent, iter) {}
331 DenseIter& operator++() { BaseT::increment();
return *
this; }
333 bool isChildNode()
const {
return isChild(mIter); }
335 ChildNodeT* probeChild(NonConstValueType& value)
const
337 if (isChild(mIter))
return &getChild(mIter);
338 value = getTile(mIter).value;
341 bool probeChild(ChildNodeT*& child, NonConstValueType& value)
const
343 child = this->probeChild(value);
344 return child !=
nullptr;
346 bool probeValue(NonConstValueType& value)
const {
return !this->probeChild(value); }
348 void setChild(ChildNodeT& c)
const { RootNodeT::setChild(mIter, c); }
349 void setChild(ChildNodeT* c)
const {
OPENVDB_ASSERT(c !=
nullptr); RootNodeT::setChild(mIter, *c); }
350 void setValue(
const ValueT& v)
const
352 if (isTile(mIter)) getTile(mIter).value = v;
356 else stealChild(mIter, Tile(v,
true));
361 using ChildOnIter = ChildIter<RootNode, MapIter, ChildOnPred, ChildType>;
362 using ChildOnCIter = ChildIter<const RootNode, MapCIter, ChildOnPred, const ChildType>;
363 using ChildOffIter = ValueIter<RootNode, MapIter, ChildOffPred, const ValueType>;
364 using ChildOffCIter = ValueIter<const RootNode, MapCIter, ChildOffPred, ValueType>;
365 using ChildAllIter = DenseIter<RootNode, MapIter, ChildType, ValueType>;
366 using ChildAllCIter = DenseIter<const RootNode, MapCIter, const ChildType, const ValueType>;
368 using ValueOnIter = ValueIter<RootNode, MapIter, ValueOnPred, ValueType>;
369 using ValueOnCIter = ValueIter<const RootNode, MapCIter, ValueOnPred, const ValueType>;
370 using ValueOffIter = ValueIter<RootNode, MapIter, ValueOffPred, ValueType>;
371 using ValueOffCIter = ValueIter<const RootNode, MapCIter, ValueOffPred, const ValueType>;
372 using ValueAllIter = ValueIter<RootNode, MapIter, ValueAllPred, ValueType>;
373 using ValueAllCIter = ValueIter<const RootNode, MapCIter, ValueAllPred, const ValueType>;
474 template<
typename OtherChildType>
478 template<
typename OtherChildType>
483 template<
typename OtherChildType>
525 template<
typename ModifyOp>
528 template<
typename ModifyOp>
543 this->
fill(bbox, value, active);
571 template<
typename DenseT>
575#if OPENVDB_ABI_VERSION_NUMBER < 14
579 bool writeTopology(std::ostream&,
bool toHalf =
false)
const;
580 bool readTopology(std::istream&,
bool fromHalf =
false);
582 void writeBuffers(std::ostream&,
bool toHalf =
false)
const;
583 void readBuffers(std::istream&,
bool fromHalf =
false);
584 void readBuffers(std::istream&,
const CoordBBox&,
bool fromHalf =
false);
595 template<
typename AccessorT>
601 template<
typename AccessorT>
608 template<
typename AccessorT>
615 template<
typename AccessorT>
623 template<
typename ModifyOp,
typename AccessorT>
630 template<
typename ModifyOp,
typename AccessorT>
637 template<
typename AccessorT>
644 template<
typename AccessorT>
652 template<
typename AccessorT>
660 template<
typename AccessorT>
679 template<
typename AccessorT>
690 template<
typename NodeT>
711 template<
typename AccessorT>
729 template<
typename AccessorT>
735 template <
typename NodeT>
737 template <
typename NodeT>
739 template <
typename NodeT>
755 template<
typename NodeT,
typename AccessorT>
757 template<
typename NodeT,
typename AccessorT>
780 template<
typename AccessorT>
782 template<
typename AccessorT>
784 template<
typename AccessorT>
845 template<
typename ArrayT>
void getNodes(ArrayT& array);
846 template<
typename ArrayT>
void getNodes(ArrayT& array)
const;
873 template<
typename ArrayT>
875 template<
typename ArrayT>
904 template<
typename OtherChildType>
920 template<
typename OtherChildType>
933 template<
typename OtherChildType>
936 template<
typename CombineOp>
939 template<
typename CombineOp,
typename OtherRootNode >
941 CombineOp& op,
bool prune =
false);
956 bool hasKey(
const Coord& key)
const {
return mTable.find(key) != mTable.end(); }
967 void insertKeys(CoordSet&)
const;
972 MapIter findKey(
const Coord& key) {
return mTable.find(key); }
973 MapCIter findKey(
const Coord& key)
const {
return mTable.find(key); }
978 MapIter findCoord(
const Coord& xyz) {
return mTable.find(coordToKey(xyz)); }
979 MapCIter findCoord(
const Coord& xyz)
const {
return mTable.find(coordToKey(xyz)); }
984 MapIter findOrAddCoord(
const Coord& xyz);
990 template<
typename OtherChildType>
991 static void enforceSameConfiguration(
const RootNode<OtherChildType>& other);
998 template<
typename OtherChildType>
999 static void enforceCompatibleValueTypes(
const RootNode<OtherChildType>& other);
1001 template<
typename CombineOp,
typename OtherRootNode >
1002 void doCombine2(
const RootNode&,
const OtherRootNode&, CombineOp&,
bool prune);
1005 ValueType mBackground;
1008 Index32 mTransientData = 0;
1035template<
typename HeadT,
int HeadLevel>
1038 using Type =
typename SubtreeT::template Append<HeadT>;
1042template<
typename HeadT>
1054template<
typename ChildT1,
typename NodeT2>
1059template<
typename ChildT1,
typename ChildT2>
1061 static const bool value = ChildT1::template SameConfiguration<ChildT2>::value;
1069template<
typename ChildT>
1078template<
typename ChildT>
1087template<
typename ChildT>
1088template<
typename OtherChildType>
1092 : mBackground(backgd)
1093 , mOrigin(other.mOrigin)
1094 , mTransientData(other.mTransientData)
1098 if (mOrigin !=
Coord(0,0,0)) {
1102 enforceSameConfiguration(other);
1104 const Tile bgTile(backgd,
false), fgTile(foregd,
true);
1106 for (
typename OtherRootT::MapCIter i=other.mTable.begin(), e=other.mTable.end(); i != e; ++i) {
1107 mTable.emplace(i->first, OtherRootT::isTile(i)
1108 ? NodeStruct(OtherRootT::isTileOn(i) ? fgTile : bgTile)
1109 : NodeStruct(*(
new ChildT(OtherRootT::getChild(i), backgd, foregd,
TopologyCopy()))));
1114template<
typename ChildT>
1115template<
typename OtherChildType>
1119 : mBackground(backgd)
1120 , mOrigin(other.mOrigin)
1121 , mTransientData(other.mTransientData)
1125 if (mOrigin !=
Coord(0,0,0)) {
1129 enforceSameConfiguration(other);
1131 const Tile bgTile(backgd,
false), fgTile(backgd,
true);
1133 for (
typename OtherRootT::MapCIter i=other.mTable.begin(), e=other.mTable.end(); i != e; ++i) {
1134 mTable.emplace(i->first,
1135 OtherRootT::isTile(i)
1136 ? NodeStruct(OtherRootT::isTileOn(i) ? fgTile : bgTile)
1137 : NodeStruct(*(
new ChildT(OtherRootT::getChild(i), backgd,
TopologyCopy()))));
1148template<
typename RootT,
typename OtherRootT,
bool Compatible = false>
1155 self.enforceSameConfiguration(other);
1156 self.enforceCompatibleValueTypes(other);
1158 std::ostringstream ostr;
1159 ostr <<
"cannot convert a " <<
typeid(OtherRootT).name()
1160 <<
" to a " <<
typeid(RootT).name();
1166template<
typename RootT,
typename OtherRootT>
1171 using ValueT =
typename RootT::ValueType;
1172 using ChildT =
typename RootT::ChildNodeType;
1173 using Tile =
typename RootT::Tile;
1174 using OtherValueT =
typename OtherRootT::ValueType;
1175 using OtherMapCIter =
typename OtherRootT::MapCIter;
1176 using OtherTile =
typename OtherRootT::Tile;
1180 static inline ValueT convertValue(
const OtherValueT& val) {
1187 self.mBackground = Local::convertValue(other.mBackground);
1188 if (other.mOrigin !=
Coord(0,0,0)) {
1189 OPENVDB_THROW(
ValueError,
"RootNodeCopyHelper::copyWithValueConversion: non-zero offsets are currently not supported");
1191 self.mOrigin = other.mOrigin;
1192 self.mTransientData = other.mTransientData;
1196 for (OtherMapCIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
1197 if (other.isTile(i)) {
1199 const OtherTile& otherTile = other.getTile(i);
1200 self.mTable.emplace(i->first,
1201 Tile(Local::convertValue(otherTile.value), otherTile.active));
1204 self.mTable.emplace(i->first, *(
new ChildT(other.getChild(i))));
1212template<
typename ChildT>
1213inline RootNode<ChildT>&
1216 if (&other !=
this) {
1217 mBackground = other.mBackground;
1218 mOrigin = other.mOrigin;
1219 if (mOrigin !=
Coord(0,0,0)) {
1222 mTransientData = other.mTransientData;
1226 for (MapCIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
1227 mTable.emplace(i->first,
1228 isTile(i) ? NodeStruct(getTile(i)) : NodeStruct(*(
new ChildT(getChild(i)))));
1235template<
typename ChildT>
1236template<
typename OtherChildType>
1241 using OtherValueT =
typename OtherRootT::ValueType;
1251template<
typename ChildT>
1257 if (updateChildNodes) {
1260 for (MapIter
iter=mTable.begin();
iter!=mTable.end(); ++
iter) {
1261 ChildT *child =
iter->second.child;
1263 child->resetBackground(mBackground,
background);
1265 Tile& tile = getTile(
iter);
1266 if (tile.active)
continue;
1278template<
typename ChildT>
1285template<
typename ChildT>
1292template<
typename ChildT>
1300template<
typename ChildT>
1305 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1312template<
typename ChildT>
1316 std::set<Coord> keysToErase;
1317 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1320 for (std::set<Coord>::iterator i = keysToErase.begin(), e = keysToErase.end(); i != e; ++i) {
1323 return keysToErase.size();
1330template<
typename ChildT>
1332RootNode<ChildT>::insertKeys(CoordSet& keys)
const
1334 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1335 keys.insert(i->first);
1340template<
typename ChildT>
1341inline typename RootNode<ChildT>::MapIter
1342RootNode<ChildT>::findOrAddCoord(
const Coord& xyz)
1344 const Coord key = coordToKey(xyz);
1345 std::pair<MapIter, bool> result = mTable.try_emplace(key,
1346 Tile(mBackground,
false));
1347 return result.first;
1351template<
typename ChildT>
1356 std::pair<MapIter, bool> result = mTable.try_emplace(key,
1357 Tile(mBackground,
false));
1358 return result.second;
1365template<
typename ChildT>
1370 ChildT::getNodeLog2Dims(dims);
1374template<
typename ChildT>
1378 return mTable.empty() ?
Coord(0) : mTable.begin()->first;
1381template<
typename ChildT>
1385 return mTable.empty() ?
Coord(0) : mTable.rbegin()->first +
Coord(ChildT::DIM - 1);
1389template<
typename ChildT>
1401template<
typename ChildT>
1402template<
typename OtherChildType>
1407 using OtherMapT =
typename OtherRootT::MapType;
1408 using OtherIterT =
typename OtherRootT::MapIter;
1409 using OtherCIterT =
typename OtherRootT::MapCIter;
1414 OtherMapT copyOfOtherTable = other.mTable;
1417 for (MapCIter thisIter = mTable.begin(); thisIter != mTable.end(); ++thisIter) {
1421 OtherCIterT otherIter = other.findKey(thisIter->first);
1422 if (otherIter == other.mTable.end())
return false;
1425 if (isChild(thisIter)) {
1426 if (OtherRootT::isTile(otherIter))
return false;
1428 if (!getChild(thisIter).
hasSameTopology(&OtherRootT::getChild(otherIter)))
return false;
1430 if (OtherRootT::isChild(otherIter))
return false;
1431 if (getTile(thisIter).active != OtherRootT::getTile(otherIter).active)
return false;
1438 copyOfOtherTable.erase(otherIter->first);
1441 for (OtherIterT i = copyOfOtherTable.begin(), e = copyOfOtherTable.end(); i != e; ++i) {
1448template<
typename ChildT>
1449template<
typename OtherChildType>
1453 std::vector<Index> thisDims, otherDims;
1456 return (thisDims == otherDims);
1460template<
typename ChildT>
1461template<
typename OtherChildType>
1465 std::vector<Index> thisDims, otherDims;
1468 if (thisDims != otherDims) {
1469 std::ostringstream ostr;
1470 ostr <<
"grids have incompatible configurations (" << thisDims[0];
1471 for (
size_t i = 1, N = thisDims.size(); i < N; ++i) ostr <<
" x " << thisDims[i];
1472 ostr <<
" vs. " << otherDims[0];
1473 for (
size_t i = 1, N = otherDims.size(); i < N; ++i) ostr <<
" x " << otherDims[i];
1480template<
typename ChildT>
1481template<
typename OtherChildType>
1485 using OtherValueType =
typename OtherChildType::ValueType;
1490template<
typename ChildT>
1491template<
typename OtherChildType>
1495 using OtherValueType =
typename OtherChildType::ValueType;
1497 std::ostringstream ostr;
1508template<
typename ChildT>
1513 for (MapCIter
iter=mTable.begin();
iter!=mTable.end(); ++
iter) {
1514 if (
const ChildT *child =
iter->second.child) {
1515 sum += child->memUsage();
1522template<
typename ChildT>
1526 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1527 delete i->second.child;
1533template<
typename ChildT>
1537 for (MapCIter
iter=mTable.begin();
iter!=mTable.end(); ++
iter) {
1538 if (
const ChildT *child =
iter->second.child) {
1539 child->evalActiveBoundingBox(bbox, visitVoxels);
1540 }
else if (isTileOn(
iter)) {
1547template<
typename ChildT>
1552 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1553 if (isChild(i)) sum += getChild(i).leafCount();
1559template<
typename ChildT>
1564 if (ChildT::LEVEL != 0) {
1565 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1566 if (isChild(i)) sum += getChild(i).nonLeafCount();
1573template<
typename ChildT>
1578 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1579 if (isChild(i)) ++sum;
1585template<
typename ChildT>
1590 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1591 if (isTile(i)) ++sum;
1597template<
typename ChildT>
1602 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1603 if (isTileOn(i)) ++sum;
1609template<
typename ChildT>
1614 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1615 if (isTileOff(i)) ++sum;
1621template<
typename ChildT>
1626 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1628 sum += getChild(i).onVoxelCount();
1629 }
else if (isTileOn(i)) {
1630 sum += ChildT::NUM_VOXELS;
1637template<
typename ChildT>
1642 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1644 sum += getChild(i).offVoxelCount();
1646 sum += ChildT::NUM_VOXELS;
1653template<
typename ChildT>
1658 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1659 if (isChild(i)) sum += getChild(i).onLeafVoxelCount();
1665template<
typename ChildT>
1670 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1671 if (isChild(i)) sum += getChild(i).offLeafVoxelCount();
1676template<
typename ChildT>
1681 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1683 sum += getChild(i).onTileCount();
1684 }
else if (isTileOn(i)) {
1691template<
typename ChildT>
1697 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1700 getChild(i).nodeCount(vec);
1704 vec[ChildNodeType::LEVEL] = sum;
1710template<
typename ChildT>
1714 MapCIter
iter = this->findCoord(xyz);
1715 if (
iter == mTable.end() || isTileOff(
iter))
return false;
1716 return isTileOn(
iter) ? true : getChild(
iter).isValueOn(xyz);
1719template<
typename ChildT>
1723 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1724 if (isChild(i) ? getChild(i).
hasActiveTiles() : getTile(i).active)
return true;
1729template<
typename ChildT>
1730template<
typename AccessorT>
1734 MapCIter
iter = this->findCoord(xyz);
1735 if (
iter == mTable.end() || isTileOff(
iter))
return false;
1736 if (isTileOn(
iter))
return true;
1737 acc.insert(xyz, &getChild(
iter));
1738 return getChild(
iter).isValueOnAndCache(xyz, acc);
1742template<
typename ChildT>
1743inline const typename ChildT::ValueType&
1746 MapCIter
iter = this->findCoord(xyz);
1747 return iter == mTable.end() ? mBackground
1748 : (isTile(
iter) ? getTile(
iter).value : getChild(
iter).getValue(xyz));
1751template<
typename ChildT>
1752template<
typename AccessorT>
1753inline const typename ChildT::ValueType&
1756 MapCIter
iter = this->findCoord(xyz);
1757 if (
iter == mTable.end())
return mBackground;
1758 if (isChild(
iter)) {
1759 acc.insert(xyz, &getChild(
iter));
1760 return getChild(
iter).getValueAndCache(xyz, acc);
1762 return getTile(
iter).value;
1766template<
typename ChildT>
1770 MapCIter
iter = this->findCoord(xyz);
1771 return iter == mTable.end() ? -1
1772 : (isTile(
iter) ? 0 : int(
LEVEL) - int(getChild(
iter).getValueLevel(xyz)));
1775template<
typename ChildT>
1776template<
typename AccessorT>
1780 MapCIter
iter = this->findCoord(xyz);
1781 if (
iter == mTable.end())
return -1;
1782 if (isTile(
iter))
return 0;
1783 acc.insert(xyz, &getChild(
iter));
1784 return int(
LEVEL) - int(getChild(
iter).getValueLevelAndCache(xyz, acc));
1788template<
typename ChildT>
1792 MapIter
iter = this->findCoord(xyz);
1793 if (
iter != mTable.end() && !isTileOff(
iter)) {
1794 if (isTileOn(
iter)) {
1795 setChild(
iter, *
new ChildT(xyz, getTile(
iter).value,
true));
1797 getChild(
iter).setValueOff(xyz);
1802template<
typename ChildT>
1806 ChildT* child =
nullptr;
1808 MapIter
iter = this->findKey(key);
1809 if (
iter == mTable.end()) {
1811 child =
new ChildT(xyz, mBackground);
1812 mTable.emplace(key, *child);
1816 }
else if (isChild(
iter)) {
1817 child = &getChild(
iter);
1818 }
else if (on != getTile(
iter).active) {
1819 child =
new ChildT(xyz, getTile(
iter).value, !on);
1820 setChild(
iter, *child);
1822 if (child) child->setActiveState(xyz, on);
1825template<
typename ChildT>
1826template<
typename AccessorT>
1830 ChildT* child =
nullptr;
1832 MapIter
iter = this->findKey(key);
1833 if (
iter == mTable.end()) {
1835 child =
new ChildT(xyz, mBackground);
1836 mTable.emplace(key, *child);
1840 }
else if (isChild(
iter)) {
1841 child = &getChild(
iter);
1842 }
else if (on != getTile(
iter).active) {
1843 child =
new ChildT(xyz, getTile(
iter).value, !on);
1844 setChild(
iter, *child);
1847 acc.insert(xyz, child);
1848 child->setActiveStateAndCache(xyz, on, acc);
1853template<
typename ChildT>
1857 ChildT* child =
nullptr;
1859 MapIter
iter = this->findKey(key);
1860 if (
iter == mTable.end()) {
1862 child =
new ChildT(xyz, mBackground);
1863 mTable.emplace(key, *child);
1865 }
else if (isChild(
iter)) {
1866 child = &getChild(
iter);
1868 child =
new ChildT(xyz, getTile(
iter).value, isTileOn(
iter));
1869 setChild(
iter, *child);
1871 if (child) child->setValueOff(xyz, value);
1874template<
typename ChildT>
1875template<
typename AccessorT>
1879 ChildT* child =
nullptr;
1881 MapIter
iter = this->findKey(key);
1882 if (
iter == mTable.end()) {
1884 child =
new ChildT(xyz, mBackground);
1885 mTable.emplace(key, *child);
1887 }
else if (isChild(
iter)) {
1888 child = &getChild(
iter);
1890 child =
new ChildT(xyz, getTile(
iter).value, isTileOn(
iter));
1891 setChild(
iter, *child);
1894 acc.insert(xyz, child);
1895 child->setValueOffAndCache(xyz, value, acc);
1900template<
typename ChildT>
1904 ChildT* child =
nullptr;
1906 MapIter
iter = this->findKey(key);
1907 if (
iter == mTable.end()) {
1908 child =
new ChildT(xyz, mBackground);
1909 mTable.emplace(key, *child);
1910 }
else if (isChild(
iter)) {
1911 child = &getChild(
iter);
1913 child =
new ChildT(xyz, getTile(
iter).value, isTileOn(
iter));
1914 setChild(
iter, *child);
1916 if (child) child->setValueOn(xyz, value);
1919template<
typename ChildT>
1920template<
typename AccessorT>
1924 ChildT* child =
nullptr;
1926 MapIter
iter = this->findKey(key);
1927 if (
iter == mTable.end()) {
1928 child =
new ChildT(xyz, mBackground);
1929 mTable.emplace(key, *child);
1930 }
else if (isChild(
iter)) {
1931 child = &getChild(
iter);
1933 child =
new ChildT(xyz, getTile(
iter).value, isTileOn(
iter));
1934 setChild(
iter, *child);
1937 acc.insert(xyz, child);
1938 child->setValueAndCache(xyz, value, acc);
1943template<
typename ChildT>
1947 ChildT* child =
nullptr;
1949 MapIter
iter = this->findKey(key);
1950 if (
iter == mTable.end()) {
1951 child =
new ChildT(xyz, mBackground);
1952 mTable.emplace(key, *child);
1953 }
else if (isChild(
iter)) {
1954 child = &getChild(
iter);
1956 child =
new ChildT(xyz, getTile(
iter).value, isTileOn(
iter));
1957 setChild(
iter, *child);
1959 if (child) child->setValueOnly(xyz, value);
1962template<
typename ChildT>
1963template<
typename AccessorT>
1967 ChildT* child =
nullptr;
1969 MapIter
iter = this->findKey(key);
1970 if (
iter == mTable.end()) {
1971 child =
new ChildT(xyz, mBackground);
1972 mTable.emplace(key, *child);
1973 }
else if (isChild(
iter)) {
1974 child = &getChild(
iter);
1976 child =
new ChildT(xyz, getTile(
iter).value, isTileOn(
iter));
1977 setChild(
iter, *child);
1980 acc.insert(xyz, child);
1981 child->setValueOnlyAndCache(xyz, value, acc);
1986template<
typename ChildT>
1987template<
typename ModifyOp>
1991 ChildT* child =
nullptr;
1993 MapIter
iter = this->findKey(key);
1994 if (
iter == mTable.end()) {
1995 child =
new ChildT(xyz, mBackground);
1996 mTable.emplace(key, *child);
1997 }
else if (isChild(
iter)) {
1998 child = &getChild(
iter);
2002 bool createChild = isTileOff(
iter);
2012 child =
new ChildT(xyz, getTile(
iter).value, isTileOn(
iter));
2013 setChild(
iter, *child);
2016 if (child) child->modifyValue(xyz, op);
2019template<
typename ChildT>
2020template<
typename ModifyOp,
typename AccessorT>
2024 ChildT* child =
nullptr;
2026 MapIter
iter = this->findKey(key);
2027 if (
iter == mTable.end()) {
2028 child =
new ChildT(xyz, mBackground);
2029 mTable.emplace(key, *child);
2030 }
else if (isChild(
iter)) {
2031 child = &getChild(
iter);
2035 bool createChild = isTileOff(
iter);
2045 child =
new ChildT(xyz, getTile(
iter).value, isTileOn(
iter));
2046 setChild(
iter, *child);
2050 acc.insert(xyz, child);
2051 child->modifyValueAndCache(xyz, op, acc);
2056template<
typename ChildT>
2057template<
typename ModifyOp>
2061 ChildT* child =
nullptr;
2063 MapIter
iter = this->findKey(key);
2064 if (
iter == mTable.end()) {
2065 child =
new ChildT(xyz, mBackground);
2066 mTable.emplace(key, *child);
2067 }
else if (isChild(
iter)) {
2068 child = &getChild(
iter);
2070 const Tile& tile = getTile(
iter);
2071 bool modifiedState = tile.active;
2073 op(modifiedVal, modifiedState);
2077 child =
new ChildT(xyz, tile.value, tile.active);
2078 setChild(
iter, *child);
2081 if (child) child->modifyValueAndActiveState(xyz, op);
2084template<
typename ChildT>
2085template<
typename ModifyOp,
typename AccessorT>
2088 const Coord& xyz,
const ModifyOp& op, AccessorT& acc)
2090 ChildT* child =
nullptr;
2092 MapIter
iter = this->findKey(key);
2093 if (
iter == mTable.end()) {
2094 child =
new ChildT(xyz, mBackground);
2095 mTable.emplace(key, *child);
2096 }
else if (isChild(
iter)) {
2097 child = &getChild(
iter);
2099 const Tile& tile = getTile(
iter);
2100 bool modifiedState = tile.active;
2102 op(modifiedVal, modifiedState);
2106 child =
new ChildT(xyz, tile.value, tile.active);
2107 setChild(
iter, *child);
2111 acc.insert(xyz, child);
2112 child->modifyValueAndActiveStateAndCache(xyz, op, acc);
2117template<
typename ChildT>
2121 MapCIter
iter = this->findCoord(xyz);
2122 if (
iter == mTable.end()) {
2123 value = mBackground;
2125 }
else if (isChild(
iter)) {
2126 return getChild(
iter).probeValue(xyz, value);
2128 value = getTile(
iter).value;
2129 return isTileOn(
iter);
2132template<
typename ChildT>
2133template<
typename AccessorT>
2137 MapCIter
iter = this->findCoord(xyz);
2138 if (
iter == mTable.end()) {
2139 value = mBackground;
2141 }
else if (isChild(
iter)) {
2142 acc.insert(xyz, &getChild(
iter));
2143 return getChild(
iter).probeValueAndCache(xyz, value, acc);
2145 value = getTile(
iter).value;
2146 return isTileOn(
iter);
2153template<
typename ChildT>
2157 if (bbox.
empty())
return;
2162 for (
int x = bbox.
min().
x(); x <= bbox.
max().
x(); x = tileMax.
x() + 1) {
2164 for (
int y = bbox.
min().
y(); y <= bbox.
max().
y(); y = tileMax.
y() + 1) {
2166 for (
int z = bbox.
min().
z(); z <= bbox.
max().
z(); z = tileMax.
z() + 1) {
2171 tileMax = tileMin.
offsetBy(ChildT::DIM - 1);
2177 ChildT* child =
nullptr;
2178 MapIter
iter = this->findKey(tileMin);
2179 if (
iter == mTable.end()) {
2182 child =
new ChildT(xyz, mBackground);
2183 mTable.emplace(tileMin, *child);
2184 }
else if (isTile(
iter)) {
2187 const Tile& tile = getTile(
iter);
2188 child =
new ChildT(xyz, tile.value, tile.active);
2189 setChild(
iter, *child);
2190 }
else if (isChild(
iter)) {
2191 child = &getChild(
iter);
2196 child->fill(
CoordBBox(xyz, tmp), value, active);
2202 MapIter
iter = this->findOrAddCoord(tileMin);
2203 setTile(
iter, Tile(value, active));
2211template<
typename ChildT>
2215 if (bbox.
empty())
return;
2217 if (active && mTable.empty()) {
2227 Coord xyz, tileMin, tileMax;
2228 for (
int x = bbox.
min().
x(); x <= bbox.
max().
x(); x = tileMax.
x() + 1) {
2230 for (
int y = bbox.
min().
y(); y <= bbox.
max().
y(); y = tileMax.
y() + 1) {
2232 for (
int z = bbox.
min().
z(); z <= bbox.
max().
z(); z = tileMax.
z() + 1) {
2237 tileMax = tileMin.
offsetBy(ChildT::DIM - 1);
2241 const auto iter = findOrAddCoord(tileMin);
2246 const auto& tile = getTile(
iter);
2247 auto* child =
new ChildT{tileMin, tile.value, tile.active};
2248 setChild(
iter, *child);
2251 getChild(
iter).denseFill(bbox, value, active);
2261template<
typename ChildT>
2269 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2270 if (this->isTileOff(i))
continue;
2271 ChildT* child = i->second.child;
2272 if (child ==
nullptr) {
2275 child =
new ChildT{i->first, this->getTile(i).value,
true};
2276 i->second.child = child;
2278 child->voxelizeActiveTiles(threaded);
2286template<
typename ChildT>
2287template<
typename DenseT>
2291 using DenseValueType =
typename DenseT::ValueType;
2293 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
2294 const Coord& min = dense.bbox().min();
2296 for (
Coord xyz = bbox.
min(); xyz[0] <= bbox.
max()[0]; xyz[0] = nodeBBox.
max()[0] + 1) {
2297 for (xyz[1] = bbox.
min()[1]; xyz[1] <= bbox.
max()[1]; xyz[1] = nodeBBox.
max()[1] + 1) {
2298 for (xyz[2] = bbox.
min()[2]; xyz[2] <= bbox.
max()[2]; xyz[2] = nodeBBox.
max()[2] + 1) {
2306 MapCIter
iter = this->findKey(nodeBBox.
min());
2307 if (
iter != mTable.end() && isChild(
iter)) {
2308 getChild(
iter).copyToDense(sub, dense);
2312 DenseValueType* a0 = dense.data() + zStride*sub.
min()[2];
2313 for (
Int32 x=sub.
min()[0], ex=sub.
max()[0]+1; x<ex; ++x) {
2314 DenseValueType* a1 = a0 + x*xStride;
2315 for (
Int32 y=sub.
min()[1], ey=sub.
max()[1]+1; y<ey; ++y) {
2316 DenseValueType* a2 = a1 + y*yStride;
2317 for (
Int32 z=sub.
min()[2], ez=sub.
max()[2]+1; z<ez; ++z, a2 += zStride) {
2318 *a2 = DenseValueType(value);
2331#if OPENVDB_ABI_VERSION_NUMBER < 14
2333template<
typename ChildT>
2338 os.write(
reinterpret_cast<const char*
>(&mBackground),
sizeof(ValueType));
2341 os.write(
reinterpret_cast<const char*
>(&truncatedVal),
sizeof(ValueType));
2345 const Index numTiles = this->tileCount(), numChildren = this->childCount();
2346 os.write(
reinterpret_cast<const char*
>(&numTiles),
sizeof(
Index));
2347 os.write(
reinterpret_cast<const char*
>(&numChildren),
sizeof(
Index));
2349 if (numTiles == 0 && numChildren == 0)
return false;
2352 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2353 if (isChild(i))
continue;
2354 os.write(
reinterpret_cast<const char*
>(i->first.asPointer()), 3 *
sizeof(
Int32));
2355 os.write(
reinterpret_cast<const char*
>(&getTile(i).value),
sizeof(ValueType));
2356 os.write(
reinterpret_cast<const char*
>(&getTile(i).active),
sizeof(
bool));
2359 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2360 if (isTile(i))
continue;
2361 os.write(
reinterpret_cast<const char*
>(i->first.asPointer()), 3 *
sizeof(
Int32));
2362 getChild(i).writeTopology(os, toHalf);
2369template<
typename ChildT>
2380 is.read(
reinterpret_cast<char*
>(&mBackground),
sizeof(ValueType));
2383 Index numTiles = 0, numChildren = 0;
2384 is.read(
reinterpret_cast<char*
>(&numTiles),
sizeof(
Index));
2385 is.read(
reinterpret_cast<char*
>(&numChildren),
sizeof(
Index));
2387 if (numTiles == 0 && numChildren == 0)
return false;
2394 for (
Index n = 0; n < numTiles; ++n) {
2395 is.read(
reinterpret_cast<char*
>(vec), 3 *
sizeof(
Int32));
2396 is.read(
reinterpret_cast<char*
>(&value),
sizeof(ValueType));
2397 is.read(
reinterpret_cast<char*
>(&active),
sizeof(
bool));
2398 mTable.emplace(Coord(vec), Tile(value, active));
2402 for (
Index n = 0; n < numChildren; ++n) {
2403 is.read(
reinterpret_cast<char*
>(vec), 3 *
sizeof(
Int32));
2405 ChildT* child =
new ChildT(PartialCreate(), origin, mBackground);
2406 child->readTopology(is, fromHalf);
2407 mTable.emplace(Coord(vec), *child);
2414template<
typename ChildT>
2418 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2419 if (isChild(i)) getChild(i).writeBuffers(os, toHalf);
2424template<
typename ChildT>
2428 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2429 if (isChild(i)) getChild(i).readBuffers(is, fromHalf);
2434template<
typename ChildT>
2438 const Tile bgTile(mBackground,
false);
2440 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2446 ChildT& child = getChild(i);
2447 child.readBuffers(is, clipBBox, fromHalf);
2451 this->
clip(clipBBox);
2460template<
typename ChildT>
2464 const Tile bgTile(mBackground,
false);
2468 MapType copyOfTable(mTable);
2469 for (MapIter i = copyOfTable.begin(), e = copyOfTable.end(); i != e; ++i) {
2470 const Coord& xyz = i->first;
2474 setTile(this->findCoord(xyz), bgTile);
2476 }
else if (!clipBBox.
isInside(tileBBox)) {
2480 getChild(i).clip(clipBBox, mBackground);
2485 const Tile& origTile = getTile(i);
2486 setTile(this->findCoord(xyz), bgTile);
2487 this->
sparseFill(tileBBox, origTile.value, origTile.active);
2500template<
typename ChildT>
2506 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2507 if (this->isTile(i))
continue;
2508 this->getChild(i).prune(tolerance);
2509 if (this->getChild(i).isConstant(value, state, tolerance)) {
2510 this->setTile(i, Tile(value, state));
2520template<
typename ChildT>
2521template<
typename NodeT>
2525 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
2526 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2528 MapIter
iter = this->findCoord(xyz);
2529 if (
iter == mTable.end() || isTile(
iter))
return nullptr;
2530 return (std::is_same<NodeT, ChildT>::value)
2531 ?
reinterpret_cast<NodeT*
>(&stealChild(
iter, Tile(value, state)))
2540template<
typename ChildT>
2544 if (leaf ==
nullptr)
return;
2545 ChildT* child =
nullptr;
2546 const Coord& xyz = leaf->origin();
2548 MapIter
iter = this->findKey(key);
2549 if (
iter == mTable.end()) {
2550 if (ChildT::LEVEL>0) {
2551 child =
new ChildT(xyz, mBackground,
false);
2553 child =
reinterpret_cast<ChildT*
>(leaf);
2555 mTable.emplace(key, *child);
2556 }
else if (isChild(
iter)) {
2557 if (ChildT::LEVEL>0) {
2558 child = &getChild(
iter);
2560 child =
reinterpret_cast<ChildT*
>(leaf);
2561 setChild(
iter, *child);
2564 if (ChildT::LEVEL>0) {
2565 child =
new ChildT(xyz, getTile(
iter).value, isTileOn(
iter));
2567 child =
reinterpret_cast<ChildT*
>(leaf);
2569 setChild(
iter, *child);
2571 child->addLeaf(leaf);
2575template<
typename ChildT>
2576template<
typename AccessorT>
2580 if (leaf ==
nullptr)
return;
2581 ChildT* child =
nullptr;
2582 const Coord& xyz = leaf->origin();
2584 MapIter
iter = this->findKey(key);
2585 if (
iter == mTable.end()) {
2586 if (ChildT::LEVEL>0) {
2587 child =
new ChildT(xyz, mBackground,
false);
2589 child =
reinterpret_cast<ChildT*
>(leaf);
2591 mTable.emplace(key, *child);
2592 }
else if (isChild(
iter)) {
2593 if (ChildT::LEVEL>0) {
2594 child = &getChild(
iter);
2596 child =
reinterpret_cast<ChildT*
>(leaf);
2597 setChild(
iter, *child);
2600 if (ChildT::LEVEL>0) {
2601 child =
new ChildT(xyz, getTile(
iter).value, isTileOn(
iter));
2603 child =
reinterpret_cast<ChildT*
>(leaf);
2605 setChild(
iter, *child);
2607 acc.insert(xyz, child);
2608 child->addLeafAndCache(leaf, acc);
2611template<
typename ChildT>
2615 if (!child)
return false;
2616 const Coord& xyz = child->origin();
2618 MapIter
iter = this->findKey(key);
2619 if (
iter == mTable.end()) {
2620 mTable.emplace(key, *child);
2622 setChild(
iter, *child);
2627template<
typename ChildT>
2637template<
typename ChildT>
2642 MapIter
iter = this->findKey(key);
2643 if (
iter == mTable.end()) {
2644 mTable.emplace(key, Tile(value, state));
2646 setTile(
iter, Tile(value, state));
2650template<
typename ChildT>
2655 if (
LEVEL >= level) {
2657 MapIter
iter = this->findKey(key);
2658 if (
iter == mTable.end()) {
2659 if (
LEVEL > level) {
2660 ChildT* child =
new ChildT(xyz, mBackground,
false);
2661 mTable.emplace(key, *child);
2662 child->addTile(level, xyz, value, state);
2664 mTable.emplace(key, Tile(value, state));
2666 }
else if (isChild(
iter)) {
2667 if (
LEVEL > level) {
2668 getChild(
iter).addTile(level, xyz, value, state);
2670 setTile(
iter, Tile(value, state));
2673 if (
LEVEL > level) {
2674 ChildT* child =
new ChildT(xyz, getTile(
iter).value, isTileOn(
iter));
2675 setChild(
iter, *child);
2676 child->addTile(level, xyz, value, state);
2678 setTile(
iter, Tile(value, state));
2685template<
typename ChildT>
2686template<
typename AccessorT>
2689 bool state, AccessorT& acc)
2691 if (
LEVEL >= level) {
2693 MapIter
iter = this->findKey(key);
2694 if (
iter == mTable.end()) {
2695 if (
LEVEL > level) {
2696 ChildT* child =
new ChildT(xyz, mBackground,
false);
2697 acc.insert(xyz, child);
2698 mTable.emplace(key, *child);
2699 child->addTileAndCache(level, xyz, value, state, acc);
2701 mTable.emplace(key, Tile(value, state));
2703 }
else if (isChild(
iter)) {
2704 if (
LEVEL > level) {
2705 ChildT* child = &getChild(
iter);
2706 acc.insert(xyz, child);
2707 child->addTileAndCache(level, xyz, value, state, acc);
2709 setTile(
iter, Tile(value, state));
2712 if (
LEVEL > level) {
2713 ChildT* child =
new ChildT(xyz, getTile(
iter).value, isTileOn(
iter));
2714 acc.insert(xyz, child);
2715 setChild(
iter, *child);
2716 child->addTileAndCache(level, xyz, value, state, acc);
2718 setTile(
iter, Tile(value, state));
2725template<
typename ChildT>
2730 MapIter
iter = this->findKey(key);
2731 if (
iter != mTable.end()) {
2733 if (isChild(
iter))
delete iter->second.child;
2744template<
typename ChildT>
2745inline typename ChildT::LeafNodeType*
2748 ChildT* child =
nullptr;
2750 MapIter
iter = this->findKey(key);
2751 if (
iter == mTable.end()) {
2752 child =
new ChildT(xyz, mBackground,
false);
2753 mTable.emplace(key, *child);
2754 }
else if (isChild(
iter)) {
2755 child = &getChild(
iter);
2757 child =
new ChildT(xyz, getTile(
iter).value, isTileOn(
iter));
2758 setChild(
iter, *child);
2760 return child->touchLeaf(xyz);
2764template<
typename ChildT>
2765template<
typename AccessorT>
2766inline typename ChildT::LeafNodeType*
2769 ChildT* child =
nullptr;
2771 MapIter
iter = this->findKey(key);
2772 if (
iter == mTable.end()) {
2773 child =
new ChildT(xyz, mBackground,
false);
2774 mTable.emplace(key, *child);
2775 }
else if (isChild(
iter)) {
2776 child = &getChild(
iter);
2778 child =
new ChildT(xyz, getTile(
iter).value, isTileOn(
iter));
2779 setChild(
iter, *child);
2781 acc.insert(xyz, child);
2782 return child->touchLeafAndCache(xyz, acc);
2789template<
typename ChildT>
2790template<
typename NodeT>
2794 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
2795 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2797 MapIter
iter = this->findCoord(xyz);
2798 if (
iter == mTable.end() || isTile(
iter))
return nullptr;
2799 ChildT* child = &getChild(
iter);
2800 return (std::is_same<NodeT, ChildT>::value)
2801 ?
reinterpret_cast<NodeT*
>(child)
2807template<
typename ChildT>
2808template<
typename NodeT>
2816template<
typename ChildT>
2817template<
typename NodeT>
2821 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
2822 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2824 MapCIter
iter = this->findCoord(xyz);
2825 if (
iter == mTable.end() || isTile(
iter))
return nullptr;
2826 const ChildT* child = &getChild(
iter);
2827 return (std::is_same<NodeT, ChildT>::value)
2828 ?
reinterpret_cast<const NodeT*
>(child)
2834template<
typename ChildT>
2838 MapIter
iter = this->findCoord(xyz);
2839 if (
iter == mTable.end()) {
2842 }
else if (isChild(
iter)) {
2843 child = &getChild(
iter);
2846 const Tile& tile = getTile(
iter);
2849 active = tile.active;
2854template<
typename ChildT>
2858 MapCIter
iter = this->findCoord(xyz);
2859 if (
iter == mTable.end()) {
2862 }
else if (isChild(
iter)) {
2863 child = &getChild(
iter);
2866 const Tile& tile = getTile(
iter);
2869 active = tile.active;
2874template<
typename ChildT>
2882template<
typename ChildT>
2890template<
typename ChildT>
2891inline typename ChildT::LeafNodeType*
2898template<
typename ChildT>
2899inline const typename ChildT::LeafNodeType*
2906template<
typename ChildT>
2907template<
typename AccessorT>
2908inline typename ChildT::LeafNodeType*
2915template<
typename ChildT>
2916template<
typename AccessorT>
2917inline const typename ChildT::LeafNodeType*
2924template<
typename ChildT>
2925template<
typename AccessorT>
2926inline const typename ChildT::LeafNodeType*
2933template<
typename ChildT>
2934template<
typename NodeT,
typename AccessorT>
2938 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
2939 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2941 MapIter
iter = this->findCoord(xyz);
2942 if (
iter == mTable.end() || isTile(
iter))
return nullptr;
2943 ChildT* child = &getChild(
iter);
2944 acc.insert(xyz, child);
2945 return (std::is_same<NodeT, ChildT>::value)
2946 ?
reinterpret_cast<NodeT*
>(child)
2952template<
typename ChildT>
2953template<
typename NodeT,
typename AccessorT>
2957 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
2958 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2960 MapCIter
iter = this->findCoord(xyz);
2961 if (
iter == mTable.end() || isTile(
iter))
return nullptr;
2962 const ChildT* child = &getChild(
iter);
2963 acc.insert(xyz, child);
2964 return (std::is_same<NodeT, ChildT>::value)
2965 ?
reinterpret_cast<const NodeT*
>(child)
2974template<
typename ChildT>
2975inline const typename ChildT::ValueType&
2978 MapCIter
iter = this->findCoord(xyz);
2981 return getTile(
iter).value;
2985template<
typename ChildT>
2989 MapCIter
iter = this->findCoord(xyz);
2992 const Tile& tile = getTile(
iter);
2998template<
typename ChildT>
3002 MapIter
iter = this->findCoord(xyz);
3005 return &getChild(
iter);
3009template<
typename ChildT>
3013 MapCIter
iter = this->findCoord(xyz);
3016 return &getChild(
iter);
3020template<
typename ChildT>
3031template<
typename ChildT>
3032template<
typename ArrayT>
3036 using NodePtr =
typename ArrayT::value_type;
3037 static_assert(std::is_pointer<NodePtr>::value,
3038 "argument to getNodes() must be a pointer array");
3039 using NodeType =
typename std::remove_pointer<NodePtr>::type;
3040 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
3041 static_assert(NodeChainType::template Contains<NonConstNodeType>,
3042 "can't extract non-const nodes from a const tree");
3043 using ArrayChildT =
typename std::conditional<
3044 std::is_const<NodeType>::value,
const ChildT, ChildT>::type;
3046 for (MapIter
iter=mTable.begin();
iter!=mTable.end(); ++
iter) {
3047 if (ChildT* child =
iter->second.child) {
3049 if (std::is_same<NodePtr, ArrayChildT*>::value) {
3050 array.push_back(
reinterpret_cast<NodePtr
>(
iter->second.child));
3052 child->getNodes(array);
3059template<
typename ChildT>
3060template<
typename ArrayT>
3064 using NodePtr =
typename ArrayT::value_type;
3065 static_assert(std::is_pointer<NodePtr>::value,
3066 "argument to getNodes() must be a pointer array");
3067 using NodeType =
typename std::remove_pointer<NodePtr>::type;
3068 static_assert(std::is_const<NodeType>::value,
3069 "argument to getNodes() must be an array of const node pointers");
3070 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
3071 static_assert(NodeChainType::template Contains<NonConstNodeType>,
3072 "can't extract non-const nodes from a const tree");
3074 for (MapCIter
iter=mTable.begin();
iter!=mTable.end(); ++
iter) {
3077 if (std::is_same<NodePtr, const ChildT*>::value) {
3078 array.push_back(
reinterpret_cast<NodePtr
>(
iter->second.child));
3080 child->getNodes(array);
3089template<
typename ChildT>
3090template<
typename ArrayT>
3094 using NodePtr =
typename ArrayT::value_type;
3095 static_assert(std::is_pointer<NodePtr>::value,
3096 "argument to stealNodes() must be a pointer array");
3097 using NodeType =
typename std::remove_pointer<NodePtr>::type;
3098 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
3099 static_assert(NodeChainType::template Contains<NonConstNodeType>,
3100 "can't extract non-const nodes from a const tree");
3101 using ArrayChildT =
typename std::conditional<
3102 std::is_const<NodeType>::value,
const ChildT, ChildT>::type;
3104 for (MapIter
iter=mTable.begin();
iter!=mTable.end(); ++
iter) {
3105 if (ChildT* child =
iter->second.child) {
3107 if (std::is_same<NodePtr, ArrayChildT*>::value) {
3108 array.push_back(
reinterpret_cast<NodePtr
>(&stealChild(
iter, Tile(value, state))));
3110 child->stealNodes(array, value, state);
3121template<
typename ChildT>
3122template<MergePolicy Policy>
3132 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3133 MapIter j = mTable.find(i->first);
3134 if (other.isChild(i)) {
3135 if (j == mTable.end()) {
3136 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3137 child.resetBackground(other.mBackground, mBackground);
3138 mTable.emplace(i->first, child);
3139 }
else if (isTile(j)) {
3141 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3142 child.resetBackground(other.mBackground, mBackground);
3147 other.mBackground, mBackground);
3149 }
else if (other.isTileOn(i)) {
3150 if (j == mTable.end()) {
3151 mTable.emplace(i->first, i->second);
3152 }
else if (!isTileOn(j)) {
3154 setTile(j, Tile(other.getTile(i).value,
true));
3161 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3162 MapIter j = mTable.find(i->first);
3163 if (other.isChild(i)) {
3164 if (j == mTable.end()) {
3165 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3166 child.resetBackground(other.mBackground, mBackground);
3167 mTable.emplace(i->first, child);
3168 }
else if (isTile(j)) {
3169 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3170 child.resetBackground(other.mBackground, mBackground);
3174 getChild(i), other.mBackground, mBackground);
3181 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3182 MapIter j = mTable.find(i->first);
3183 if (other.isChild(i)) {
3184 if (j == mTable.end()) {
3186 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3187 child.resetBackground(other.mBackground, mBackground);
3188 mTable.emplace(i->first, child);
3189 }
else if (isTile(j)) {
3191 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3192 child.resetBackground(other.mBackground, mBackground);
3193 const Tile tile = getTile(j);
3198 tile.value, tile.active);
3203 other.mBackground, mBackground);
3205 }
else if (other.isTileOn(i)) {
3206 if (j == mTable.end()) {
3208 mTable.emplace(i->first, i->second);
3209 }
else if (isTileOff(j)) {
3211 setTile(j, Tile(other.getTile(i).value,
true));
3212 }
else if (isChild(j)) {
3214 const Tile& tile = getTile(i);
3216 tile.value, tile.active);
3233template<
typename ChildT>
3234template<
typename OtherChildType>
3239 using OtherCIterT =
typename OtherRootT::MapCIter;
3241 enforceSameConfiguration(other);
3243 for (OtherCIterT i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3244 MapIter j = mTable.find(i->first);
3245 if (other.isChild(i)) {
3246 if (j == mTable.end()) {
3247 mTable.emplace(i->first,
3248 *(
new ChildT(other.getChild(i), mBackground,
TopologyCopy())));
3249 }
else if (this->isChild(j)) {
3250 this->getChild(j).topologyUnion(other.getChild(i), preserveTiles);
3252 if (!preserveTiles || this->isTileOff(j)) {
3253 ChildT* child =
new ChildT(
3254 other.getChild(i), this->getTile(j).value,
TopologyCopy());
3255 if (this->isTileOn(j)) child->setValuesOn();
3256 this->setChild(j, *child);
3259 }
else if (other.isTileOn(i)) {
3260 if (j == mTable.end()) {
3261 mTable.emplace(i->first, Tile(mBackground,
true));
3262 }
else if (this->isChild(j)) {
3263 this->getChild(j).setValuesOn();
3264 }
else if (this->isTileOff(j)) {
3265 this->setTile(j, Tile(this->getTile(j).value,
true));
3271template<
typename ChildT>
3272template<
typename OtherChildType>
3277 using OtherCIterT =
typename OtherRootT::MapCIter;
3279 enforceSameConfiguration(other);
3281 std::set<Coord> tmp;
3282 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
3283 OtherCIterT j = other.mTable.find(i->first);
3284 if (this->isChild(i)) {
3285 if (j == other.mTable.end() || other.isTileOff(j)) {
3286 tmp.insert(i->first);
3287 }
else if (other.isChild(j)) {
3288 this->getChild(i).topologyIntersection(other.getChild(j), mBackground);
3290 }
else if (this->isTileOn(i)) {
3291 if (j == other.mTable.end() || other.isTileOff(j)) {
3292 this->setTile(i, Tile(this->getTile(i).value,
false));
3293 }
else if (other.isChild(j)) {
3295 new ChildT(other.getChild(j), this->getTile(i).value,
TopologyCopy());
3296 this->setChild(i, *child);
3300 for (std::set<Coord>::iterator i = tmp.begin(), e = tmp.end(); i != e; ++i) {
3301 MapIter it = this->findCoord(*i);
3302 setTile(it, Tile());
3307template<
typename ChildT>
3308template<
typename OtherChildType>
3313 using OtherCIterT =
typename OtherRootT::MapCIter;
3315 enforceSameConfiguration(other);
3317 for (OtherCIterT i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3318 MapIter j = mTable.find(i->first);
3319 if (other.isChild(i)) {
3320 if (j == mTable.end() || this->isTileOff(j)) {
3322 }
else if (this->isChild(j)) {
3323 this->getChild(j).topologyDifference(other.getChild(i), mBackground);
3324 }
else if (this->isTileOn(j)) {
3326 ChildT* child =
new ChildT(j->first, this->getTile(j).value,
true);
3327 child->topologyDifference(other.getChild(i), mBackground);
3328 this->setChild(j, *child);
3330 }
else if (other.isTileOn(i)) {
3331 if (j == mTable.end() || this->isTileOff(j)) {
3333 }
else if (this->isChild(j)) {
3336 }
else if (this->isTileOn(j)) {
3337 this->setTile(j, Tile(this->getTile(j).value,
false));
3346template<
typename ChildT>
3347template<
typename CombineOp>
3354 this->insertKeys(keys);
3355 other.insertKeys(keys);
3357 for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3358 MapIter
iter = findOrAddCoord(*i), otherIter = other.findOrAddCoord(*i);
3359 if (isTile(
iter) && isTile(otherIter)) {
3363 .setAIsActive(isTileOn(
iter))
3364 .setBRef(getTile(otherIter).value)
3365 .setBIsActive(isTileOn(otherIter)));
3368 }
else if (isChild(
iter) && isTile(otherIter)) {
3370 ChildT& child = getChild(
iter);
3371 child.combine(getTile(otherIter).value, isTileOn(otherIter), op);
3373 }
else if (isTile(
iter) && isChild(otherIter)) {
3378 ChildT& child = getChild(otherIter);
3379 child.combine(getTile(
iter).value, isTileOn(
iter), swappedOp);
3382 setChild(
iter, stealChild(otherIter, Tile()));
3386 ChildT &child = getChild(
iter), &otherChild = getChild(otherIter);
3387 child.combine(otherChild, op);
3394 mBackground = args.
result();
3406template<
typename CombineOp,
typename RootT,
typename OtherRootT,
bool Compatible = false>
3409 static inline void combine2(RootT& self,
const RootT&,
const OtherRootT& other1,
3414 self.enforceSameConfiguration(other1);
3415 self.enforceCompatibleValueTypes(other1);
3417 std::ostringstream ostr;
3418 ostr <<
"cannot combine a " <<
typeid(OtherRootT).name()
3419 <<
" into a " <<
typeid(RootT).name();
3425template<
typename CombineOp,
typename RootT,
typename OtherRootT>
3428 static inline void combine2(RootT& self,
const RootT& other0,
const OtherRootT& other1,
3429 CombineOp& op,
bool prune)
3431 self.doCombine2(other0, other1, op, prune);
3436template<
typename ChildT>
3437template<
typename CombineOp,
typename OtherRootNode>
3440 CombineOp& op,
bool prune)
3442 using OtherValueType =
typename OtherRootNode::ValueType;
3446 *
this, other0, other1, op,
prune);
3450template<
typename ChildT>
3451template<
typename CombineOp,
typename OtherRootNode>
3453RootNode<ChildT>::doCombine2(
const RootNode& other0,
const OtherRootNode& other1,
3454 CombineOp& op,
bool prune)
3456 enforceSameConfiguration(other1);
3458 using OtherValueT =
typename OtherRootNode::ValueType;
3459 using OtherTileT =
typename OtherRootNode::Tile;
3460 using OtherNodeStructT =
typename OtherRootNode::NodeStruct;
3461 using OtherMapCIterT =
typename OtherRootNode::MapCIter;
3466 other0.insertKeys(keys);
3467 other1.insertKeys(keys);
3469 const NodeStruct bg0(Tile(other0.mBackground,
false));
3470 const OtherNodeStructT bg1(OtherTileT(other1.mBackground,
false));
3472 for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3473 MapIter thisIter = this->findOrAddCoord(*i);
3474 MapCIter iter0 = other0.findKey(*i);
3475 OtherMapCIterT iter1 = other1.findKey(*i);
3476 const NodeStruct& ns0 = (iter0 != other0.mTable.end()) ? iter0->second : bg0;
3477 const OtherNodeStructT& ns1 = (iter1 != other1.mTable.end()) ? iter1->second : bg1;
3478 if (ns0.isTile() && ns1.isTile()) {
3481 op(args.
setARef(ns0.tile.value)
3487 if (!isChild(thisIter)) {
3489 const Coord& childOrigin =
3490 ns0.isChild() ? ns0.child->origin() : ns1.child->origin();
3491 setChild(thisIter, *(
new ChildT(childOrigin, getTile(thisIter).value)));
3493 ChildT& child = getChild(thisIter);
3498 child.combine2(ns0.tile.value, *ns1.child, ns0.isTileOn(), op);
3499 }
else if (ns1.isTile()) {
3502 child.combine2(*ns0.child, ns1.tile.value, ns1.isTileOn(), op);
3506 child.combine2(*ns0.child, *ns1.child, op);
3509 if (prune && isChild(thisIter)) getChild(thisIter).prune();
3513 op(args.
setARef(other0.mBackground).
setBRef(other1.mBackground));
3514 mBackground = args.
result();
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition Types.h:640
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition Types.h:692
const AValueType & result() const
Get the output value.
Definition Types.h:684
CombineArgs & setBIsActive(bool b)
Set the active state of the B value.
Definition Types.h:708
CombineArgs & setBRef(const BValueType &b)
Redirect the B value to a new external source.
Definition Types.h:694
bool resultIsActive() const
Definition Types.h:703
CombineArgs & setAIsActive(bool b)
Set the active state of the A value.
Definition Types.h:706
static CoordBBox inf()
Return an "infinite" bounding box, as defined by the Coord value range.
Definition Coord.h:322
static CoordBBox createCube(const Coord &min, ValueType dim)
Definition Coord.h:316
void minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition Coord.h:176
static bool lessThan(const Coord &a, const Coord &b)
Definition Coord.h:209
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition Types.h:754
Definition Exceptions.h:64
Definition Exceptions.h:65
Axis-aligned bounding box of signed integer coordinates.
Definition Coord.h:252
void translate(const Coord &t)
Translate this bounding box by (tx, ty, tz).
Definition Coord.h:461
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition Coord.h:421
bool empty() const
Return true if this bounding box is empty (i.e., encloses no coordinates).
Definition Coord.h:359
const Coord & min() const
Definition Coord.h:324
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition Coord.h:415
const Coord & max() const
Definition Coord.h:325
bool isInside(const Coord &xyz) const
Return true if point (x, y, z) is inside this bounding box.
Definition Coord.h:403
void intersect(const CoordBBox &bbox)
Intersect this bounding box with the given bounding box.
Definition Coord.h:447
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:26
Int32 y() const
Definition Coord.h:132
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition Coord.h:92
Int32 x() const
Definition Coord.h:131
Coord & setZ(Int32 z)
Definition Coord.h:82
Coord & setY(Int32 y)
Definition Coord.h:81
Int32 z() const
Definition Coord.h:133
Coord & setX(Int32 x)
Definition Coord.h:80
static CoordBBox getNodeBoundingBox()
Return the bounding box of this RootNode, i.e., an infinite bounding box.
Definition RootNode.h:407
void setValueAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition RootNode.h:1922
DenseIter< RootNode, MapIter, typename SubtreeT::Back, ValueType > ChildAllIter
Definition RootNode.h:365
static bool hasSameConfiguration(const RootNode< OtherChildType > &other)
Return false if the other node's dimensions don't match this node's.
Definition RootNode.h:1451
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:1768
ValueIter< const RootNode, MapCIter, ValueOffPred, const ValueType > ValueOffCIter
Definition RootNode.h:371
RootNode(const RootNode &other)
Definition RootNode.h:75
ChildOnCIter cbeginChildOn() const
Definition RootNode.h:376
ChildOnCIter beginChildOn() const
Definition RootNode.h:379
ChildOnIter beginChildOn()
Definition RootNode.h:382
Index getDepth() const
Definition RootNode.h:463
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:2836
RootNode(const RootNode< OtherChildType > &other, const ValueType &background, TopologyCopy)
Construct a new tree that reproduces the topology and active states of another tree (which may have a...
Definition RootNode.h:1117
bool isValueOn(const Coord &xyz) const
Definition RootNode.h:1712
ValueIter< const RootNode, MapCIter, ValueOnPred, const ValueType > ValueOnCIter
Definition RootNode.h:369
void getIndexRange(CoordBBox &bbox) const
Return the current index range. Both min and max are inclusive.
Definition RootNode.h:1391
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:2289
RootNode & operator=(const RootNode &other)
Copy a root node of the same type as this node.
Definition RootNode.h:1214
Coord getMaxIndex() const
ValueOffCIter cbeginValueOff() const
Definition RootNode.h:387
LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as probeLeaf() but, if necessary, update the given accessor with pointers to the nodes along the...
Index32 transientData() const
Return the transient data value.
Definition RootNode.h:410
bool isBackgroundTile(const MapCIter &) const
Definition RootNode.h:1294
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:2578
static Index getChildDim()
Definition RootNode.h:456
const ChildNodeType * getConstChildUnsafe(const Coord &xyz) const
Return the child node at the given coordinate.
Definition RootNode.h:3011
RootNode & operator=(const RootNode< OtherChildType > &other)
Copy a root node of the same tree configuration as this node but a different ValueType.
Coord coordToKey(const Coord &xyz) const
Return a MapType key for the given coordinates, offset by the mOrigin.
Definition RootNode.h:953
void combine(RootNode &other, CombineOp &, bool prune=false)
Definition RootNode.h:3349
bool getTileValueUnsafe(const Coord &xyz, ValueType &value) const
Return the tile value and active state at the given coordinate.
Definition RootNode.h:2987
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
Definition RootNode.h:3034
const ValueType & getTileValueUnsafe(const Coord &xyz) const
Return the tile value at the given coordinate.
Definition RootNode.h:2976
Index64 nonLeafCount() const
Definition RootNode.h:1561
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:2523
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
Definition RootNode.h:2263
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< RootNode, MapIter, ValueOffPred, ValueType > ValueOffIter
Definition RootNode.h:370
Index32 activeTileCount() const
Definition RootNode.h:1599
ValueIter< RootNode, MapIter, ValueAllPred, ValueType > ValueAllIter
Definition RootNode.h:372
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:3236
Index64 onLeafVoxelCount() const
Definition RootNode.h:1655
const LeafNodeType * probeConstLeafAndCache(const Coord &xyz, AccessorT &acc) const
void clip(const CoordBBox &)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition RootNode.h:2462
LeafNodeType * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists,...
Definition RootNode.h:2892
static bool hasCompatibleValueType(const RootNode< OtherChildType > &other)
Definition RootNode.h:1483
ValueAllCIter cbeginValueAll() const
Definition RootNode.h:388
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:2936
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:2502
typename NodeChain< RootNode, LEVEL >::Type NodeChainType
Definition RootNode.h:49
bool isBackgroundTile(const Tile &) const
Return true if the given tile is inactive and has the background value.
Definition RootNode.h:1280
typename typename SubtreeT::Back::LeafNodeType LeafNodeType
Definition RootNode.h:42
size_t eraseBackgroundTiles()
Remove all background tiles.
Definition RootNode.h:1314
void topologyDifference(const RootNode< OtherChildType > &other)
Difference this tree's set of active values with the active values of the other tree,...
Definition RootNode.h:3310
ValueIter< RootNode, MapIter, ValueOnPred, ValueType > ValueOnIter
Definition RootNode.h:368
ValueOnCIter beginValueOn() const
Definition RootNode.h:389
void merge(RootNode &other)
Efficiently merge another tree into this tree using one of several schemes.
Definition RootNode.h:3124
ChildIter< RootNode, MapIter, ChildOnPred, typename SubtreeT::Back > ChildOnIter
Definition RootNode.h:361
Index64 offLeafVoxelCount() const
Definition RootNode.h:1667
Index getWidth() const
Definition RootNode.h:461
Index getTableSize() const
Return the number of entries in this node's table.
Definition RootNode.h:459
bool probe(const Coord &xyz, const ChildNodeType *&child, ValueType &value, bool &active) const
Definition RootNode.h:749
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile containing voxel (x, y, z) at the specified tree level, creating a new branch if necessary...
Definition RootNode.h:2652
void setOrigin(const Coord &origin)
change the origin on this root node
Definition RootNode.h:2629
void combine2(const RootNode &other0, const OtherRootNode &other1, CombineOp &op, bool prune=false)
Definition RootNode.h:3439
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition RootNode.h:944
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition RootNode.h:2059
void setValueOnlyAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition RootNode.h:1965
size_t numBackgroundTiles() const
Return the number of background tiles.
Definition RootNode.h:1302
ValueIter< const RootNode, MapCIter, ChildOffPred, ValueType > ChildOffCIter
Definition RootNode.h:364
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:1945
bool empty() const
Return true if this node's table is either empty or contains only background tiles.
Definition RootNode.h:447
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Definition RootNode.h:2900
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:2876
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:2155
ValueOffCIter beginValueOff() const
Definition RootNode.h:390
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition RootNode.h:1877
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:2542
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
ChildAllCIter cbeginChildAll() const
Definition RootNode.h:378
Index64 leafCount() const
Definition RootNode.h:1549
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:2639
ChildAllIter beginChildAll()
Definition RootNode.h:384
bool probeConst(const Coord &xyz, const ChildNodeType *&child, ValueType &value, bool &active) const
Definition RootNode.h:2856
friend struct RootNodeCombineHelper
Definition RootNode.h:964
static Index getLevel()
Definition RootNode.h:454
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
Definition RootNode.h:1855
ValueIter< const RootNode, MapCIter, ValueAllPred, const ValueType > ValueAllCIter
Definition RootNode.h:373
const ChildNodeType * getChildUnsafe(const Coord &xyz) const
Return the child node at the given coordinate.
Definition RootNode.h:3022
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Definition RootNode.h:1732
const NodeT * probeConstNodeAndCache(const Coord &xyz, AccessorT &acc) const
Definition RootNode.h:2955
bool probeValue(const Coord &xyz, ValueType &value) const
Definition RootNode.h:2119
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:1804
ValueOnIter beginValueOn()
Definition RootNode.h:392
void modifyValueAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition RootNode.h:2022
static const Index LEVEL
Definition RootNode.h:46
Index32 inactiveTileCount() const
Definition RootNode.h:1611
ChildOffCIter cbeginChildOff() const
Definition RootNode.h:377
ChildOffIter beginChildOff()
Definition RootNode.h:383
Index64 onVoxelCount() const
Definition RootNode.h:1623
ChildOffCIter beginChildOff() const
Definition RootNode.h:380
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:2688
typename typename SubtreeT::Back::ValueType ValueType
Definition RootNode.h:43
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition RootNode.h:1790
void nodeCount(std::vector< Index64 > &vec) const
Definition RootNode.h:1693
ValueOnCIter cbeginValueOn() const
Definition RootNode.h:386
RootNode(const ValueType &background)
Construct a new tree with the given background value.
Definition RootNode.h:1080
const LeafNodeType * probeLeaf(const Coord &xyz) const
Definition RootNode.h:774
Index32 tileCount() const
Definition RootNode.h:1587
Index32 childCount() const
Definition RootNode.h:1575
Index64 onTileCount() const
Definition RootNode.h:1678
RootNode()
Construct a new tree with a background value of 0.
Definition RootNode.h:1071
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:1989
bool isBackgroundTile(const MapIter &) const
Return true if the given iterator points to an inactive tile with the background value.
Definition RootNode.h:1287
~RootNode()
Definition RootNode.h:123
Index64 offVoxelCount() const
Definition RootNode.h:1639
LeafNodeType * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists,...
Definition RootNode.h:2746
void getNodes(ArrayT &array) const
Definition RootNode.h:3062
RootNode(const RootNode< OtherChildType > &other, const ValueType &background, const ValueType &foreground, TopologyCopy)
Construct a new tree that reproduces the topology and active states of another tree (which may have a...
Definition RootNode.h:1090
typename typename SubtreeT::Back::BuildType BuildType
Definition RootNode.h:44
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:1253
ChildNodeType * getChildUnsafe(const Coord &xyz)
Return the child node at the given coordinate.
Definition RootNode.h:3000
DenseIter< const RootNode, MapCIter, const typename SubtreeT::Back, const ValueType > ChildAllCIter
Definition RootNode.h:366
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:1404
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:2213
const NodeT * probeNode(const Coord &xyz) const
Definition RootNode.h:2810
ChildAllCIter beginChildAll() const
Definition RootNode.h:381
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Definition RootNode.h:1828
void topologyIntersection(const RootNode< OtherChildType > &other)
Intersects this tree's set of active values with the active values of the other tree,...
Definition RootNode.h:3274
void setTransientData(Index32 transientData)
Set the transient data value.
Definition RootNode.h:412
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:3092
Index getHeight() const
Definition RootNode.h:462
const LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc) const
bool probeValueAndCache(const Coord &xyz, ValueType &value, AccessorT &) const
Definition RootNode.h:2135
bool addChild(ChildNodeType *child)
Add the given child node at the root level. If a child node with the same origin already exists,...
Definition RootNode.h:2613
const NodeT * probeConstNode(const Coord &xyz) const
Definition RootNode.h:2819
bool hasKey(const Coord &key) const
Return true if this node's mTable contains the given key.
Definition RootNode.h:956
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:1535
const ChildNodeType * probeChild(const Coord &xyz) const
Definition RootNode.h:766
const ValueType & background() const
Definition RootNode.h:429
static void getNodeLog2Dims(std::vector< Index > &dims)
Definition RootNode.h:1367
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:84
ValueOffIter beginValueOff()
Definition RootNode.h:393
ValueIter< RootNode, MapIter, ChildOffPred, const ValueType > ChildOffIter
Definition RootNode.h:363
void sparseFill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Definition RootNode.h:541
Coord getMinIndex() const
friend struct RootNodeCopyHelper
Definition RootNode.h:963
const ChildNodeType * probeConstChild(const Coord &xyz) const
Definition RootNode.h:2884
typename SubtreeT::Back ChildNodeType
Definition RootNode.h:41
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:2727
bool hasActiveTiles() const
Return true if this root node, or any of its child nodes, have active tiles.
Definition RootNode.h:1721
int getValueDepthAndCache(const Coord &xyz, AccessorT &) const
Definition RootNode.h:1778
const ValueType & getValue(const Coord &xyz) const
Definition RootNode.h:1744
Index64 memUsage() const
Return the total amount of memory in bytes occupied by this node and its children.
Definition RootNode.h:1510
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:1902
void stealNodes(ArrayT &array)
Definition RootNode.h:876
bool expand(const Coord &xyz)
Expand this node's table so that (x, y, z) is included in the index range.
Definition RootNode.h:1353
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition RootNode.h:2087
ValueAllCIter beginValueAll() const
Definition RootNode.h:391
NodeT * probeNode(const Coord &xyz)
Return a pointer to the node that contains voxel (x, y, z). If no such node exists,...
Definition RootNode.h:2792
ChildIter< const RootNode, MapCIter, ChildOnPred, const typename SubtreeT::Back > ChildOnCIter
Definition RootNode.h:362
ValueAllIter beginValueAll()
Definition RootNode.h:394
friend class RootNode
Definition RootNode.h:961
T truncateRealToHalf(const T &val)
Return the given value truncated to 16-bit float precision.
Definition Compression.h:216
void checkFormatVersion(std::ios_base &)
Throws an IoError if the file format version number is not supported.
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...
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition Vec3.h:474
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
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:428
T negative(const T &val)
Return the unary negation of the given value.
Definition Math.h:139
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition Math.h:465
bool operator!=(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Inequality operator, does exact floating point comparisons.
Definition Vec3.h:482
Definition TreeIterator.h:30
Index32 Index
Definition Types.h:34
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition Math.h:71
uint32_t Index32
Definition Types.h:32
int32_t Int32
Definition Types.h:36
uint64_t Index64
Definition Types.h:33
@ MERGE_ACTIVE_STATES
Definition Types.h:578
@ MERGE_NODES
Definition Types.h:579
@ MERGE_ACTIVE_STATES_AND_NODES
Definition Types.h:580
const char * typeNameAsString()
Definition Types.h:587
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
CanConvertType<FromType, ToType>::value is true if a value of type ToType can be constructed from a v...
Definition Types.h:459
@ value
Definition Types.h:459
A list of types (not necessarily unique)
Definition TypeList.h:576
TypeList< typename HeadT::ChildNodeType, HeadT > Type
Definition RootNode.h:1044
NodeChain<RootNodeType, RootNodeType::LEVEL>::Type is a openvdb::TypeList that lists the types of the...
Definition RootNode.h:1036
typename NodeChain< typename HeadT::ChildNodeType, HeadLevel-1 >::Type SubtreeT
Definition RootNode.h:1037
typename SubtreeT::template Append< HeadT > Type
Definition RootNode.h:1038
static void combine2(RootT &self, const RootT &other0, const OtherRootT &other1, CombineOp &op, bool prune)
Definition RootNode.h:3428
Definition RootNode.h:3408
static void combine2(RootT &self, const RootT &, const OtherRootT &other1, CombineOp &, bool)
Definition RootNode.h:3409
static void copyWithValueConversion(RootT &self, const OtherRootT &other)
Definition RootNode.h:1169
Definition RootNode.h:1150
static void copyWithValueConversion(RootT &self, const OtherRootT &other)
Definition RootNode.h:1151
SameConfiguration<OtherNodeType>::value is true if and only if OtherNodeType is the type of a RootNod...
Definition RootNode.h:64
static const bool value
Definition RootNode.h:65
ValueConverter<T>::Type is the type of a RootNode having the same child hierarchy as this node but a ...
Definition RootNode.h:56
RootNode< typename ChildType::template ValueConverter< OtherValueType >::Type > Type
Definition RootNode.h:57
static const bool value
Definition RootNode.h:1061
Definition RootNode.h:1055
static const bool value
Definition RootNode.h:1056
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:291