private void secondWalk(final TreeNode v, final double m, final int level, final double levelStart) {
        // construct the position from the prelim and the level information

        // The rootLocation affects the way how x and y are changed and in what
        // direction.
        final double levelChangeSign = getLevelChangeSign();
        final boolean levelChangeOnYAxis = isLevelChangeInYAxis();
        final double levelSize = getSizeOfLevel(level);

        double x = getPrelim(v) + m;

        double y;
        final AlignmentInLevel alignment = configuration.getAlignmentInLevel();
        if (alignment == AlignmentInLevel.Center) {
            y = levelStart + levelChangeSign * (levelSize / 2);
        } else if (alignment == AlignmentInLevel.TowardsRoot) {
            y = levelStart + levelChangeSign * (getNodeThickness(v) / 2);
        } else {
            y = levelStart + levelSize - levelChangeSign * (getNodeThickness(v) / 2);
        }

        if (!levelChangeOnYAxis) {
            final double t = x;
            x = y;
            y = t;
        }

        positions.put(v, new NormalizedPosition(x, y));

        // update the bounds
        updateBounds(v, x, y);

        // recurse
        if (!tree.isLeaf(v)) {
            final double nextLevelStart = levelStart
                    + (levelSize + configuration.getGapBetweenLevels(level + 1)) * levelChangeSign;
            for (final TreeNode w : tree.getChildren(v)) {
                secondWalk(w, m + getMod(v), level + 1, nextLevelStart);
            }
        }
    }
In difference to the original algorithm we also pass in extra level
information.
stroom-core-client-widget/src/main/java/stroom/widget/htree/client/treelayout/AbegoTreeLayout.java