diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files
index fefabee6901b217ba62982c408c5b0e5a2eda18f..2f20fee7e8a59471a1a670dddb00a7ab87e0c2eb 100644
--- a/src/OpenFOAM/Make/files
+++ b/src/OpenFOAM/Make/files
@@ -584,6 +584,8 @@ algorithms/indexedOctree/indexedOctreeName.C
 algorithms/indexedOctree/treeDataCell.C
 
 
+algorithms/dynamicIndexedOctree/dynamicIndexedOctreeName.C
+algorithms/dynamicIndexedOctree/dynamicTreeDataPoint.C
 
 graph/curve/curve.C
 graph/graph.C
diff --git a/src/OpenFOAM/algorithms/dynamicIndexedOctree/dynamicIndexedOctree.C b/src/OpenFOAM/algorithms/dynamicIndexedOctree/dynamicIndexedOctree.C
new file mode 100644
index 0000000000000000000000000000000000000000..0db3d8f472a50e68db593260f2467673a9c59bc1
--- /dev/null
+++ b/src/OpenFOAM/algorithms/dynamicIndexedOctree/dynamicIndexedOctree.C
@@ -0,0 +1,3018 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "dynamicIndexedOctree.H"
+#include "linePointRef.H"
+#include "OFstream.H"
+#include "ListOps.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+template <class Type>
+Foam::scalar Foam::dynamicIndexedOctree<Type>::perturbTol_ = 10*SMALL;
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+// Does bb intersect a sphere around sample? Or is any corner point of bb
+// closer than nearestDistSqr to sample.
+template <class Type>
+bool Foam::dynamicIndexedOctree<Type>::overlaps
+(
+    const point& p0,
+    const point& p1,
+    const scalar nearestDistSqr,
+    const point& sample
+)
+{
+    // Find out where sample is in relation to bb.
+    // Find nearest point on bb.
+    scalar distSqr = 0;
+
+    for (direction dir = 0; dir < vector::nComponents; dir++)
+    {
+        scalar d0 = p0[dir] - sample[dir];
+        scalar d1 = p1[dir] - sample[dir];
+
+        if ((d0 > 0) != (d1 > 0))
+        {
+            // sample inside both extrema. This component does not add any
+            // distance.
+        }
+        else if (mag(d0) < mag(d1))
+        {
+            distSqr += d0*d0;
+        }
+        else
+        {
+            distSqr += d1*d1;
+        }
+
+        if (distSqr > nearestDistSqr)
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+
+// Does bb intersect a sphere around sample? Or is any corner point of bb
+// closer than nearestDistSqr to sample.
+template <class Type>
+bool Foam::dynamicIndexedOctree<Type>::overlaps
+(
+    const treeBoundBox& parentBb,
+    const direction octant,
+    const scalar nearestDistSqr,
+    const point& sample
+)
+{
+    //- Accelerated version of
+    //     treeBoundBox subBb(parentBb.subBbox(mid, octant))
+    //     overlaps
+    //     (
+    //          subBb.min(),
+    //          subBb.max(),
+    //          nearestDistSqr,
+    //          sample
+    //     )
+
+    const point& min = parentBb.min();
+    const point& max = parentBb.max();
+
+    point other;
+
+    if (octant & treeBoundBox::RIGHTHALF)
+    {
+        other.x() = max.x();
+    }
+    else
+    {
+        other.x() = min.x();
+    }
+
+    if (octant & treeBoundBox::TOPHALF)
+    {
+        other.y() = max.y();
+    }
+    else
+    {
+        other.y() = min.y();
+    }
+
+    if (octant & treeBoundBox::FRONTHALF)
+    {
+        other.z() = max.z();
+    }
+    else
+    {
+        other.z() = min.z();
+    }
+
+    const point mid(0.5*(min+max));
+
+    return overlaps(mid, other, nearestDistSqr, sample);
+}
+
+
+//
+// Construction helper routines
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+
+// Split list of indices into 8 bins
+template <class Type>
+void Foam::dynamicIndexedOctree<Type>::divide
+(
+    const autoPtr<DynamicList<label> >& indices,
+    const treeBoundBox& bb,
+    contentListList& result
+) const
+{
+    for (direction octant = 0; octant < 8; octant++)
+    {
+        result.append
+        (
+            autoPtr<DynamicList<label> >
+            (
+                new DynamicList<label>(indices().size()/8)
+            )
+        );
+    }
+
+    // Precalculate bounding boxes.
+    FixedList<treeBoundBox, 8> subBbs;
+    for (direction octant = 0; octant < 8; octant++)
+    {
+        subBbs[octant] = bb.subBbox(octant);
+    }
+
+    forAll(indices(), i)
+    {
+        label shapeI = indices()[i];
+
+        for (direction octant = 0; octant < 8; octant++)
+        {
+            if (shapes_.overlaps(shapeI, subBbs[octant]))
+            {
+                result[octant]().append(shapeI);
+            }
+        }
+    }
+}
+
+
+// Subdivide the (content) node.
+template <class Type>
+typename Foam::dynamicIndexedOctree<Type>::node
+Foam::dynamicIndexedOctree<Type>::divide
+(
+    const treeBoundBox& bb,
+    const label contentI,
+    const label parentNodeIndex,
+    const label octantToBeDivided
+)
+{
+    const autoPtr<DynamicList<label> >& indices = contents_[contentI];
+
+    node nod;
+
+    if
+    (
+        bb.min()[0] >= bb.max()[0]
+     || bb.min()[1] >= bb.max()[1]
+     || bb.min()[2] >= bb.max()[2]
+    )
+    {
+        FatalErrorIn("dynamicIndexedOctree<Type>::divide(..)")
+            << "Badly formed bounding box:" << bb
+            << abort(FatalError);
+    }
+
+    nod.bb_ = bb;
+    nod.parent_ = -1;
+
+    contentListList dividedIndices(8);
+    divide(indices, bb, dividedIndices);
+
+    // Have now divided the indices into 8 (possibly empty) subsets.
+    // Replace current contentI with the first (non-empty) subset.
+    // Append the rest.
+    bool replaced = false;
+
+    for (direction octant = 0; octant < dividedIndices.size(); octant++)
+    {
+        autoPtr<DynamicList<label> >& subIndices = dividedIndices[octant];
+
+        if (subIndices().size())
+        {
+            if (!replaced)
+            {
+                contents_[contentI]().transfer(subIndices());
+                nod.subNodes_[octant] = contentPlusOctant(contentI, octant);
+
+                replaced = true;
+            }
+            else
+            {
+                // Store at end of contents.
+                // note dummy append + transfer trick
+                label sz = contents_.size();
+
+                contents_.append
+                (
+                    autoPtr<DynamicList<label> >
+                    (
+                        new DynamicList<label>()
+                    )
+                );
+
+                contents_[sz]().transfer(subIndices());
+
+                nod.subNodes_[octant] = contentPlusOctant(sz, octant);
+            }
+        }
+        else
+        {
+            // Mark node as empty
+            nod.subNodes_[octant] = emptyPlusOctant(octant);
+        }
+    }
+
+    // Don't update the parent node if it is the first node.
+    if (parentNodeIndex != -1)
+    {
+        nod.parent_ = parentNodeIndex;
+
+        label sz = nodes_.size();
+
+        nodes_.append(nod);
+
+        nodes_[parentNodeIndex].subNodes_[octantToBeDivided]
+            = nodePlusOctant(sz, octantToBeDivided);
+    }
+
+    return nod;
+}
+
+
+template <class Type>
+void Foam::dynamicIndexedOctree<Type>::recursiveSubDivision
+(
+    const treeBoundBox& subBb,
+    const label contentI,
+    const label parentIndex,
+    const label octant,
+    label& nLevels
+)
+{
+    if
+    (
+        contents_[contentI]().size() > minSize_
+     && nLevels < maxLevels_
+    )
+    {
+        // Create node for content
+        node nod = divide(subBb, contentI, parentIndex, octant);
+
+        // Increment the number of levels in the tree
+        nLevels++;
+
+        // Recursively divide the contents until maxLevels_ is
+        // reached or the content sizes are less than minSize_
+        for (direction subOct = 0; subOct < 8; subOct++)
+        {
+            const labelBits& subNodeLabel = nod.subNodes_[subOct];
+
+            if (isContent(subNodeLabel))
+            {
+                const treeBoundBox subBb = nod.bb_.subBbox(subOct);
+
+                const label subContentI = getContent(subNodeLabel);
+
+                const label parentNodeIndex = nodes_.size() - 1;
+
+                recursiveSubDivision
+                (
+                    subBb,
+                    subContentI,
+                    parentNodeIndex,
+                    subOct,
+                    nLevels
+                );
+            }
+        }
+    }
+}
+
+
+// Pre-calculates wherever possible the volume status per node/subnode.
+// Recurses to determine status of lowest level boxes. Level above is
+// combination of octants below.
+template <class Type>
+typename Foam::dynamicIndexedOctree<Type>::volumeType
+Foam::dynamicIndexedOctree<Type>::calcVolumeType
+(
+    const label nodeI
+) const
+{
+    const node& nod = nodes_[nodeI];
+
+    volumeType myType = UNKNOWN;
+
+    for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
+    {
+        volumeType subType;
+
+        labelBits index = nod.subNodes_[octant];
+
+        if (isNode(index))
+        {
+            // tree node. Recurse.
+            subType = calcVolumeType(getNode(index));
+        }
+        else if (isContent(index))
+        {
+            // Contents. Depending on position in box might be on either
+            // side.
+            subType = MIXED;
+        }
+        else
+        {
+            // No data in this octant. Set type for octant acc. to the mid
+            // of its bounding box.
+            const treeBoundBox subBb = nod.bb_.subBbox(octant);
+
+            subType = volumeType
+            (
+                shapes_.getVolumeType(*this, subBb.midpoint())
+            );
+        }
+
+        // Store octant type
+        nodeTypes_.set((nodeI<<3)+octant, subType);
+
+        // Combine sub node types into type for treeNode. Result is 'mixed' if
+        // types differ among subnodes.
+        if (myType == UNKNOWN)
+        {
+            myType = subType;
+        }
+        else if (subType != myType)
+        {
+            myType = MIXED;
+        }
+    }
+    return myType;
+}
+
+
+template <class Type>
+typename Foam::dynamicIndexedOctree<Type>::volumeType
+Foam::dynamicIndexedOctree<Type>::getVolumeType
+(
+    const label nodeI,
+    const point& sample
+) const
+{
+    const node& nod = nodes_[nodeI];
+
+    direction octant = nod.bb_.subOctant(sample);
+
+    volumeType octantType = volumeType(nodeTypes_.get((nodeI<<3)+octant));
+
+    if (octantType == INSIDE)
+    {
+        return octantType;
+    }
+    else if (octantType == OUTSIDE)
+    {
+        return octantType;
+    }
+    else if (octantType == UNKNOWN)
+    {
+        // Can happen for e.g. non-manifold surfaces.
+        return octantType;
+    }
+    else if (octantType == MIXED)
+    {
+        labelBits index = nod.subNodes_[octant];
+
+        if (isNode(index))
+        {
+            // Recurse
+            volumeType subType = getVolumeType(getNode(index), sample);
+
+            return subType;
+        }
+        else if (isContent(index))
+        {
+            // Content. Defer to shapes.
+            return volumeType(shapes_.getVolumeType(*this, sample));
+        }
+        else
+        {
+            // Empty node. Cannot have 'mixed' as its type since not divided
+            // up and has no items inside it.
+            FatalErrorIn
+            (
+                "dynamicIndexedOctree<Type>::getVolumeType"
+                "(const label, const point&)"
+            )   << "Sample:" << sample << " node:" << nodeI
+                << " with bb:" << nodes_[nodeI].bb_ << nl
+                << "Empty subnode has invalid volume type MIXED."
+                << abort(FatalError);
+
+            return UNKNOWN;
+        }
+    }
+    else
+    {
+        FatalErrorIn
+        (
+            "dynamicIndexedOctree<Type>::getVolumeType"
+            "(const label, const point&)"
+        )   << "Sample:" << sample << " at node:" << nodeI
+            << " octant:" << octant
+            << " with bb:" << nod.bb_.subBbox(octant) << nl
+            << "Node has invalid volume type " << octantType
+            << abort(FatalError);
+
+        return UNKNOWN;
+    }
+}
+
+
+template <class Type>
+typename Foam::dynamicIndexedOctree<Type>::volumeType
+Foam::dynamicIndexedOctree<Type>::getSide
+(
+    const vector& outsideNormal,
+    const vector& vec
+)
+{
+    if ((outsideNormal&vec) >= 0)
+    {
+        return OUTSIDE;
+    }
+    else
+    {
+        return INSIDE;
+    }
+}
+
+
+//
+// Query routines
+// ~~~~~~~~~~~~~~
+//
+
+// Find nearest point starting from nodeI
+template <class Type>
+void Foam::dynamicIndexedOctree<Type>::findNearest
+(
+    const label nodeI,
+    const point& sample,
+
+    scalar& nearestDistSqr,
+    label& nearestShapeI,
+    point& nearestPoint
+) const
+{
+    const node& nod = nodes_[nodeI];
+
+    // Determine order to walk through octants
+    FixedList<direction, 8> octantOrder;
+    nod.bb_.searchOrder(sample, octantOrder);
+
+    // Go into all suboctants (one containing sample first) and update nearest.
+    for (direction i = 0; i < 8; i++)
+    {
+        direction octant = octantOrder[i];
+
+        labelBits index = nod.subNodes_[octant];
+
+        if (isNode(index))
+        {
+            label subNodeI = getNode(index);
+
+            const treeBoundBox& subBb = nodes_[subNodeI].bb_;
+
+            if (overlaps(subBb.min(), subBb.max(), nearestDistSqr, sample))
+            {
+                findNearest
+                (
+                    subNodeI,
+                    sample,
+
+                    nearestDistSqr,
+                    nearestShapeI,
+                    nearestPoint
+                );
+            }
+        }
+        else if (isContent(index))
+        {
+            if
+            (
+                overlaps
+                (
+                    nod.bb_,
+                    octant,
+                    nearestDistSqr,
+                    sample
+                )
+            )
+            {
+                shapes_.findNearest
+                (
+                    contents_[getContent(index)],
+                    sample,
+
+                    nearestDistSqr,
+                    nearestShapeI,
+                    nearestPoint
+                );
+            }
+        }
+    }
+}
+
+
+// Find nearest point to line.
+template <class Type>
+void Foam::dynamicIndexedOctree<Type>::findNearest
+(
+    const label nodeI,
+    const linePointRef& ln,
+
+    treeBoundBox& tightest,
+    label& nearestShapeI,
+    point& linePoint,
+    point& nearestPoint
+) const
+{
+    const node& nod = nodes_[nodeI];
+    const treeBoundBox& nodeBb = nod.bb_;
+
+    // Determine order to walk through octants
+    FixedList<direction, 8> octantOrder;
+    nod.bb_.searchOrder(ln.centre(), octantOrder);
+
+    // Go into all suboctants (one containing sample first) and update nearest.
+    for (direction i = 0; i < 8; i++)
+    {
+        direction octant = octantOrder[i];
+
+        labelBits index = nod.subNodes_[octant];
+
+        if (isNode(index))
+        {
+            const treeBoundBox& subBb = nodes_[getNode(index)].bb_;
+
+            if (subBb.overlaps(tightest))
+            {
+                findNearest
+                (
+                    getNode(index),
+                    ln,
+
+                    tightest,
+                    nearestShapeI,
+                    linePoint,
+                    nearestPoint
+                );
+            }
+        }
+        else if (isContent(index))
+        {
+            const treeBoundBox subBb(nodeBb.subBbox(octant));
+
+            if (subBb.overlaps(tightest))
+            {
+                shapes_.findNearest
+                (
+                    contents_[getContent(index)],
+                    ln,
+
+                    tightest,
+                    nearestShapeI,
+                    linePoint,
+                    nearestPoint
+                );
+            }
+        }
+    }
+}
+
+
+template <class Type>
+Foam::treeBoundBox Foam::dynamicIndexedOctree<Type>::subBbox
+(
+    const label parentNodeI,
+    const direction octant
+) const
+{
+    // Get type of node at octant
+    const node& nod = nodes_[parentNodeI];
+    labelBits index = nod.subNodes_[octant];
+
+    if (isNode(index))
+    {
+        // Use stored bb
+        return nodes_[getNode(index)].bb_;
+    }
+    else
+    {
+        // Calculate subBb
+        return nod.bb_.subBbox(octant);
+    }
+}
+
+
+// Takes a bb and a point on/close to the edge of the bb and pushes the point
+// inside by a small fraction.
+template <class Type>
+Foam::point Foam::dynamicIndexedOctree<Type>::pushPoint
+(
+    const treeBoundBox& bb,
+    const point& pt,
+    const bool pushInside
+)
+{
+    // Get local length scale.
+    const vector perturbVec = perturbTol_*bb.span();
+
+    point perturbedPt(pt);
+
+    // Modify all components which are close to any face of the bb to be
+    // well inside/outside them.
+
+    if (pushInside)
+    {
+        for (direction dir = 0; dir < vector::nComponents; dir++)
+        {
+            if (mag(pt[dir]-bb.min()[dir]) < mag(perturbVec[dir]))
+            {
+                // Close to 'left' side. Push well beyond left side.
+                scalar perturbDist = perturbVec[dir] + ROOTVSMALL;
+                perturbedPt[dir] = bb.min()[dir] + perturbDist;
+            }
+            else if (mag(pt[dir]-bb.max()[dir]) < mag(perturbVec[dir]))
+            {
+                // Close to 'right' side. Push well beyond right side.
+                scalar perturbDist = perturbVec[dir] + ROOTVSMALL;
+                perturbedPt[dir] = bb.max()[dir] - perturbDist;
+            }
+        }
+    }
+    else
+    {
+        for (direction dir = 0; dir < vector::nComponents; dir++)
+        {
+            if (mag(pt[dir]-bb.min()[dir]) < mag(perturbVec[dir]))
+            {
+                scalar perturbDist = perturbVec[dir] + ROOTVSMALL;
+                perturbedPt[dir] = bb.min()[dir] - perturbDist;
+            }
+            else if (mag(pt[dir]-bb.max()[dir]) < mag(perturbVec[dir]))
+            {
+                scalar perturbDist = perturbVec[dir] + ROOTVSMALL;
+                perturbedPt[dir] = bb.max()[dir] + perturbDist;
+            }
+        }
+    }
+
+    if (debug)
+    {
+        if (pushInside != bb.contains(perturbedPt))
+        {
+            FatalErrorIn("dynamicIndexedOctree<Type>::pushPoint(..)")
+                << "pushed point:" << pt
+                << " to:" << perturbedPt
+                << " wanted side:" << pushInside
+                << " obtained side:" << bb.contains(perturbedPt)
+                << " of bb:" << bb
+                << abort(FatalError);
+        }
+    }
+
+    return perturbedPt;
+}
+
+
+// Takes a bb and a point on the edge of the bb and pushes the point
+// outside by a small fraction.
+template <class Type>
+Foam::point Foam::dynamicIndexedOctree<Type>::pushPoint
+(
+    const treeBoundBox& bb,
+    const direction faceID,
+    const point& pt,
+    const bool pushInside
+)
+{
+    // Get local length scale.
+    const vector perturbVec = perturbTol_*bb.span();
+
+    point perturbedPt(pt);
+
+    // Modify all components which are close to any face of the bb to be
+    // well outside them.
+
+    if (faceID == 0)
+    {
+        FatalErrorIn("dynamicIndexedOctree<Type>::pushPoint(..)")
+            << abort(FatalError);
+    }
+
+    if (faceID & treeBoundBox::LEFTBIT)
+    {
+        if (pushInside)
+        {
+            perturbedPt[0] = bb.min()[0] + (perturbVec[0] + ROOTVSMALL);
+        }
+        else
+        {
+            perturbedPt[0] = bb.min()[0] - (perturbVec[0] + ROOTVSMALL);
+        }
+    }
+    else if (faceID & treeBoundBox::RIGHTBIT)
+    {
+        if (pushInside)
+        {
+            perturbedPt[0] = bb.max()[0] - (perturbVec[0] + ROOTVSMALL);
+        }
+        else
+        {
+            perturbedPt[0] = bb.max()[0] + (perturbVec[0] + ROOTVSMALL);
+        }
+    }
+
+    if (faceID & treeBoundBox::BOTTOMBIT)
+    {
+        if (pushInside)
+        {
+            perturbedPt[1] = bb.min()[1] + (perturbVec[1] + ROOTVSMALL);
+        }
+        else
+        {
+            perturbedPt[1] = bb.min()[1] - (perturbVec[1] + ROOTVSMALL);
+        }
+    }
+    else if (faceID & treeBoundBox::TOPBIT)
+    {
+        if (pushInside)
+        {
+            perturbedPt[1] = bb.max()[1] - (perturbVec[1] + ROOTVSMALL);
+        }
+        else
+        {
+            perturbedPt[1] = bb.max()[1] + (perturbVec[1] + ROOTVSMALL);
+        }
+    }
+
+    if (faceID & treeBoundBox::BACKBIT)
+    {
+        if (pushInside)
+        {
+            perturbedPt[2] = bb.min()[2] + (perturbVec[2] + ROOTVSMALL);
+        }
+        else
+        {
+            perturbedPt[2] = bb.min()[2] - (perturbVec[2] + ROOTVSMALL);
+        }
+    }
+    else if (faceID & treeBoundBox::FRONTBIT)
+    {
+        if (pushInside)
+        {
+            perturbedPt[2] = bb.max()[2] - (perturbVec[2] + ROOTVSMALL);
+        }
+        else
+        {
+            perturbedPt[2] = bb.max()[2] + (perturbVec[2] + ROOTVSMALL);
+        }
+    }
+
+    if (debug)
+    {
+        if (pushInside != bb.contains(perturbedPt))
+        {
+            FatalErrorIn("dynamicIndexedOctree<Type>::pushPoint(..)")
+                << "pushed point:" << pt << " on face:" << faceString(faceID)
+                << " to:" << perturbedPt
+                << " wanted side:" << pushInside
+                << " obtained side:" << bb.contains(perturbedPt)
+                << " of bb:" << bb
+                << abort(FatalError);
+        }
+    }
+
+    return perturbedPt;
+}
+
+
+// Guarantees that if pt is on a face it gets perturbed so it is away
+// from the face edges.
+// If pt is not on a face does nothing.
+template <class Type>
+Foam::point Foam::dynamicIndexedOctree<Type>::pushPointIntoFace
+(
+    const treeBoundBox& bb,
+    const vector& dir,          // end-start
+    const point& pt
+)
+{
+    if (debug)
+    {
+        if (bb.posBits(pt) != 0)
+        {
+            FatalErrorIn("dynamicIndexedOctree<Type>::pushPointIntoFace(..)")
+                << " bb:" << bb << endl
+                << "does not contain point " << pt << abort(FatalError);
+        }
+    }
+
+
+    // Handle two cases:
+    // - point exactly on multiple faces. Push away from all but one.
+    // - point on a single face. Push away from edges of face.
+
+    direction ptFaceID = bb.faceBits(pt);
+
+    direction nFaces = 0;
+    FixedList<direction, 3> faceIndices;
+
+    if (ptFaceID & treeBoundBox::LEFTBIT)
+    {
+        faceIndices[nFaces++] = treeBoundBox::LEFT;
+    }
+    else if (ptFaceID & treeBoundBox::RIGHTBIT)
+    {
+        faceIndices[nFaces++] = treeBoundBox::RIGHT;
+    }
+
+    if (ptFaceID & treeBoundBox::BOTTOMBIT)
+    {
+        faceIndices[nFaces++] = treeBoundBox::BOTTOM;
+    }
+    else if (ptFaceID & treeBoundBox::TOPBIT)
+    {
+        faceIndices[nFaces++] = treeBoundBox::TOP;
+    }
+
+    if (ptFaceID & treeBoundBox::BACKBIT)
+    {
+        faceIndices[nFaces++] = treeBoundBox::BACK;
+    }
+    else if (ptFaceID & treeBoundBox::FRONTBIT)
+    {
+        faceIndices[nFaces++] = treeBoundBox::FRONT;
+    }
+
+
+    // Determine the face we want to keep the point on
+
+    direction keepFaceID;
+
+    if (nFaces == 0)
+    {
+        // Return original point
+        return pt;
+    }
+    else if (nFaces == 1)
+    {
+        // Point is on a single face
+        keepFaceID = faceIndices[0];
+    }
+    else
+    {
+        // Determine best face out of faceIndices[0 .. nFaces-1].
+        // The best face is the one most perpendicular to the ray direction.
+
+        keepFaceID = faceIndices[0];
+        scalar maxInproduct = mag(treeBoundBox::faceNormals[keepFaceID] & dir);
+
+        for (direction i = 1; i < nFaces; i++)
+        {
+            direction face = faceIndices[i];
+            scalar s = mag(treeBoundBox::faceNormals[face] & dir);
+            if (s > maxInproduct)
+            {
+                maxInproduct = s;
+                keepFaceID = face;
+            }
+        }
+    }
+
+
+    // 1. Push point into bb, away from all corners
+
+    point facePoint(pushPoint(bb, pt, true));
+    direction faceID = 0;
+
+    // 2. Snap it back onto the preferred face
+
+    if (keepFaceID == treeBoundBox::LEFT)
+    {
+        facePoint.x() = bb.min().x();
+        faceID = treeBoundBox::LEFTBIT;
+    }
+    else if (keepFaceID == treeBoundBox::RIGHT)
+    {
+        facePoint.x() = bb.max().x();
+        faceID = treeBoundBox::RIGHTBIT;
+    }
+    else if (keepFaceID == treeBoundBox::BOTTOM)
+    {
+        facePoint.y() = bb.min().y();
+        faceID = treeBoundBox::BOTTOMBIT;
+    }
+    else if (keepFaceID == treeBoundBox::TOP)
+    {
+        facePoint.y() = bb.max().y();
+        faceID = treeBoundBox::TOPBIT;
+    }
+    else if (keepFaceID == treeBoundBox::BACK)
+    {
+        facePoint.z() = bb.min().z();
+        faceID = treeBoundBox::BACKBIT;
+    }
+    else if (keepFaceID == treeBoundBox::FRONT)
+    {
+        facePoint.z() = bb.max().z();
+        faceID = treeBoundBox::FRONTBIT;
+    }
+
+
+    if (debug)
+    {
+        if (faceID != bb.faceBits(facePoint))
+        {
+            FatalErrorIn("dynamicIndexedOctree<Type>::pushPointIntoFace(..)")
+                << "Pushed point from " << pt
+                << " on face:" << ptFaceID << " of bb:" << bb << endl
+                << "onto " << facePoint
+                << " on face:" << faceID
+                << " which is not consistent with geometric face "
+                << bb.faceBits(facePoint)
+                << abort(FatalError);
+        }
+        if (bb.posBits(facePoint) != 0)
+        {
+            FatalErrorIn("dynamicIndexedOctree<Type>::pushPointIntoFace(..)")
+                << " bb:" << bb << endl
+                << "does not contain perturbed point "
+                << facePoint << abort(FatalError);
+        }
+    }
+
+
+    return facePoint;
+}
+
+
+//// Takes a bb and a point on the outside of the bb. Checks if on multiple
+// faces
+//// and if so perturbs point so it is only on one face.
+//template <class Type>
+//void Foam::dynamicIndexedOctree<Type>::checkMultipleFaces
+//(
+//    const treeBoundBox& bb,
+//    const vector& dir,          // end-start
+//    pointIndexHit& faceHitInfo,
+//    direction& faceID
+//)
+//{
+//    // Do the quick elimination of no or one face.
+//    if
+//    (
+//        (faceID == 0)
+//     || (faceID == treeBoundBox::LEFTBIT)
+//     || (faceID == treeBoundBox::RIGHTBIT)
+//     || (faceID == treeBoundBox::BOTTOMBIT)
+//     || (faceID == treeBoundBox::TOPBIT)
+//     || (faceID == treeBoundBox::BACKBIT)
+//     || (faceID == treeBoundBox::FRONTBIT)
+//    )
+//    {
+//        return;
+//    }
+//
+//
+//    // Check the direction of vector w.r.t. faces being intersected.
+//    FixedList<scalar, 6> inproducts(-GREAT);
+//
+//    direction nFaces = 0;
+//
+//    if (faceID & treeBoundBox::LEFTBIT)
+//    {
+//        inproducts[treeBoundBox::LEFT] = mag
+//        (
+//            treeBoundBox::faceNormals[treeBoundBox::LEFT]
+//          & dir
+//        );
+//        nFaces++;
+//    }
+//    if (faceID & treeBoundBox::RIGHTBIT)
+//    {
+//        inproducts[treeBoundBox::RIGHT] = mag
+//        (
+//            treeBoundBox::faceNormals[treeBoundBox::RIGHT]
+//          & dir
+//        );
+//        nFaces++;
+//    }
+//
+//    if (faceID & treeBoundBox::BOTTOMBIT)
+//    {
+//        inproducts[treeBoundBox::BOTTOM] = mag
+//        (
+//            treeBoundBox::faceNormals[treeBoundBox::BOTTOM]
+//          & dir
+//        );
+//        nFaces++;
+//    }
+//    if (faceID & treeBoundBox::TOPBIT)
+//    {
+//        inproducts[treeBoundBox::TOP] = mag
+//        (
+//            treeBoundBox::faceNormals[treeBoundBox::TOP]
+//          & dir
+//        );
+//        nFaces++;
+//    }
+//
+//    if (faceID & treeBoundBox::BACKBIT)
+//    {
+//        inproducts[treeBoundBox::BACK] = mag
+//        (
+//            treeBoundBox::faceNormals[treeBoundBox::BACK]
+//          & dir
+//        );
+//        nFaces++;
+//    }
+//    if (faceID & treeBoundBox::FRONTBIT)
+//    {
+//        inproducts[treeBoundBox::FRONT] = mag
+//        (
+//            treeBoundBox::faceNormals[treeBoundBox::FRONT]
+//          & dir
+//        );
+//        nFaces++;
+//    }
+//
+//    if (nFaces == 0 || nFaces == 1 || nFaces > 3)
+//    {
+//        FatalErrorIn("dynamicIndexedOctree<Type>::checkMultipleFaces(..)")
+//            << "Problem : nFaces:" << nFaces << abort(FatalError);
+//    }
+//
+//    // Keep point on most perpendicular face; shift it away from the aligned
+//    // ones.
+//    // E.g. line hits top and left face:
+//    //     a
+//    // ----+----+
+//    //     |    |
+//    //     |    |
+//    //     +----+
+//    // Shift point down (away from top):
+//    //
+//    //    a+----+
+//    // ----|    |
+//    //     |    |
+//    //     +----+
+//
+//    label maxIndex = -1;
+//    scalar maxInproduct = -GREAT;
+//
+//    for (direction i = 0; i < 6; i++)
+//    {
+//        if (inproducts[i] > maxInproduct)
+//        {
+//            maxInproduct = inproducts[i];
+//            maxIndex = i;
+//        }
+//    }
+//
+//    if (maxIndex == -1)
+//    {
+//        FatalErrorIn("dynamicIndexedOctree<Type>::checkMultipleFaces(..)")
+//            << "Problem maxIndex:" << maxIndex << " inproducts:" << inproducts
+//            << abort(FatalError);
+//    }
+//
+//    const point oldPoint(faceHitInfo.rawPoint());
+//    const direction oldFaceID = faceID;
+//
+//    // 1. Push point into bb, away from all corners
+//
+//    faceHitInfo.rawPoint() = pushPoint(bb, oldFaceID, oldPoint, true);
+//
+//    // 2. Snap it back onto the preferred face
+//
+//    if (maxIndex == treeBoundBox::LEFT)
+//    {
+//        faceHitInfo.rawPoint().x() = bb.min().x();
+//        faceID = treeBoundBox::LEFTBIT;
+//    }
+//    else if (maxIndex == treeBoundBox::RIGHT)
+//    {
+//        faceHitInfo.rawPoint().x() = bb.max().x();
+//        faceID = treeBoundBox::RIGHTBIT;
+//    }
+//    else if (maxIndex == treeBoundBox::BOTTOM)
+//    {
+//        faceHitInfo.rawPoint().y() = bb.min().y();
+//        faceID = treeBoundBox::BOTTOMBIT;
+//    }
+//    else if (maxIndex == treeBoundBox::TOP)
+//    {
+//        faceHitInfo.rawPoint().y() = bb.max().y();
+//        faceID = treeBoundBox::TOPBIT;
+//    }
+//    else if (maxIndex == treeBoundBox::BACK)
+//    {
+//        faceHitInfo.rawPoint().z() = bb.min().z();
+//        faceID = treeBoundBox::BACKBIT;
+//    }
+//    else if (maxIndex == treeBoundBox::FRONT)
+//    {
+//        faceHitInfo.rawPoint().z() = bb.max().z();
+//        faceID = treeBoundBox::FRONTBIT;
+//    }
+//
+//    Pout<< "From ray:" << dir
+//        << " from point:" << oldPoint
+//        << " on faces:" << faceString(oldFaceID)
+//        << " of bb:" << bb
+//        << " with inprods:" << inproducts
+//        << " maxIndex:" << maxIndex << endl
+//        << "perturbed to point:" << faceHitInfo.rawPoint()
+//        << " on face:" << faceString(faceID)
+//        << endl;
+//
+//
+//    if (debug)
+//    {
+//        if (faceID != bb.faceBits(faceHitInfo.rawPoint()))
+//        {
+//            FatalErrorIn("dynamicIndexedOctree<Type>::checkMultipleFaces(..)")
+//                << "Pushed point from " << oldPoint
+//                << " on face:" << oldFaceID << " of bb:" << bb << endl
+//                << "onto " << faceHitInfo.rawPoint()
+//                << " on face:" << faceID
+//                << " which is not consistent with geometric face "
+//                <<  bb.faceBits(faceHitInfo.rawPoint())
+//                << abort(FatalError);
+//        }
+//    }
+//}
+
+
+// Get parent node and octant. Return false if top of tree reached.
+template <class Type>
+bool Foam::dynamicIndexedOctree<Type>::walkToParent
+(
+    const label nodeI,
+    const direction octant,
+
+    label& parentNodeI,
+    label& parentOctant
+) const
+{
+    parentNodeI = nodes_[nodeI].parent_;
+
+    if (parentNodeI == -1)
+    {
+        // Reached edge of tree
+        return false;
+    }
+
+    const node& parentNode = nodes_[parentNodeI];
+
+    // Find octant nodeI is in.
+    parentOctant = 255;
+
+    for (direction i = 0; i < parentNode.subNodes_.size(); i++)
+    {
+        labelBits index = parentNode.subNodes_[i];
+
+        if (isNode(index) && getNode(index) == nodeI)
+        {
+            parentOctant = i;
+            break;
+        }
+    }
+
+    if (parentOctant == 255)
+    {
+        FatalErrorIn("walkToParent(..)")
+            << "Problem: no parent found for octant:" << octant
+            << " node:" << nodeI
+            << abort(FatalError);
+    }
+
+    return true;
+}
+
+
+// Walk tree to neighbouring node. Gets current position as
+// node and octant in this node and walks in the direction given by
+// the facePointBits (combination of treeBoundBox::LEFTBIT, TOPBIT etc.)
+// Returns false if edge of tree hit.
+template <class Type>
+bool Foam::dynamicIndexedOctree<Type>::walkToNeighbour
+(
+    const point& facePoint,
+    const direction faceID,  // face(s) that facePoint is on
+    label& nodeI,
+    direction& octant
+) const
+{
+    label oldNodeI = nodeI;
+    direction oldOctant = octant;
+
+    // Find out how to test for octant. Say if we want to go left we need
+    // to traverse up the tree until we hit a node where our octant is
+    // on the right.
+
+    // Coordinate direction to test
+    const direction X = treeBoundBox::RIGHTHALF;
+    const direction Y = treeBoundBox::TOPHALF;
+    const direction Z = treeBoundBox::FRONTHALF;
+
+    direction octantMask = 0;
+    direction wantedValue = 0;
+
+    if ((faceID & treeBoundBox::LEFTBIT) != 0)
+    {
+        // We want to go left so check if in right octant (i.e. x-bit is set)
+        octantMask |= X;
+        wantedValue |= X;
+    }
+    else if ((faceID & treeBoundBox::RIGHTBIT) != 0)
+    {
+        octantMask |= X;  // wantedValue already 0
+    }
+
+    if ((faceID & treeBoundBox::BOTTOMBIT) != 0)
+    {
+        // Want to go down so check for y-bit set.
+        octantMask |= Y;
+        wantedValue |= Y;
+    }
+    else if ((faceID & treeBoundBox::TOPBIT) != 0)
+    {
+        // Want to go up so check for y-bit not set.
+        octantMask |= Y;
+    }
+
+    if ((faceID & treeBoundBox::BACKBIT) != 0)
+    {
+        octantMask |= Z;
+        wantedValue |= Z;
+    }
+    else if ((faceID & treeBoundBox::FRONTBIT) != 0)
+    {
+        octantMask |= Z;
+    }
+
+    // So now we have the coordinate directions in the octant we need to check
+    // and the resulting value.
+
+    /*
+    // +---+---+
+    // |   |   |
+    // |   |   |
+    // |   |   |
+    // +---+-+-+
+    // |   | | |
+    // |  a+-+-+
+    // |   |\| |
+    // +---+-+-+
+    //        \
+    //
+    // e.g. ray is at (a) in octant 0(or 4) with faceIDs : LEFTBIT+TOPBIT.
+    // If we would be in octant 1(or 5) we could go to the correct octant
+    // in the same node by just flipping the x and y bits (exoring).
+    // But if we are not in octant 1/5 we have to go up until we are.
+    // In general for leftbit+topbit:
+    // - we have to check for x and y : octantMask  = 011
+    // - the checked bits have to be  : wantedValue = ?01
+    */
+
+    //Pout<< "For point " << facePoint << endl;
+
+    // Go up until we have chance to cross to the wanted direction
+    while (wantedValue != (octant & octantMask))
+    {
+        // Go up to the parent.
+
+        // Remove the directions that are not on the boundary of the parent.
+        // See diagram above
+        if (wantedValue & X)    // && octantMask&X
+        {
+            // Looking for right octant.
+            if (octant & X)
+            {
+                // My octant is one of the left ones so punch out the x check
+                octantMask &= ~X;
+                wantedValue &= ~X;
+            }
+        }
+        else
+        {
+            if (!(octant & X))
+            {
+                // My octant is right but I want to go left.
+                octantMask &= ~X;
+                wantedValue &= ~X;
+            }
+        }
+
+        if (wantedValue & Y)
+        {
+            if (octant & Y)
+            {
+                octantMask &= ~Y;
+                wantedValue &= ~Y;
+            }
+        }
+        else
+        {
+            if (!(octant & Y))
+            {
+                octantMask &= ~Y;
+                wantedValue &= ~Y;
+            }
+        }
+
+        if (wantedValue & Z)
+        {
+            if (octant & Z)
+            {
+                octantMask &= ~Z;
+                wantedValue &= ~Z;
+            }
+        }
+        else
+        {
+            if (!(octant & Z))
+            {
+                octantMask &= ~Z;
+                wantedValue &= ~Z;
+            }
+        }
+
+
+        label parentNodeI;
+        label parentOctant;
+        walkToParent(nodeI, octant, parentNodeI, parentOctant);
+
+        if (parentNodeI == -1)
+        {
+            // Reached edge of tree
+            return false;
+        }
+
+        //Pout<< "    walked from node:" << nodeI << " octant:" << octant
+        //    << " bb:" << nodes_[nodeI].bb_.subBbox(octant) << endl
+        //    << "    to:" << parentNodeI << " octant:" << parentOctant
+        //    << " bb:" << nodes_[parentNodeI].bb_.subBbox(parentOctant)
+        //    << endl;
+        //
+        //Pout<< "    octantMask:" << octantMask
+        //    << " wantedValue:" << wantedValue << endl;
+
+        nodeI = parentNodeI;
+        octant = parentOctant;
+    }
+
+    // So now we hit the correct parent node. Switch to the correct octant.
+    // Is done by jumping to the 'other half' so if e.g. in x direction in
+    // right half we now jump to the left half.
+    octant ^= octantMask;
+
+    //Pout<< "    to node:" << nodeI << " octant:" << octant
+    //    << " subBb:" <<subBbox(nodeI, octant) << endl;
+
+
+    if (debug)
+    {
+        const treeBoundBox subBb(subBbox(nodeI, octant));
+
+        if (!subBb.contains(facePoint))
+        {
+            FatalErrorIn("dynamicIndexedOctree<Type>::walkToNeighbour(..)")
+                << "When searching for " << facePoint
+                << " ended up in node:" << nodeI
+                << " octant:" << octant
+                << " with bb:" << subBb
+                << abort(FatalError);
+        }
+    }
+
+
+    // See if we need to travel down. Note that we already go into the
+    // the first level ourselves (instead of having findNode decide)
+    labelBits index = nodes_[nodeI].subNodes_[octant];
+
+    if (isNode(index))
+    {
+        labelBits node = findNode(getNode(index), facePoint);
+
+        nodeI = getNode(node);
+        octant = getOctant(node);
+    }
+
+
+    if (debug)
+    {
+        const treeBoundBox subBb(subBbox(nodeI, octant));
+
+        if (nodeI == oldNodeI && octant == oldOctant)
+        {
+            FatalErrorIn("dynamicIndexedOctree<Type>::walkToNeighbour(..)")
+                << "Did not go to neighbour when searching for " << facePoint
+                << endl
+                << "    starting from face:" << faceString(faceID)
+                << " node:" << nodeI
+                << " octant:" << octant
+                << " bb:" << subBb
+                << abort(FatalError);
+        }
+
+        if (!subBb.contains(facePoint))
+        {
+            FatalErrorIn("dynamicIndexedOctree<Type>::walkToNeighbour(..)")
+                << "When searching for " << facePoint
+                << " ended up in node:" << nodeI
+                << " octant:" << octant
+                << " bb:" << subBb
+                << abort(FatalError);
+        }
+    }
+
+
+    return true;
+}
+
+
+template <class Type>
+Foam::word Foam::dynamicIndexedOctree<Type>::faceString
+(
+    const direction faceID
+)
+{
+    word desc;
+
+    if (faceID == 0)
+    {
+        desc = "noFace";
+    }
+    if (faceID & treeBoundBox::LEFTBIT)
+    {
+        if (!desc.empty()) desc += "+";
+        desc += "left";
+    }
+    if (faceID & treeBoundBox::RIGHTBIT)
+    {
+        if (!desc.empty()) desc += "+";
+        desc += "right";
+    }
+    if (faceID & treeBoundBox::BOTTOMBIT)
+    {
+        if (!desc.empty()) desc += "+";
+        desc += "bottom";
+    }
+    if (faceID & treeBoundBox::TOPBIT)
+    {
+        if (!desc.empty()) desc += "+";
+        desc += "top";
+    }
+    if (faceID & treeBoundBox::BACKBIT)
+    {
+        if (!desc.empty()) desc += "+";
+        desc += "back";
+    }
+    if (faceID & treeBoundBox::FRONTBIT)
+    {
+        if (!desc.empty()) desc += "+";
+        desc += "front";
+    }
+    return desc;
+}
+
+
+// Traverse a node. If intersects a triangle return first intersection point:
+//  hitInfo.index = index of shape
+//  hitInfo.point = point on shape
+// Else return a miss and the bounding box face hit:
+//  hitInfo.point = coordinate of intersection of ray with bounding box
+//  hitBits  = posbits of point on bounding box
+template <class Type>
+void Foam::dynamicIndexedOctree<Type>::traverseNode
+(
+    const bool findAny,
+    const point& treeStart,
+    const vector& treeVec,
+
+    const point& start,
+    const point& end,
+    const label nodeI,
+    const direction octant,
+
+    pointIndexHit& hitInfo,
+    direction& hitBits
+) const
+{
+    if (debug)
+    {
+        const treeBoundBox octantBb(subBbox(nodeI, octant));
+
+        if (octantBb.posBits(start) != 0)
+        {
+            FatalErrorIn("dynamicIndexedOctree<Type>::traverseNode(..)")
+                << "Node:" << nodeI << " octant:" << octant
+                << " bb:" << octantBb << endl
+                << "does not contain point " << start << abort(FatalError);
+        }
+    }
+
+
+    const node& nod = nodes_[nodeI];
+
+    labelBits index = nod.subNodes_[octant];
+
+    if (isContent(index))
+    {
+        const labelList& indices = contents_[getContent(index)];
+
+        if (indices.size())
+        {
+            if (findAny)
+            {
+                // Find any intersection
+
+                forAll(indices, elemI)
+                {
+                    label shapeI = indices[elemI];
+
+                    point pt;
+                    bool hit = shapes_.intersects(shapeI, start, end, pt);
+
+                    // Note that intersection of shape might actually be
+                    // in a neighbouring box. For findAny this is not important.
+                    if (hit)
+                    {
+                        // Hit so pt is nearer than nearestPoint.
+                        // Update hit info
+                        hitInfo.setHit();
+                        hitInfo.setIndex(shapeI);
+                        hitInfo.setPoint(pt);
+                        return;
+                    }
+                }
+            }
+            else
+            {
+                // Find nearest intersection
+
+                const treeBoundBox octantBb(subBbox(nodeI, octant));
+
+                point nearestPoint(end);
+
+                forAll(indices, elemI)
+                {
+                    label shapeI = indices[elemI];
+
+                    point pt;
+                    bool hit = shapes_.intersects
+                    (
+                        shapeI,
+                        start,
+                        nearestPoint,
+                        pt
+                    );
+
+                    // Note that intersection of shape might actually be
+                    // in a neighbouring box. Since we need to maintain strict
+                    // (findAny=false) ordering skip such an intersection. It
+                    // will be found when we are doing the next box.
+
+                    if (hit && octantBb.contains(pt))
+                    {
+                        // Hit so pt is nearer than nearestPoint.
+                        nearestPoint = pt;
+                        // Update hit info
+                        hitInfo.setHit();
+                        hitInfo.setIndex(shapeI);
+                        hitInfo.setPoint(pt);
+                    }
+                }
+
+                if (hitInfo.hit())
+                {
+                    // Found intersected shape.
+                    return;
+                }
+            }
+        }
+    }
+
+    // Nothing intersected in this node
+    // Traverse to end of node. Do by ray tracing back from end and finding
+    // intersection with bounding box of node.
+    // start point is now considered to be inside bounding box.
+
+    const treeBoundBox octantBb(subBbox(nodeI, octant));
+
+    point pt;
+    bool intersected = octantBb.intersects
+    (
+        end,            //treeStart,
+        (start-end),    //treeVec,
+
+        end,
+        start,
+
+        pt,
+        hitBits
+    );
+
+
+    if (intersected)
+    {
+        // Return miss. Set misspoint to face.
+        hitInfo.setPoint(pt);
+    }
+    else
+    {
+        // Rare case: did not find intersection of ray with octantBb. Can
+        // happen if end is on face/edge of octantBb. Do like
+        // lagrangian and re-track with perturbed vector (slightly pushed out
+        // of bounding box)
+
+        point perturbedEnd(pushPoint(octantBb, end, false));
+
+        traverseNode
+        (
+            findAny,
+            treeStart,
+            treeVec,
+            start,
+            perturbedEnd,
+            nodeI,
+            octant,
+
+            hitInfo,
+            hitBits
+        );
+    }
+}
+
+
+// Find first intersection
+template <class Type>
+Foam::pointIndexHit Foam::dynamicIndexedOctree<Type>::findLine
+(
+    const bool findAny,
+    const point& treeStart,
+    const point& treeEnd,
+    const label startNodeI,
+    const direction startOctant,
+    const bool verbose
+) const
+{
+    const vector treeVec(treeEnd - treeStart);
+
+    // Current node as parent+octant
+    label nodeI = startNodeI;
+    direction octant = startOctant;
+
+    if (verbose)
+    {
+        Pout<< "findLine : treeStart:" << treeStart
+            << " treeEnd:" << treeEnd << endl
+            << "node:" << nodeI
+            << " octant:" << octant
+            << " bb:" << subBbox(nodeI, octant) << endl;
+    }
+
+    // Current position. Initialize to miss
+    pointIndexHit hitInfo(false, treeStart, -1);
+
+    //while (true)
+    label i = 0;
+    for (; i < 100000; i++)
+    {
+        // Ray-trace to end of current node. Updates point (either on triangle
+        // in case of hit or on node bounding box in case of miss)
+
+        const treeBoundBox octantBb(subBbox(nodeI, octant));
+
+        // Make sure point is away from any edges/corners
+        point startPoint
+        (
+            pushPointIntoFace
+            (
+                octantBb,
+                treeVec,
+                hitInfo.rawPoint()
+            )
+        );
+
+        if (verbose)
+        {
+            Pout<< "iter:" << i
+                << " at current:" << hitInfo.rawPoint()
+                << " (perturbed:" << startPoint << ")" << endl
+                << "    node:" << nodeI
+                << " octant:" << octant
+                << " bb:" << subBbox(nodeI, octant) << endl;
+        }
+
+
+
+
+        // Faces of current bounding box current point is on
+        direction hitFaceID = 0;
+
+        traverseNode
+        (
+            findAny,
+            treeStart,
+            treeVec,
+
+            startPoint,     // Note: pass in copy since hitInfo
+                            // also used in return value.
+            treeEnd,        // pass in overall end so is nicely outside bb
+            nodeI,
+            octant,
+
+            hitInfo,
+            hitFaceID
+        );
+
+        // Did we hit a triangle?
+        if (hitInfo.hit())
+        {
+            break;
+        }
+
+        if (hitFaceID == 0 || hitInfo.rawPoint() == treeEnd)
+        {
+            // endpoint inside the tree. Return miss.
+            break;
+        }
+
+        // Create a point on other side of face.
+        point perturbedPoint
+        (
+            pushPoint
+            (
+                octantBb,
+                hitFaceID,
+                hitInfo.rawPoint(),
+                false                   // push outside of octantBb
+            )
+        );
+
+        if (verbose)
+        {
+            Pout<< "    iter:" << i
+                << " hit face:" << faceString(hitFaceID)
+                << " at:" << hitInfo.rawPoint() << nl
+                << "    node:" << nodeI
+                << " octant:" << octant
+                << " bb:" << subBbox(nodeI, octant) << nl
+                << "    walking to neighbour containing:" << perturbedPoint
+                << endl;
+        }
+
+
+        // Nothing hit so we are on face of bounding box (given as node+octant+
+        // position bits). Traverse to neighbouring node. Use slightly perturbed
+        // point.
+
+        bool ok = walkToNeighbour
+        (
+            perturbedPoint,
+            hitFaceID,  // face(s) that hitInfo is on
+
+            nodeI,
+            octant
+        );
+
+        if (!ok)
+        {
+            // Hit the edge of the tree. Return miss.
+            break;
+        }
+
+        if (verbose)
+        {
+            const treeBoundBox octantBb(subBbox(nodeI, octant));
+            Pout<< "    walked for point:" << hitInfo.rawPoint() << endl
+                << "    to neighbour node:" << nodeI
+                << " octant:" << octant
+                << " face:" << faceString(octantBb.faceBits(hitInfo.rawPoint()))
+                << " of octantBb:" << octantBb << endl
+                << endl;
+        }
+    }
+
+    if (i == 100000)
+    {
+        // Probably in loop.
+        if (!verbose)
+        {
+            // Redo intersection but now with verbose flag switched on.
+            return findLine
+            (
+                findAny,
+                treeStart,
+                treeEnd,
+                startNodeI,
+                startOctant,
+                true            //verbose
+            );
+        }
+        if (debug)
+        {
+            FatalErrorIn("dynamicIndexedOctree<Type>::findLine(..)")
+                << "Got stuck in loop raytracing from:" << treeStart
+                << " to:" << treeEnd << endl
+                << "inside top box:" << subBbox(startNodeI, startOctant)
+                << abort(FatalError);
+        }
+        else
+        {
+            WarningIn("dynamicIndexedOctree<Type>::findLine(..)")
+                << "Got stuck in loop raytracing from:" << treeStart
+                << " to:" << treeEnd << endl
+                << "inside top box:" << subBbox(startNodeI, startOctant)
+                << endl;
+        }
+    }
+
+    return hitInfo;
+}
+
+
+// Find first intersection
+template <class Type>
+Foam::pointIndexHit Foam::dynamicIndexedOctree<Type>::findLine
+(
+    const bool findAny,
+    const point& start,
+    const point& end
+) const
+{
+    pointIndexHit hitInfo;
+
+    if (nodes_.size())
+    {
+        const treeBoundBox& treeBb = nodes_[0].bb_;
+
+        // No effort is made to deal with points which are on edge of tree
+        // bounding box for now.
+
+        direction startBit = treeBb.posBits(start);
+        direction endBit = treeBb.posBits(end);
+
+        if ((startBit & endBit) != 0)
+        {
+            // Both start and end outside domain and in same block.
+            return pointIndexHit(false, vector::zero, -1);
+        }
+
+
+        // Trim segment to treeBb
+
+        point trackStart(start);
+        point trackEnd(end);
+
+        if (startBit != 0)
+        {
+            // Track start to inside domain.
+            if (!treeBb.intersects(start, end, trackStart))
+            {
+                return pointIndexHit(false, vector::zero, -1);
+            }
+        }
+
+        if (endBit != 0)
+        {
+            // Track end to inside domain.
+            if (!treeBb.intersects(end, trackStart, trackEnd))
+            {
+                return pointIndexHit(false, vector::zero, -1);
+            }
+        }
+
+
+        // Find lowest level tree node that start is in.
+        labelBits index = findNode(0, trackStart);
+
+        label parentNodeI = getNode(index);
+        direction octant = getOctant(index);
+
+        hitInfo = findLine
+        (
+            findAny,
+            trackStart,
+            trackEnd,
+            parentNodeI,
+            octant
+        );
+    }
+
+    return hitInfo;
+}
+
+
+template <class Type>
+void Foam::dynamicIndexedOctree<Type>::findBox
+(
+    const label nodeI,
+    const treeBoundBox& searchBox,
+    labelHashSet& elements
+) const
+{
+    const node& nod = nodes_[nodeI];
+    const treeBoundBox& nodeBb = nod.bb_;
+
+    for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
+    {
+        labelBits index = nod.subNodes_[octant];
+
+        if (isNode(index))
+        {
+            const treeBoundBox& subBb = nodes_[getNode(index)].bb_;
+
+            if (subBb.overlaps(searchBox))
+            {
+                findBox(getNode(index), searchBox, elements);
+            }
+        }
+        else if (isContent(index))
+        {
+            const treeBoundBox subBb(nodeBb.subBbox(octant));
+
+            if (subBb.overlaps(searchBox))
+            {
+                const labelList& indices = contents_[getContent(index)];
+
+                forAll(indices, i)
+                {
+                    label shapeI = indices[i];
+
+                    if (shapes_.overlaps(shapeI, searchBox))
+                    {
+                        elements.insert(shapeI);
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+template <class Type>
+void Foam::dynamicIndexedOctree<Type>::findSphere
+(
+    const label nodeI,
+    const point& centre,
+    const scalar radiusSqr,
+    labelHashSet& elements
+) const
+{
+    const node& nod = nodes_[nodeI];
+    const treeBoundBox& nodeBb = nod.bb_;
+
+    for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
+    {
+        labelBits index = nod.subNodes_[octant];
+
+        if (isNode(index))
+        {
+            const treeBoundBox& subBb = nodes_[getNode(index)].bb_;
+
+            if (subBb.overlaps(centre, radiusSqr))
+            {
+                findSphere(getNode(index), centre, radiusSqr, elements);
+            }
+        }
+        else if (isContent(index))
+        {
+            const treeBoundBox subBb(nodeBb.subBbox(octant));
+
+            if (subBb.overlaps(centre, radiusSqr))
+            {
+                const labelList& indices = contents_[getContent(index)];
+
+                forAll(indices, i)
+                {
+                    label shapeI = indices[i];
+
+                    if (shapes_.overlaps(shapeI, centre, radiusSqr))
+                    {
+                        elements.insert(shapeI);
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+template <class Type>
+template <class CompareOp>
+void Foam::dynamicIndexedOctree<Type>::findNear
+(
+    const scalar nearDist,
+    const bool okOrder,
+    const dynamicIndexedOctree<Type>& tree1,
+    const labelBits index1,
+    const treeBoundBox& bb1,
+    const dynamicIndexedOctree<Type>& tree2,
+    const labelBits index2,
+    const treeBoundBox& bb2,
+    CompareOp& cop
+)
+{
+    const vector nearSpan(nearDist, nearDist, nearDist);
+
+    if (tree1.isNode(index1))
+    {
+        const node& nod1 = tree1.nodes()[tree1.getNode(index1)];
+        const treeBoundBox searchBox
+        (
+            bb1.min()-nearSpan,
+            bb1.max()+nearSpan
+        );
+
+        if (tree2.isNode(index2))
+        {
+            if (bb2.overlaps(searchBox))
+            {
+                const node& nod2 = tree2.nodes()[tree2.getNode(index2)];
+
+                for (direction i2 = 0; i2 < nod2.subNodes_.size(); i2++)
+                {
+                    labelBits subIndex2 = nod2.subNodes_[i2];
+                    const treeBoundBox subBb2
+                    (
+                        tree2.isNode(subIndex2)
+                      ? tree2.nodes()[tree2.getNode(subIndex2)].bb_
+                      : bb2.subBbox(i2)
+                    );
+
+                    findNear
+                    (
+                        nearDist,
+                        !okOrder,
+                        tree2,
+                        subIndex2,
+                        subBb2,
+                        tree1,
+                        index1,
+                        bb1,
+                        cop
+                    );
+                }
+            }
+        }
+        else if (tree2.isContent(index2))
+        {
+            // index2 is leaf, index1 not yet.
+            for (direction i1 = 0; i1 < nod1.subNodes_.size(); i1++)
+            {
+                labelBits subIndex1 = nod1.subNodes_[i1];
+                const treeBoundBox subBb1
+                (
+                    tree1.isNode(subIndex1)
+                  ? tree1.nodes()[tree1.getNode(subIndex1)].bb_
+                  : bb1.subBbox(i1)
+                );
+
+                findNear
+                (
+                    nearDist,
+                    !okOrder,
+                    tree2,
+                    index2,
+                    bb2,
+                    tree1,
+                    subIndex1,
+                    subBb1,
+                    cop
+                );
+            }
+        }
+    }
+    else if (tree1.isContent(index1))
+    {
+        const treeBoundBox searchBox
+        (
+            bb1.min()-nearSpan,
+            bb1.max()+nearSpan
+        );
+
+        if (tree2.isNode(index2))
+        {
+            const node& nod2 =
+                tree2.nodes()[tree2.getNode(index2)];
+
+            if (bb2.overlaps(searchBox))
+            {
+                for (direction i2 = 0; i2 < nod2.subNodes_.size(); i2++)
+                {
+                    labelBits subIndex2 = nod2.subNodes_[i2];
+                    const treeBoundBox subBb2
+                    (
+                        tree2.isNode(subIndex2)
+                      ? tree2.nodes()[tree2.getNode(subIndex2)].bb_
+                      : bb2.subBbox(i2)
+                    );
+
+                    findNear
+                    (
+                        nearDist,
+                        !okOrder,
+                        tree2,
+                        subIndex2,
+                        subBb2,
+                        tree1,
+                        index1,
+                        bb1,
+                        cop
+                    );
+                }
+            }
+        }
+        else if (tree2.isContent(index2))
+        {
+            // Both are leaves. Check n^2.
+
+            const labelList& indices1 =
+                tree1.contents()[tree1.getContent(index1)];
+            const labelList& indices2 =
+                tree2.contents()[tree2.getContent(index2)];
+
+            forAll(indices1, i)
+            {
+                label shape1 = indices1[i];
+
+                forAll(indices2, j)
+                {
+                    label shape2 = indices2[j];
+
+                    if ((&tree1 != &tree2) || (shape1 != shape2))
+                    {
+                        if (okOrder)
+                        {
+                            cop
+                            (
+                                nearDist,
+                                tree1.shapes(),
+                                shape1,
+                                tree2.shapes(),
+                                shape2
+                            );
+                        }
+                        else
+                        {
+                            cop
+                            (
+                                nearDist,
+                                tree2.shapes(),
+                                shape2,
+                                tree1.shapes(),
+                                shape1
+                            );
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+// Number of elements in node.
+template <class Type>
+Foam::label Foam::dynamicIndexedOctree<Type>::countElements
+(
+    const labelBits index
+) const
+{
+    label nElems = 0;
+
+    if (isNode(index))
+    {
+        // tree node.
+        label nodeI = getNode(index);
+
+        const node& nod = nodes_[nodeI];
+
+        for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
+        {
+            nElems += countElements(nod.subNodes_[octant]);
+        }
+    }
+    else if (isContent(index))
+    {
+        nElems += contents_[getContent(index)]().size();
+    }
+    else
+    {
+        // empty node
+    }
+
+    return nElems;
+}
+
+
+template <class Type>
+void Foam::dynamicIndexedOctree<Type>::writeOBJ
+(
+    const label nodeI,
+    const direction octant
+) const
+{
+    OFstream str
+    (
+        "node" + Foam::name(nodeI) + "_octant" + Foam::name(octant) + ".obj"
+    );
+
+    labelBits index = nodes_[nodeI].subNodes_[octant];
+
+    treeBoundBox subBb;
+
+    if (isNode(index))
+    {
+        subBb = nodes_[getNode(index)].bb_;
+    }
+    else if (isContent(index) || isEmpty(index))
+    {
+        subBb = nodes_[nodeI].bb_.subBbox(octant);
+    }
+
+    Pout<< "dumpContentNode : writing node:" << nodeI << " octant:" << octant
+        << " to " << str.name() << endl;
+
+    // Dump bounding box
+    pointField bbPoints(subBb.points());
+
+    forAll(bbPoints, i)
+    {
+        const point& pt = bbPoints[i];
+
+        str<< "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
+    }
+
+    forAll(treeBoundBox::edges, i)
+    {
+        const edge& e = treeBoundBox::edges[i];
+
+        str<< "l " << e[0] + 1 << ' ' << e[1] + 1 << nl;
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+template <class Type>
+Foam::dynamicIndexedOctree<Type>::dynamicIndexedOctree
+(
+    const Type& shapes,
+    const treeBoundBox& bb,
+    const label maxLevels,          // maximum number of levels
+    const scalar maxLeafRatio,
+    const scalar maxDuplicity
+)
+:
+    shapes_(shapes),
+    bb_(bb),
+    maxLevels_(maxLevels),
+    nLevelsMax_(0),
+    maxLeafRatio_(maxLeafRatio),
+    minSize_(label(maxLeafRatio)),
+    maxDuplicity_(maxDuplicity),
+    nodes_(label(shapes.size() / maxLeafRatio_)),
+    contents_(label(shapes.size() / maxLeafRatio_)),
+    nodeTypes_(0)
+{
+    if (shapes_.size() == 0)
+    {
+        return;
+    }
+
+    insert(0, shapes_.size());
+
+    if (debug)
+    {
+        writeTreeInfo();
+    }
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template <class Type>
+Foam::scalar& Foam::dynamicIndexedOctree<Type>::perturbTol()
+{
+    return perturbTol_;
+}
+
+
+template <class Type>
+Foam::pointIndexHit Foam::dynamicIndexedOctree<Type>::findNearest
+(
+    const point& sample,
+    const scalar startDistSqr
+) const
+{
+    scalar nearestDistSqr = startDistSqr;
+    label nearestShapeI = -1;
+    point nearestPoint = vector::zero;
+
+    if (nodes_.size())
+    {
+        findNearest
+        (
+            0,
+            sample,
+
+            nearestDistSqr,
+            nearestShapeI,
+            nearestPoint
+        );
+    }
+
+    return pointIndexHit(nearestShapeI != -1, nearestPoint, nearestShapeI);
+}
+
+
+template <class Type>
+Foam::pointIndexHit Foam::dynamicIndexedOctree<Type>::findNearest
+(
+    const linePointRef& ln,
+    treeBoundBox& tightest,
+    point& linePoint
+) const
+{
+    label nearestShapeI = -1;
+    point nearestPoint;
+
+    if (nodes_.size())
+    {
+        findNearest
+        (
+            0,
+            ln,
+
+            tightest,
+            nearestShapeI,
+            linePoint,
+            nearestPoint
+        );
+    }
+    else
+    {
+        nearestPoint = vector::zero;
+    }
+
+    return pointIndexHit(nearestShapeI != -1, nearestPoint, nearestShapeI);
+}
+
+
+// Find nearest intersection
+template <class Type>
+Foam::pointIndexHit Foam::dynamicIndexedOctree<Type>::findLine
+(
+    const point& start,
+    const point& end
+) const
+{
+    return findLine(false, start, end);
+}
+
+
+// Find nearest intersection
+template <class Type>
+Foam::pointIndexHit Foam::dynamicIndexedOctree<Type>::findLineAny
+(
+    const point& start,
+    const point& end
+) const
+{
+    return findLine(true, start, end);
+}
+
+
+template <class Type>
+Foam::labelList Foam::dynamicIndexedOctree<Type>::findBox
+(
+    const treeBoundBox& searchBox
+) const
+{
+    // Storage for labels of shapes inside bb. Size estimate.
+    labelHashSet elements(shapes_.size() / 100);
+
+    if (nodes_.size())
+    {
+        findBox(0, searchBox, elements);
+    }
+
+    return elements.toc();
+}
+
+
+template <class Type>
+Foam::labelList Foam::dynamicIndexedOctree<Type>::findSphere
+(
+    const point& centre,
+    const scalar radiusSqr
+) const
+{
+    // Storage for labels of shapes inside bb. Size estimate.
+    labelHashSet elements(shapes_.size() / 100);
+
+    if (nodes_.size())
+    {
+        findSphere(0, centre, radiusSqr, elements);
+    }
+
+    return elements.toc();
+}
+
+
+// Find node (as parent+octant) containing point
+template <class Type>
+Foam::labelBits Foam::dynamicIndexedOctree<Type>::findNode
+(
+    const label nodeI,
+    const point& sample
+) const
+{
+    if (nodes_.empty())
+    {
+        // Empty tree. Return what?
+        return nodePlusOctant(nodeI, 0);
+    }
+
+    const node& nod = nodes_[nodeI];
+
+    if (debug)
+    {
+        if (!nod.bb_.contains(sample))
+        {
+            FatalErrorIn("findNode(..)")
+                << "Cannot find " << sample << " in node " << nodeI
+                << abort(FatalError);
+        }
+    }
+
+    direction octant = nod.bb_.subOctant(sample);
+
+    labelBits index = nod.subNodes_[octant];
+
+    if (isNode(index))
+    {
+        // Recurse
+        return findNode(getNode(index), sample);
+    }
+    else if (isContent(index))
+    {
+        // Content. Return treenode+octant
+        return nodePlusOctant(nodeI, octant);
+    }
+    else
+    {
+        // Empty. Return treenode+octant
+        return nodePlusOctant(nodeI, octant);
+    }
+}
+
+
+template <class Type>
+Foam::label Foam::dynamicIndexedOctree<Type>::findInside(const point& sample) const
+{
+    labelBits index = findNode(0, sample);
+
+    const node& nod = nodes_[getNode(index)];
+
+    labelBits contentIndex = nod.subNodes_[getOctant(index)];
+
+    // Need to check for the presence of content, in-case the node is empty
+    if (isContent(contentIndex))
+    {
+        labelList indices = contents_[getContent(contentIndex)];
+
+        forAll(indices, elemI)
+        {
+            label shapeI = indices[elemI];
+
+            if (shapes_.contains(shapeI, sample))
+            {
+                return shapeI;
+            }
+        }
+    }
+
+    return -1;
+}
+
+
+template <class Type>
+const Foam::labelList& Foam::dynamicIndexedOctree<Type>::findIndices
+(
+    const point& sample
+) const
+{
+    labelBits index = findNode(0, sample);
+
+    const node& nod = nodes_[getNode(index)];
+
+    labelBits contentIndex = nod.subNodes_[getOctant(index)];
+
+    // Need to check for the presence of content, in-case the node is empty
+    if (isContent(contentIndex))
+    {
+        return contents_[getContent(contentIndex)];
+    }
+    else
+    {
+        return emptyList<label>();
+    }
+}
+
+
+// Determine type (inside/outside/mixed) per node.
+template <class Type>
+typename Foam::dynamicIndexedOctree<Type>::volumeType
+Foam::dynamicIndexedOctree<Type>::getVolumeType
+(
+    const point& sample
+) const
+{
+    if (nodes_.empty())
+    {
+        return UNKNOWN;
+    }
+
+    if (nodeTypes_.size() != 8*nodes_.size())
+    {
+        // Calculate type for every octant of node.
+
+        nodeTypes_.setSize(8*nodes_.size());
+        nodeTypes_ = UNKNOWN;
+
+        calcVolumeType(0);
+
+        if (debug)
+        {
+            label nUNKNOWN = 0;
+            label nMIXED = 0;
+            label nINSIDE = 0;
+            label nOUTSIDE = 0;
+
+            forAll(nodeTypes_, i)
+            {
+                volumeType type = volumeType(nodeTypes_.get(i));
+
+                if (type == UNKNOWN)
+                {
+                    nUNKNOWN++;
+                }
+                else if (type == MIXED)
+                {
+                    nMIXED++;
+                }
+                else if (type == INSIDE)
+                {
+                    nINSIDE++;
+                }
+                else if (type == OUTSIDE)
+                {
+                    nOUTSIDE++;
+                }
+                else
+                {
+                    FatalErrorIn("getVolumeType") << abort(FatalError);
+                }
+            }
+
+            Pout<< "dynamicIndexedOctree<Type>::getVolumeType : "
+                << " bb:" << bb()
+                << " nodes_:" << nodes_.size()
+                << " nodeTypes_:" << nodeTypes_.size()
+                << " nUNKNOWN:" << nUNKNOWN
+                << " nMIXED:" << nMIXED
+                << " nINSIDE:" << nINSIDE
+                << " nOUTSIDE:" << nOUTSIDE
+                << endl;
+        }
+    }
+
+    return getVolumeType(0, sample);
+}
+
+
+template <class Type>
+template <class CompareOp>
+void Foam::dynamicIndexedOctree<Type>::findNear
+(
+    const scalar nearDist,
+    const dynamicIndexedOctree<Type>& tree2,
+    CompareOp& cop
+) const
+{
+    findNear
+    (
+        nearDist,
+        true,
+        *this,
+        nodePlusOctant(0, 0),
+        bb(),
+        tree2,
+        nodePlusOctant(0, 0),
+        tree2.bb(),
+        cop
+    );
+}
+
+
+template <class Type>
+bool Foam::dynamicIndexedOctree<Type>::insert(label startIndex, label endIndex)
+{
+    if (startIndex == endIndex)
+    {
+        return false;
+    }
+
+    if (nodes_.empty())
+    {
+        contents_.append
+        (
+            autoPtr<DynamicList<label> >
+            (
+                new DynamicList<label>(1)
+            )
+        );
+
+        contents_[0]().append(0);
+
+        // Create topnode.
+        node topNode = divide(bb_, 0, -1, 0);
+
+        nodes_.append(topNode);
+
+        startIndex++;
+    }
+
+    bool success = true;
+
+    for (label pI = startIndex; pI < endIndex; ++pI)
+    {
+        label nLevels = 1;
+
+        if (!insertIndex(0, pI, nLevels))
+        {
+            success = false;
+        }
+
+        nLevelsMax_ = max(nLevels, nLevelsMax_);
+    }
+
+    return success;
+}
+
+
+template <class Type>
+bool Foam::dynamicIndexedOctree<Type>::insertIndex
+(
+    const label nodIndex,
+    const label index,
+    label& nLevels
+)
+{
+    bool shapeInserted = false;
+
+    for (direction octant = 0; octant < 8; octant++)
+    {
+        const labelBits& subNodeLabel = nodes_[nodIndex].subNodes_[octant];
+
+        if (isNode(subNodeLabel))
+        {
+            const treeBoundBox& subBb = nodes_[getNode(subNodeLabel)].bb_;
+
+            if (shapes().overlaps(index, subBb))
+            {
+                nLevels++;
+
+                if (insertIndex(getNode(subNodeLabel), index, nLevels))
+                {
+                    shapeInserted = true;
+                }
+            }
+        }
+        else if (isContent(subNodeLabel))
+        {
+            const treeBoundBox subBb = nodes_[nodIndex].bb_.subBbox(octant);
+
+            if (shapes().overlaps(index, subBb))
+            {
+                const label contentI = getContent(subNodeLabel);
+
+                contents_[contentI]().append(index);
+
+                recursiveSubDivision
+                (
+                    subBb,
+                    contentI,
+                    nodIndex,
+                    octant,
+                    nLevels
+                );
+
+                shapeInserted = true;
+            }
+        }
+        else
+        {
+            const treeBoundBox subBb = nodes_[nodIndex].bb_.subBbox(octant);
+
+            if (shapes().overlaps(index, subBb))
+            {
+                label sz = contents_.size();
+
+                contents_.append
+                (
+                    autoPtr<DynamicList<label> >(new DynamicList<label>(1))
+                );
+
+                contents_[sz]().append(index);
+
+                nodes_[nodIndex].subNodes_[octant]
+                    = contentPlusOctant(sz, octant);
+            }
+
+            shapeInserted = true;
+        }
+    }
+
+    return shapeInserted;
+}
+
+
+template <class Type>
+bool Foam::dynamicIndexedOctree<Type>::remove(const label index)
+{
+    if (nodes_.empty())
+    {
+        return false;
+    }
+
+    removeIndex(0, index);
+
+    return true;
+}
+
+
+template <class Type>
+Foam::label Foam::dynamicIndexedOctree<Type>::removeIndex
+(
+    const label nodIndex,
+    const label index
+)
+{
+    label totalContents = 0;
+
+    for (direction octant = 0; octant < 8; octant++)
+    {
+        const labelBits& subNodeLabel = nodes_[nodIndex].subNodes_[octant];
+
+        if (isNode(subNodeLabel))
+        {
+            const treeBoundBox& subBb = nodes_[getNode(subNodeLabel)].bb_;
+
+            if (shapes().overlaps(index, subBb))
+            {
+                // Recursive function.
+                label childContentsSize
+                    = removeIndex(getNode(subNodeLabel), index);
+
+                totalContents += childContentsSize;
+
+                if (childContentsSize == 0)
+                {
+                    nodes_[nodIndex].subNodes_[octant]
+                        = emptyPlusOctant(octant);
+                }
+            }
+            else
+            {
+                // Increment this so that the node will not be marked as empty
+                totalContents++;
+            }
+        }
+        else if (isContent(subNodeLabel))
+        {
+            const treeBoundBox subBb = nodes_[nodIndex].bb_.subBbox(octant);
+
+            const label contentI = getContent(subNodeLabel);
+
+            if (shapes().overlaps(index, subBb))
+            {
+                DynamicList<label>& contentList = contents_[contentI]();
+
+                DynamicList<label> newContent(contentList.size());
+
+                forAll(contentList, pI)
+                {
+                    const label oldIndex = contentList[pI];
+
+                    if (oldIndex != index)
+                    {
+                        newContent.append(oldIndex);
+                    }
+                }
+
+                newContent.shrink();
+
+                if (newContent.size() == 0)
+                {
+                    // Set to empty.
+                    nodes_[nodIndex].subNodes_[octant] = emptyPlusOctant(octant);
+                }
+
+                contentList.transfer(newContent);
+            }
+
+            totalContents += contents_[contentI]().size();
+        }
+        else
+        {
+            // Empty, do nothing.
+        }
+    }
+
+    return totalContents;
+}
+
+
+// Print contents of nodeI
+template <class Type>
+void Foam::dynamicIndexedOctree<Type>::print
+(
+    prefixOSstream& os,
+    const bool printContents,
+    const label nodeI
+) const
+{
+    const node& nod = nodes_[nodeI];
+    const treeBoundBox& bb = nod.bb_;
+
+    os  << "nodeI:" << nodeI << " bb:" << bb << nl
+        << "parent:" << nod.parent_ << nl
+        << "n:" << countElements(nodePlusOctant(nodeI, 0)) << nl;
+
+    for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
+    {
+        const treeBoundBox subBb(bb.subBbox(octant));
+
+        labelBits index = nod.subNodes_[octant];
+
+        if (isNode(index))
+        {
+            // tree node.
+            label subNodeI = getNode(index);
+
+            os  << "octant:" << octant
+                << " node: n:" << countElements(index)
+                << " bb:" << subBb << endl;
+
+            string oldPrefix = os.prefix();
+            os.prefix() = "  " + oldPrefix;
+
+            print(os, printContents, subNodeI);
+
+            os.prefix() = oldPrefix;
+        }
+        else if (isContent(index))
+        {
+            const labelList& indices = contents_[getContent(index)];
+
+            if (false) //debug)
+            {
+                writeOBJ(nodeI, octant);
+            }
+
+            os  << "octant:" << octant
+                << " content: n:" << indices.size()
+                << " bb:" << subBb;
+
+            if (printContents)
+            {
+                os << " contents:";
+                forAll(indices, j)
+                {
+                    os  << ' ' << indices[j];
+                }
+            }
+            os  << endl;
+        }
+        else
+        {
+            if (false) //debug)
+            {
+                writeOBJ(nodeI, octant);
+            }
+
+            os  << "octant:" << octant << " empty:" << subBb << endl;
+        }
+    }
+}
+
+
+template <class Type>
+void Foam::dynamicIndexedOctree<Type>::writeTreeInfo() const
+{
+    label nEntries = 0;
+    forAll(contents_, i)
+    {
+        nEntries += contents_[i]().size();
+    }
+
+    Pout<< "indexedOctree<Type>::indexedOctree"
+        << " : finished construction of tree of:" << shapes().typeName
+        << nl
+        << "    bounding box:     " << this->bb() << nl
+        << "    shapes:           " << shapes().size() << nl
+        << "    treeNodes:        " << nodes_.size() << nl
+        << "    nEntries:         " << nEntries << nl
+        << "    levels/maxLevels: " << nLevelsMax_ << "/" << maxLevels_ << nl
+        << "    minSize:          " << minSize_ << nl
+        << "        per treeLeaf:         "
+        << scalar(nEntries)/contents_.size() << nl
+        << "        per shape (duplicity):"
+        << scalar(nEntries)/shapes().size() << nl
+        << endl;
+}
+
+
+// Print contents of nodeI
+template <class Type>
+bool Foam::dynamicIndexedOctree<Type>::write(Ostream& os) const
+{
+    os << *this;
+
+    return os.good();
+}
+
+
+template <class Type>
+Foam::Ostream& Foam::operator<<(Ostream& os, const dynamicIndexedOctree<Type>& t)
+{
+    os  << t.bb() << token::SPACE << t.nodes() << endl;
+
+    forAll(t.contents(), cI)
+    {
+        os << t.contents()[cI]() << endl;
+    }
+
+    return os;
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/algorithms/dynamicIndexedOctree/dynamicIndexedOctree.H b/src/OpenFOAM/algorithms/dynamicIndexedOctree/dynamicIndexedOctree.H
new file mode 100644
index 0000000000000000000000000000000000000000..a50d5e3995e295819fd06a0563d24f88ac65d00b
--- /dev/null
+++ b/src/OpenFOAM/algorithms/dynamicIndexedOctree/dynamicIndexedOctree.H
@@ -0,0 +1,698 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::dynamicIndexedOctree
+
+Description
+    Non-pointer based hierarchical recursive searching
+
+SourceFiles
+    dynamicIndexedOctree.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef dynamicIndexedOctree_H
+#define dynamicIndexedOctree_H
+
+#include "treeBoundBox.H"
+#include "pointIndexHit.H"
+#include "FixedList.H"
+#include "Ostream.H"
+#include "HashSet.H"
+#include "labelBits.H"
+#include "PackedList.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+typedef DynamicList<autoPtr<DynamicList<label > > > contentListList;
+
+// Forward declaration of classes
+template<class Type> class dynamicIndexedOctree;
+
+template<class Type> Ostream& operator<<
+(
+    Ostream&,
+    const dynamicIndexedOctree<Type>&
+);
+
+class Istream;
+
+
+/*---------------------------------------------------------------------------*\
+                        Class dynamicIndexedOctreeName Declaration
+\*---------------------------------------------------------------------------*/
+
+TemplateName(dynamicIndexedOctree);
+
+
+/*---------------------------------------------------------------------------*\
+                           Class dynamicIndexedOctree Declaration
+\*---------------------------------------------------------------------------*/
+
+template <class Type>
+class dynamicIndexedOctree
+:
+    public dynamicIndexedOctreeName
+{
+public:
+
+    // Data types
+
+        //- volume types
+        enum volumeType
+        {
+            UNKNOWN = 0,
+            MIXED = 1,
+            INSIDE = 2,
+            OUTSIDE = 3
+        };
+
+
+        //- Tree node. Has up pointer and down pointers.
+        class node
+        {
+        public:
+
+            //- Bounding box of this node
+            treeBoundBox bb_;
+
+            //- parent node (index into nodes_ of tree)
+            label parent_;
+
+            //- IDs of the 8 nodes on all sides of the mid point
+            FixedList<labelBits, 8> subNodes_;
+
+            friend Ostream& operator<< (Ostream& os, const node& n)
+            {
+                return os << n.bb_ << token::SPACE
+                    << n.parent_ << token::SPACE << n.subNodes_;
+            }
+
+            friend Istream& operator>> (Istream& is, node& n)
+            {
+                return is >> n.bb_ >> n.parent_ >> n.subNodes_;
+            }
+
+            friend bool operator==(const node& a, const node& b)
+            {
+                return
+                    a.bb_ == b.bb_
+                 && a.parent_ == b.parent_
+                 && a.subNodes_ == b.subNodes_;
+            }
+
+            friend bool operator!=(const node& a, const node& b)
+            {
+                return !(a == b);
+            }
+        };
+
+
+private:
+
+    // Static data
+
+        //- Relative peturbation tolerance. Determines when point is
+        //  considered to be close to face/edge of bb of node.
+        //  The tolerance is relative to the bounding box of the smallest
+        //  node.
+        static scalar perturbTol_;
+
+
+    // Private data
+
+        //- Underlying shapes for geometric queries.
+        const Type shapes_;
+
+        const treeBoundBox bb_;
+
+        const label maxLevels_;
+
+        //- Current number of levels in the tree.
+        label nLevelsMax_;
+
+        const scalar maxLeafRatio_;
+
+        const label minSize_;
+
+        const scalar maxDuplicity_;
+
+        //- List of all nodes
+        DynamicList<node> nodes_;
+
+        //- List of all contents (referenced by those nodes that are contents)
+        contentListList contents_;
+
+        //- Per node per octant whether is fully inside/outside/mixed.
+        mutable PackedList<2> nodeTypes_;
+
+    // Private Member Functions
+
+        //- Helper: does bb intersect a sphere around sample? Or is any
+        //  corner point of bb closer than nearestDistSqr to sample.
+        //  (bb is implicitly provided as parent bb + octant)
+        static bool overlaps
+        (
+            const treeBoundBox& parentBb,
+            const direction octant,
+            const scalar nearestDistSqr,
+            const point& sample
+        );
+
+        // Construction
+
+            //- Split list of indices into 8 bins
+            //  according to where they are in relation to mid.
+            void divide
+            (
+                const autoPtr<DynamicList<label> >& indices,
+                const treeBoundBox& bb,
+                contentListList& result
+            ) const;
+
+            //- Subdivide the contents node at position contentI.
+            //  Appends to contents.
+            node divide
+            (
+                const treeBoundBox& bb,
+                const label contentI,
+                const label parentNodeIndex,
+                const label octantToBeDivided
+            );
+
+            // Recursively call the divide function
+            void recursiveSubDivision
+            (
+                const treeBoundBox& subBb,
+                const label contentI,
+                const label parentIndex,
+                const label octant,
+                label& nLevels
+            );
+
+//            static label compactContents
+//            (
+//                DynamicList<node>& nodes,
+//                DynamicList<labelList>& contents,
+//                const label compactLevel,
+//                const label nodeI,
+//                const label level,
+//                List<labelList>& compactedContents,
+//                label& compactI
+//            );
+
+            //- Determine inside/outside per node (mixed if cannot be
+            //  determined). Only valid for closed shapes.
+            volumeType calcVolumeType(const label nodeI) const;
+
+            //- Search cached volume type.
+            volumeType getVolumeType(const label nodeI, const point&) const;
+
+
+        // Query
+
+            //- Find nearest point to line.
+            void findNearest
+            (
+                const label nodeI,
+                const linePointRef& ln,
+
+                treeBoundBox& tightest,
+                label& nearestShapeI,
+                point& linePoint,
+                point& nearestPoint
+            ) const;
+
+            //- Return bbox of octant
+            treeBoundBox subBbox
+            (
+                const label parentNodeI,
+                const direction octant
+            ) const;
+
+            //- Helper: take a point on/close to face of bb and push it
+            //  inside or outside of bb.
+            static point pushPoint
+            (
+                const treeBoundBox&,
+                const point&,
+                const bool pushInside
+            );
+
+            //- Helper: take a point on face of bb and push it
+            //  inside or outside of bb.
+            static point pushPoint
+            (
+                const treeBoundBox&,
+                const direction,
+                const point&,
+                const bool pushInside
+            );
+
+            //- Helper: take point on face(s) of bb and push it away from
+            //  edges of face.
+            static point pushPointIntoFace
+            (
+                const treeBoundBox& bb,
+                const vector& dir,          // end-start
+                const point& pt
+            );
+
+            ////- Push point on multiple faces away from any corner/edge.
+            //static void checkMultipleFaces
+            //(
+            //    const treeBoundBox& bb,
+            //    const vector& dir,          // end-start
+            //    pointIndexHit& faceHitInfo,
+            //    direction& faceID
+            //);
+
+            //- Walk to parent of node+octant.
+            bool walkToParent
+            (
+                const label nodeI,
+                const direction octant,
+
+                label& parentNodeI,
+                label& parentOctant
+            ) const;
+
+            //- Walk tree to neighbouring node. Return false if edge of tree
+            //  hit.
+            bool walkToNeighbour
+            (
+                const point& facePoint,
+                const direction faceID,         // direction to walk in
+                label& nodeI,
+                direction& octant
+            ) const;
+
+            //- Debug: return verbose the bounding box faces
+            static word faceString(const direction faceID);
+
+            //- Traverse a node. If intersects a triangle return first
+            // intersection point.
+            // findAny=true : return any intersection
+            // findAny=false: return nearest (to start) intersection
+            void traverseNode
+            (
+                const bool findAny,
+                const point& treeStart,
+                const vector& treeVec,
+
+                const point& start,
+                const point& end,
+                const label nodeI,
+                const direction octantI,
+
+                pointIndexHit& hitInfo,
+                direction& faceID
+            ) const;
+
+            //- Find any or nearest intersection
+            pointIndexHit findLine
+            (
+                const bool findAny,
+                const point& treeStart,
+                const point& treeEnd,
+                const label startNodeI,
+                const direction startOctantI,
+                const bool verbose = false
+            ) const;
+
+            //- Find any or nearest intersection of line between start and end.
+            pointIndexHit findLine
+            (
+                const bool findAny,
+                const point& start,
+                const point& end
+            ) const;
+
+            //- Find all elements intersecting box.
+            void findBox
+            (
+                const label nodeI,
+                const treeBoundBox& searchBox,
+                labelHashSet& elements
+            ) const;
+
+
+            //- Find all elements intersecting sphere.
+            void findSphere
+            (
+                const label nodeI,
+                const point& centre,
+                const scalar radiusSqr,
+                labelHashSet& elements
+            ) const;
+
+
+            template <class CompareOp>
+            static void findNear
+            (
+                const scalar nearDist,
+                const bool okOrder,
+                const dynamicIndexedOctree<Type>& tree1,
+                const labelBits index1,
+                const treeBoundBox& bb1,
+                const dynamicIndexedOctree<Type>& tree2,
+                const labelBits index2,
+                const treeBoundBox& bb2,
+                CompareOp& cop
+            );
+
+
+        // Other
+
+            //- Count number of elements on this and sublevels
+            label countElements(const labelBits index) const;
+
+            //- Dump node+octant to an obj file
+            void writeOBJ(const label nodeI, const direction octant) const;
+
+            //- From index into contents_ to subNodes_ entry
+            static labelBits contentPlusOctant
+            (
+                const label i,
+                const direction octant
+            )
+            {
+                return labelBits(-i - 1, octant);
+            }
+
+            //- From index into nodes_ to subNodes_ entry
+            static labelBits nodePlusOctant
+            (
+                const label i,
+                const direction octant
+            )
+            {
+                return labelBits(i + 1, octant);
+            }
+
+            //- From empty to subNodes_ entry
+            static labelBits emptyPlusOctant
+            (
+                const direction octant
+            )
+            {
+                return labelBits(0, octant);
+            }
+
+public:
+
+        //- Get the perturbation tolerance
+        static scalar& perturbTol();
+
+
+    // Constructors
+
+        //- Construct from shapes
+        dynamicIndexedOctree
+        (
+            const Type& shapes,
+            const treeBoundBox& bb,
+            const label maxLevels,          // maximum number of levels
+            const scalar maxLeafRatio,      // how many elements per leaf
+            const scalar maxDuplicity       // in how many leaves is a shape on
+                                            // average
+        );
+
+        //- Clone
+        autoPtr<dynamicIndexedOctree<Type> > clone() const
+        {
+            return autoPtr<dynamicIndexedOctree<Type> >
+            (
+                new dynamicIndexedOctree<Type>(*this)
+            );
+        }
+
+    // Member Functions
+
+        // Access
+
+            //- Reference to shape
+            const Type& shapes() const
+            {
+                return shapes_;
+            }
+
+            //- List of all nodes
+            const List<node>& nodes() const
+            {
+                return nodes_;
+            }
+
+            //- List of all contents (referenced by those nodes that are
+            //  contents)
+            const contentListList& contents() const
+            {
+                return contents_;
+            }
+
+            //- Top bounding box
+            const treeBoundBox& bb() const
+            {
+                if (nodes_.empty())
+                {
+                    FatalErrorIn("dynamicIndexedOctree<Type>::bb() const")
+                        << "Tree is empty" << abort(FatalError);
+                }
+                return nodes_[0].bb_;
+            }
+
+
+        // Conversions for entries in subNodes_.
+
+            static bool isContent(const labelBits i)
+            {
+                return i.val() < 0;
+            }
+
+            static bool isEmpty(const labelBits i)
+            {
+                return i.val() == 0;
+            }
+
+            static bool isNode(const labelBits i)
+            {
+                return i.val() > 0;
+            }
+
+            static label getContent(const labelBits i)
+            {
+                if (!isContent(i))
+                {
+                    FatalErrorIn("getContent(const label)")
+                        << abort(FatalError);
+                }
+                return -i.val()-1;
+            }
+
+            static label getNode(const labelBits i)
+            {
+                if (!isNode(i))
+                {
+                    FatalErrorIn("getNode(const label)")
+                        << abort(FatalError);
+                }
+                return i.val() - 1;
+            }
+
+            static direction getOctant(const labelBits i)
+            {
+                return i.bits();
+            }
+
+
+        // Queries
+
+            //- Calculate nearest point on nearest shape.
+            //  Returns
+            //  - bool : any point found nearer than nearestDistSqr
+            //  - label: index in shapes
+            //  - point: actual nearest point found
+            pointIndexHit findNearest
+            (
+                const point& sample,
+                const scalar nearestDistSqr
+            ) const;
+
+            //- Low level: calculate nearest starting from subnode.
+            void findNearest
+            (
+                const label nodeI,
+                const point&,
+
+                scalar& nearestDistSqr,
+                label& nearestShapeI,
+                point& nearestPoint
+            ) const;
+
+            //- Find nearest to line.
+            //  Returns
+            //  - bool : any point found?
+            //  - label: index in shapes
+            //  - point: actual nearest point found
+            //  sets:
+            //  - linePoint : corresponding nearest point on line
+            pointIndexHit findNearest
+            (
+                const linePointRef& ln,
+                treeBoundBox& tightest,
+                point& linePoint
+            ) const;
+
+            //- Find nearest intersection of line between start and end.
+            pointIndexHit findLine
+            (
+                const point& start,
+                const point& end
+            ) const;
+
+            //- Find any intersection of line between start and end.
+            pointIndexHit findLineAny
+            (
+                const point& start,
+                const point& end
+            ) const;
+
+            //- Find (in no particular order) indices of all shapes inside or
+            //  overlapping bounding box (i.e. all shapes not outside box)
+            labelList findBox(const treeBoundBox& bb) const;
+
+            //- Find (in no particular order) indices of all shapes inside or
+            //  overlapping a bounding sphere (i.e. all shapes not outside
+            //  sphere)
+            labelList findSphere
+            (
+                const point& centre,
+                const scalar radiusSqr
+            ) const;
+
+            //- Find deepest node (as parent+octant) containing point. Starts
+            //  off from starting index in nodes_ (use 0 to start from top)
+            //  Use getNode and getOctant to extract info, or call findIndices.
+            labelBits findNode(const label nodeI, const point&) const;
+
+            //- Find shape containing point. Only implemented for certain
+            //  shapes.
+            label findInside(const point&) const;
+
+            //- Find the shape indices that occupy the result of findNode
+            const labelList& findIndices(const point&) const;
+
+            //- Determine type (inside/outside/mixed) for point. unknown if
+            //  cannot be determined (e.g. non-manifold surface)
+            volumeType getVolumeType(const point&) const;
+
+            //- Helper function to return the side. Returns outside if
+            //  outsideNormal&vec >= 0, inside otherwise
+            static volumeType getSide
+            (
+                const vector& outsideNormal,
+                const vector& vec
+            );
+
+            //- Helper: does bb intersect a sphere around sample? Or is any
+            //  corner point of bb closer than nearestDistSqr to sample.
+            static bool overlaps
+            (
+                const point& bbMin,
+                const point& bbMax,
+                const scalar nearestDistSqr,
+                const point& sample
+            );
+
+            //- Find near pairs and apply CompareOp to them.
+            //  tree2 can be *this or different tree.
+            template <class CompareOp>
+            void findNear
+            (
+                const scalar nearDist,
+                const dynamicIndexedOctree<Type>& tree2,
+                CompareOp& cop
+            ) const;
+
+
+        // Edit
+
+            //- Insert a new object into the tree.
+            bool insert(label startIndex, label endIndex);
+
+            bool insertIndex
+            (
+                const label nodIndex,
+                const label index,
+                label& nLevels
+            );
+
+            //- Remove an object from the tree.
+            bool remove(const label index);
+
+            label removeIndex(const label nodIndex, const label index);
+
+        // Write
+
+            //- Print tree. Either print all indices (printContent = true) or
+            //  just size of contents nodes.
+            void print
+            (
+                prefixOSstream&,
+                const bool printContents,
+                const label
+            ) const;
+
+            bool write(Ostream& os) const;
+
+            void writeTreeInfo() const;
+
+    // IOstream Operators
+
+        friend Ostream& operator<< <Type>
+        (
+            Ostream&,
+            const dynamicIndexedOctree<Type>&
+        );
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+#   include "dynamicIndexedOctree.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/algorithms/dynamicIndexedOctree/dynamicIndexedOctreeName.C b/src/OpenFOAM/algorithms/dynamicIndexedOctree/dynamicIndexedOctreeName.C
new file mode 100644
index 0000000000000000000000000000000000000000..4e842cb28fa03d0bef3973cab873bbb0d193d360
--- /dev/null
+++ b/src/OpenFOAM/algorithms/dynamicIndexedOctree/dynamicIndexedOctreeName.C
@@ -0,0 +1,32 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "dynamicIndexedOctree.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+defineTypeNameAndDebug(Foam::dynamicIndexedOctreeName, 0);
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/algorithms/dynamicIndexedOctree/dynamicTreeDataPoint.C b/src/OpenFOAM/algorithms/dynamicIndexedOctree/dynamicTreeDataPoint.C
new file mode 100644
index 0000000000000000000000000000000000000000..81b3a1c85a6a1448fe2c652e3aa6a0a8ecc6e2e5
--- /dev/null
+++ b/src/OpenFOAM/algorithms/dynamicIndexedOctree/dynamicTreeDataPoint.C
@@ -0,0 +1,163 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "dynamicTreeDataPoint.H"
+#include "treeBoundBox.H"
+#include "dynamicIndexedOctree.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+defineTypeNameAndDebug(Foam::dynamicTreeDataPoint, 0);
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::dynamicTreeDataPoint::dynamicTreeDataPoint
+(
+    const DynamicList<point>& points
+)
+:
+    points_(points)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+const Foam::DynamicList<Foam::point>&
+Foam::dynamicTreeDataPoint::shapePoints() const
+{
+    return points_;
+}
+
+
+//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
+//  Only makes sense for closed surfaces.
+Foam::label Foam::dynamicTreeDataPoint::getVolumeType
+(
+    const dynamicIndexedOctree<dynamicTreeDataPoint>& oc,
+    const point& sample
+) const
+{
+    return dynamicIndexedOctree<dynamicTreeDataPoint>::UNKNOWN;
+}
+
+
+// Check if any point on shape is inside cubeBb.
+bool Foam::dynamicTreeDataPoint::overlaps
+(
+    const label index,
+    const treeBoundBox& cubeBb
+) const
+{
+    return cubeBb.contains(points_[index]);
+}
+
+
+// Calculate nearest point to sample. Updates (if any) nearestDistSqr, minIndex,
+// nearestPoint.
+void Foam::dynamicTreeDataPoint::findNearest
+(
+    const labelUList& indices,
+    const point& sample,
+
+    scalar& nearestDistSqr,
+    label& minIndex,
+    point& nearestPoint
+) const
+{
+    forAll(indices, i)
+    {
+        const label index = indices[i];
+
+        const point& pt = points_[index];
+
+        scalar distSqr = magSqr(pt - sample);
+
+        if (distSqr < nearestDistSqr)
+        {
+            nearestDistSqr = distSqr;
+            minIndex = index;
+            nearestPoint = pt;
+        }
+    }
+}
+
+
+//- Calculates nearest (to line) point in shape.
+//  Returns point and distance (squared)
+void Foam::dynamicTreeDataPoint::findNearest
+(
+    const labelUList& indices,
+    const linePointRef& ln,
+
+    treeBoundBox& tightest,
+    label& minIndex,
+    point& linePoint,
+    point& nearestPoint
+) const
+{
+    // Best so far
+    scalar nearestDistSqr = magSqr(linePoint - nearestPoint);
+
+    forAll(indices, i)
+    {
+        const label index = indices[i];
+
+        const point& shapePt = points_[index];
+
+        if (tightest.contains(shapePt))
+        {
+            // Nearest point on line
+            pointHit pHit = ln.nearestDist(shapePt);
+            scalar distSqr = sqr(pHit.distance());
+
+            if (distSqr < nearestDistSqr)
+            {
+                nearestDistSqr = distSqr;
+                minIndex = index;
+                linePoint = pHit.rawPoint();
+                nearestPoint = shapePt;
+
+                {
+                    point& minPt = tightest.min();
+                    minPt = min(ln.start(), ln.end());
+                    minPt.x() -= pHit.distance();
+                    minPt.y() -= pHit.distance();
+                    minPt.z() -= pHit.distance();
+                }
+                {
+                    point& maxPt = tightest.max();
+                    maxPt = max(ln.start(), ln.end());
+                    maxPt.x() += pHit.distance();
+                    maxPt.y() += pHit.distance();
+                    maxPt.z() += pHit.distance();
+                }
+            }
+        }
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/algorithms/dynamicIndexedOctree/dynamicTreeDataPoint.H b/src/OpenFOAM/algorithms/dynamicIndexedOctree/dynamicTreeDataPoint.H
new file mode 100644
index 0000000000000000000000000000000000000000..6ada3c05125eb8c6b506b9d2b2adf000353b639e
--- /dev/null
+++ b/src/OpenFOAM/algorithms/dynamicIndexedOctree/dynamicTreeDataPoint.H
@@ -0,0 +1,163 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::dynamicTreeDataPoint
+
+Description
+    Holds (reference to) pointField. Encapsulation of data needed for
+    octree searches.
+    Used for searching for nearest point. No bounding boxes around points.
+    Only overlaps and calcNearest are implemented, rest makes little sense.
+
+    Optionally works on subset of points.
+
+SourceFiles
+    dynamicTreeDataPoint.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef dynamicTreeDataPoint_H
+#define dynamicTreeDataPoint_H
+
+#include "pointField.H"
+#include "treeBoundBox.H"
+#include "linePointRef.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// Forward declaration of classes
+template<class Type> class dynamicIndexedOctree;
+
+/*---------------------------------------------------------------------------*\
+                           Class dynamicTreeDataPoint Declaration
+\*---------------------------------------------------------------------------*/
+
+class dynamicTreeDataPoint
+{
+    // Private data
+
+        const DynamicList<point>& points_;
+
+public:
+
+    // Declare name of the class and its debug switch
+    ClassName("dynamicTreeDataPoint");
+
+
+    // Constructors
+
+        //- Construct from List. Holds reference!
+        dynamicTreeDataPoint(const DynamicList<point>& points);
+
+
+    // Member Functions
+
+        // Access
+
+            inline label size() const
+            {
+                return points_.size();
+            }
+
+            //- Get representative point cloud for all shapes inside
+            //  (one point per shape)
+            const DynamicList<point>& shapePoints() const;
+
+
+        // Search
+
+            //- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
+            //  Only makes sense for closed surfaces.
+            label getVolumeType
+            (
+                const dynamicIndexedOctree<dynamicTreeDataPoint>&,
+                const point&
+            ) const;
+
+            //- Does (bb of) shape at index overlap bb
+            bool overlaps
+            (
+                const label index,
+                const treeBoundBox& sampleBb
+            ) const;
+
+            //- Calculates nearest (to sample) point in shape.
+            //  Returns actual point and distance (squared)
+            void findNearest
+            (
+                const labelUList& indices,
+                const point& sample,
+
+                scalar& nearestDistSqr,
+                label& nearestIndex,
+                point& nearestPoint
+            ) const;
+
+            //- Calculates nearest (to line) point in shape.
+            //  Returns point and distance (squared)
+            void findNearest
+            (
+                const labelUList& indices,
+                const linePointRef& ln,
+
+                treeBoundBox& tightest,
+                label& minIndex,
+                point& linePoint,
+                point& nearestPoint
+            ) const;
+
+            //- Calculate intersection of shape with ray. Sets result
+            //  accordingly
+            bool intersects
+            (
+                const label index,
+                const point& start,
+                const point& end,
+                point& result
+            ) const
+            {
+                notImplemented
+                (
+                    "dynamicTreeDataPoint::intersects(const label, const point&,"
+                    "const point&, point&)"
+                );
+                return false;
+            }
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+
+#endif
+
+// ************************************************************************* //