private TreeNode apportion(final TreeNode v, TreeNode defaultAncestor, final TreeNode leftSibling,
                               final TreeNode parentOfV) {
        final TreeNode w = leftSibling;
        if (w == null) {
            // v has no left sibling
            return defaultAncestor;
        }
        // v has left sibling w

        // The following variables "v..." are used to traverse the contours to
        // the subtrees. "Minus" refers to the left, "Plus" to the right
        // subtree. "I" refers to the "inside" and "O" to the outside contour.
        TreeNode vOPlus = v;
        TreeNode vIPlus = v;
        TreeNode vIMinus = w;
        // get leftmost sibling of vIPlus, i.e. get the leftmost sibling of
        // v, i.e. the leftmost child of the parent of v (which is passed
        // in)
        TreeNode vOMinus = tree.getFirstChild(parentOfV);

        Double sIPlus = getMod(vIPlus);
        Double sOPlus = getMod(vOPlus);
        Double sIMinus = getMod(vIMinus);
        Double sOMinus = getMod(vOMinus);

        TreeNode nextRightVIMinus = nextRight(vIMinus);
        TreeNode nextLeftVIPlus = nextLeft(vIPlus);

        while (nextRightVIMinus != null && nextLeftVIPlus != null) {
            vIMinus = nextRightVIMinus;
            vIPlus = nextLeftVIPlus;
            vOMinus = nextLeft(vOMinus);
            vOPlus = nextRight(vOPlus);
            setAncestor(vOPlus, v);
            final double shift = (getPrelim(vIMinus) + sIMinus) - (getPrelim(vIPlus) + sIPlus)
                    + getDistance(vIMinus, vIPlus);

            if (shift > 0) {
                moveSubtree(ancestor(vIMinus, v, parentOfV, defaultAncestor), v, parentOfV, shift);
                sIPlus = sIPlus + shift;
                sOPlus = sOPlus + shift;
            }
            sIMinus = sIMinus + getMod(vIMinus);
            sIPlus = sIPlus + getMod(vIPlus);
            sOMinus = sOMinus + getMod(vOMinus);
            sOPlus = sOPlus + getMod(vOPlus);

            nextRightVIMinus = nextRight(vIMinus);
            nextLeftVIPlus = nextLeft(vIPlus);
        }

        if (nextRightVIMinus != null && nextRight(vOPlus) == null) {
            setThread(vOPlus, nextRightVIMinus);
            setMod(vOPlus, getMod(vOPlus) + sIMinus - sOPlus);
        }

        if (nextLeftVIPlus != null && nextLeft(vOMinus) == null) {
            setThread(vOMinus, nextLeftVIPlus);
            setMod(vOMinus, getMod(vOMinus) + sIPlus - sOMinus);
            defaultAncestor = v;
        }
        return defaultAncestor;
    }
In difference to the original algorithm we also pass in the leftSibling
and the parent of v.
<p>
<b>Why adding the parameter 'parent of v' (parentOfV) ?</b>
<p>
In this method we need access to the parent of v. Not every tree
implementation may support efficient (i.e. constant time) access to it.
On the other hand the (only) caller of this method can provide this
information with only constant extra time.
<p>
Also we need access to the "left most sibling" of v. Not every tree
implementation may support efficient (i.e. constant time) access to it.
On the other hand the "left most sibling" of v is also the "first child"
of the parent of v. The first child of a parent node we can get in
constant time. As we got the parent of v we can so also get the
"left most sibling" of v in constant time.
<p>
<b>Why adding the parameter 'leftSibling' ?</b>
<p>
In this method we need access to the "left sibling" of v. Not every tree
implementation may support efficient (i.e. constant time) access to it.
However it is easy for the caller of this method to provide this
information with only constant extra time.
<p>
<p>
<p>
In addition these extra parameters avoid the need for
{@link TreeForTreeLayout} to include extra methods "getParent",
"getLeftSibling", or "getLeftMostSibling". This keeps the interface
{@link TreeForTreeLayout} small and avoids redundant implementations.

@param v
@param defaultAncestor
@param leftSibling     [nullable] the left sibling v, if there is any
@param parentOfV       the parent of v
@return the (possibly changes) defaultAncestor
stroom-core-client-widget/src/main/java/stroom/widget/htree/client/treelayout/AbegoTreeLayout.java