11#ifndef OPENVDB_TOOLS_SIGNEDFLOODFILL_HAS_BEEN_INCLUDED 
   12#define OPENVDB_TOOLS_SIGNEDFLOODFILL_HAS_BEEN_INCLUDED 
   14#include <openvdb/version.h> 
   43template<
typename TreeOrLeafManagerT>
 
   46    size_t grainSize = 1, Index minLevel = 0);
 
   67template<
typename TreeOrLeafManagerT>
 
   70    TreeOrLeafManagerT& tree,
 
   71    const typename TreeOrLeafManagerT::ValueType& outsideWidth,
 
   72    const typename TreeOrLeafManagerT::ValueType& insideWidth,
 
   81template<
typename TreeOrLeafManagerT>
 
   85    using ValueT = 
typename TreeOrLeafManagerT::ValueType;
 
   86    using RootT = 
typename TreeOrLeafManagerT::RootNodeType;
 
   87    using LeafT = 
typename TreeOrLeafManagerT::LeafNodeType;
 
   88    static_assert(std::is_signed<ValueT>::value,
 
   89        "signed flood fill is supported only for signed value grids");
 
  101        , mMinLevel(minLevel)
 
 
  108        if (LeafT::LEVEL < mMinLevel) 
return;
 
  110        if (!leaf.allocate()) 
return; 
 
  112        const typename LeafT::NodeMaskType& valueMask = leaf.getValueMask();
 
  114        typename LeafT::ValueType* buffer =
 
  115            const_cast<typename LeafT::ValueType*
