创建树节点图

Ice*_*ind 6 c# gdi+

我正在尝试创建一个类似于节点图的树,就像这里示例图像一样.我有以下代码:

    private void DrawNode(Graphics g, Node<T> node, float xOffset, float yOffset)
    {
        if (node == null)
        {
            return;
        }

        Bitmap bmp = (from b in _nodeBitmaps where b.Node.Value.Equals(node.Value) select b.Bitmap).FirstOrDefault();

        if (bmp != null)
        {
            g.DrawImage(bmp, xOffset, yOffset);

            DrawNode(g, node.LeftNode, xOffset - 30 , yOffset + 20);
            DrawNode(g, node.RightNode, xOffset + 30, yOffset + 20);
        }
    }
Run Code Online (Sandbox Code Playgroud)

我的代码几乎正常工作.我遇到的问题是一些节点重叠.在上图中,节点25和66重叠.我确定,原因是因为它在数学上将左节点和右节点放置在空间上,所以父节点的右节点与相邻父节点的左节点重叠.我该如何解决这个问题?

更新:

这是我在dtb的建议后做的代码更新:

            int nodeWidth = 0;
            int rightChildWidth = 0;

            if (node.IsLeafNode)
            {
                nodeWidth = bmp.Width + 50;
            }
            else
            {
                int leftChildWidth = 0;

                Bitmap bmpLeft = null;
                Bitmap bmpRight = null;

                if (node.LeftNode != null)
                {
                    bmpLeft =
                        (from b in _nodeBitmaps where b.Node.Value.Equals(node.LeftNode.Value) select b.Bitmap).
                            FirstOrDefault();
                    if (bmpLeft != null)
                        leftChildWidth = bmpLeft.Width;
                }
                if (node.RightNode != null)
                {
                    bmpRight =
                        (from b in _nodeBitmaps where b.Node.Value.Equals(node.RightNode.Value) select b.Bitmap).
                            FirstOrDefault();
                    if (bmpRight != null)
                        rightChildWidth = bmpRight.Width;
                }

                nodeWidth = leftChildWidth + 50 + rightChildWidth;
            }


            g.DrawImage(bmp, xOffset + (nodeWidth - bmp.Width) / 2, yOffset);

            if (node.LeftNode != null)
            {
                DrawNode(g, node.LeftNode, xOffset, yOffset + 20);
            }
            if (node.RightNode != null)
            {
                DrawNode(g, node.RightNode, xOffset + nodeWidth - rightChildWidth, yOffset + 20);
            }
Run Code Online (Sandbox Code Playgroud)

以下是此代码的屏幕截图: 屏幕截图

dtb*_*dtb 5

为每个分配宽度node:

  • 叶子的宽度是图像的宽度,w.
  • 节点的宽度是其左子节点d的宽度+常量+右子节点的宽度.

       插图

void CalculateWidth(Node<T> node)
{
    node.Width = 20;
    if (node.Left != null)
    {
        CalculateWidth(node.Left);
        node.Width += node.Left.Width;
    }
    if (node.Right != null)
    {
        CalculateWidth(node.Right);
        node.Width += node.Right.Width;
    }
    if (node.Width < bmp.Width)
    {
        node.Width = bmp.Width;
    }
}
Run Code Online (Sandbox Code Playgroud)

从根节点开始x = 0,在宽度的一半处绘制图像,偏移x.
然后计算x每个子节点的位置并递归:

void DrawNode(Graphics g, Node<T> node, double x, double y)
{
    g.DrawImage(x + (node.Width - bmp.Width) / 2, y, bmp);

    if (node.Left != null)
    {
        DrawNode(g, node.Left, x, y + 20);
    }
    if (node.Right != null)
    {
        DrawNode(g, node.Right, x + node.Width - node.Right.Width, y + 20);
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

CalculateWidth(root);

DrawNode(g, root, 0, 0);
Run Code Online (Sandbox Code Playgroud)