>(&(leaf.getFirstValue()));
 
  117        const Index first = valueMask.findFirstOn();
 
  118        if (first < LeafT::SIZE) {
 
  119            bool xInside = buffer[first]<0, yInside = xInside, zInside = xInside;
 
  120            for (
Index x = 0; x != (1 << LeafT::LOG2DIM); ++x) {
 
  121                const Index x00 = x << (2 * LeafT::LOG2DIM);
 
  122                if (valueMask.isOn(x00)) xInside = buffer[x00] < 0; 
 
  124                for (
Index y = 0; y != (1 << LeafT::LOG2DIM); ++y) {
 
  125                    const Index xy0 = x00 + (y << LeafT::LOG2DIM);
 
  126                    if (valueMask.isOn(xy0)) yInside = buffer[xy0] < 0; 
 
  128                    for (
Index z = 0; z != (1 << LeafT::LOG2DIM); ++z) {
 
  129                        const Index xyz = xy0 + z; 
 
  130                        if (valueMask.isOn(xyz)) {
 
  131                            zInside = buffer[xyz] < 0;
 
  133                            buffer[xyz] = zInside ? mInside : mOutside;
 
  139            leaf.fill(buffer[0] < 0 ? mInside : mOutside);
 
 
  144    template<
typename NodeT>
 
  147        if (NodeT::LEVEL < mMinLevel) 
return;
 
  149        const typename NodeT::NodeMaskType& childMask = node.getChildMask();
 
  151        typename NodeT::UnionType* table = 
const_cast<typename NodeT::UnionType*
>(node.getTable());
 
  153        const Index first = childMask.findFirstOn();
 
  154        if (first < NodeT::NUM_VALUES) {
 
  155            bool xInside = table[first].getChild()->getFirstValue()<0;
 
  156            bool yInside = xInside, zInside = xInside;
 
  157            for (
Index x = 0; x != (1 << NodeT::LOG2DIM); ++x) {
 
  158                const int x00 = x << (2 * NodeT::LOG2DIM); 
 
  159                if (childMask.isOn(x00)) xInside = table[x00].getChild()->getLastValue()<0;
 
  161                for (
Index y = 0; y != (1 << NodeT::LOG2DIM); ++y) {
 
  162                    const Index xy0 = x00 + (y << NodeT::LOG2DIM); 
 
  163                    if (childMask.isOn(xy0)) yInside = table[xy0].getChild()->getLastValue()<0;
 
  165                    for (
Index z = 0; z != (1 << NodeT::LOG2DIM); ++z) {
 
  166                        const Index xyz = xy0 + z; 
 
  167                        if (childMask.isOn(xyz)) {
 
  168                            zInside = table[xyz].getChild()->getLastValue()<0;
 
  170                            table[xyz].setValue(zInside ? mInside : mOutside);
 
  176            const ValueT v =  table[0].getValue()<0 ? mInside : mOutside;
 
  177            for (
Index i = 0; i < NodeT::NUM_VALUES; ++i) table[i].setValue(v);
 
 
  184        if (RootT::LEVEL < mMinLevel) 
return;
 
  185        using ChildT = 
typename RootT::ChildNodeType;
 
  187        std::map<Coord, ChildT*> nodeKeys;
 
  188        typename RootT::ChildOnIter it = root.beginChildOn();
 
  189        for (; it; ++it) nodeKeys.insert(std::pair<Coord, ChildT*>(it.getCoord(), &(*it)));
 
  190        static const Index DIM = RootT::ChildNodeType::DIM;
 
  194        typename std::map<Coord, ChildT*>::const_iterator b = nodeKeys.begin(), e = nodeKeys.end();
 
  195        if ( b == e ) 
return;
 
  196        for (
typename std::map<Coord, ChildT*>::const_iterator a = b++; b != e; ++a, ++b) {
 
  197            Coord d = b->first - a->first; 
 
  198            if (d[0]!=0 || d[1]!=0 || d[2]==
Int32(DIM)) 
continue;
 
  199            const ValueT fill[] = { a->second->getLastValue(), b->second->getFirstValue() };
 
  200            if (!(fill[0] < 0) || !(fill[1] < 0)) 
continue; 
 
  202            for (; c[2] != b->first[2]; c[2] += DIM) root.addTile(c, mInside, 
false);
 
  204        root.setBackground(mOutside, 
false);
 
 
  208    const ValueT mOutside, mInside;
 
  209    const Index mMinLevel;
 
 
  216template<
typename TreeOrLeafManagerT>
 
  218typename std::enable_if<std::is_signed<typename TreeOrLeafManagerT::ValueType>::value, 
void>::type
 
  219doSignedFloodFill(TreeOrLeafManagerT& 
tree,
 
  220                  typename TreeOrLeafManagerT::ValueType outsideValue,
 
  221                  typename TreeOrLeafManagerT::ValueType insideValue,
 
  227    SignedFloodFillOp<TreeOrLeafManagerT> op(outsideValue, insideValue, minLevel);
 
  228    nodes.foreachBottomUp(op, threaded, grainSize);
 
  232template <
typename TreeOrLeafManagerT>
 
  234typename std::enable_if<!std::is_signed<typename TreeOrLeafManagerT::ValueType>::value, 
void>::type
 
  235doSignedFloodFill(TreeOrLeafManagerT&,
 
  236                  const typename TreeOrLeafManagerT::ValueType&,
 
  237                  const typename TreeOrLeafManagerT::ValueType&,
 
  243        "signedFloodFill is supported only for signed value grids");
 
  251template <
typename TreeOrLeafManagerT>
 
  254    TreeOrLeafManagerT& 
tree,
 
  255    const typename TreeOrLeafManagerT::ValueType& outsideValue,
 
  256    const typename TreeOrLeafManagerT::ValueType& insideValue,
 
  261    doSignedFloodFill(
tree, outsideValue, insideValue, 
threaded, grainSize, minLevel);
 
 
  265template <
typename TreeOrLeafManagerT>
 
  272    const typename TreeOrLeafManagerT::ValueType v = 
tree.root().background();
 
 
  282#ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION 
  284#ifdef OPENVDB_INSTANTIATE_SIGNEDFLOODFILL 
  288#define _FUNCTION(TreeT) \ 
  289    void signedFloodFill(TreeT&, bool, size_t, Index) 
  293#define _FUNCTION(TreeT) \ 
  294    void signedFloodFill(tree::LeafManager<TreeT>&, bool, size_t, Index) 
  298#define _FUNCTION(TreeT) \ 
  299    void signedFloodFillWithValues(TreeT&, const TreeT::ValueType&, const TreeT::ValueType&, bool, size_t, Index) 
  303#define _FUNCTION(TreeT) \ 
  304    void signedFloodFillWithValues(tree::LeafManager<TreeT>&, const TreeT::ValueType&, const TreeT::ValueType&, bool, size_t, Index) 
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Definition Exceptions.h:64
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:26
To facilitate threading over the nodes of a tree, cache node pointers in linear arrays,...
Definition NodeManager.h:532
T negative(const T &val)
Return the unary negation of the given value.
Definition Math.h:128
Definition PointDataGrid.h:170
Index32 Index
Definition Types.h:54
int32_t Int32
Definition Types.h:56
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
#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:218
#define OPENVDB_REAL_TREE_INSTANTIATE(Function)
Definition version.h.in:162