我的图形布局 组织结构图布局

组织结构图布局,有的人也叫它树状布局,在图形中是经常用到的布局算法.形成类似如下图的图形布局方式
在这里插入图片描述
首先创建一个类,

public class TreeLayouter
{
	private int m_space = 40;
	/// <summary>
	/// 空间间隔
	/// </summary>
	public int Space
	{
	    get { return m_space; }
	    set { m_space = value; }
	
	}
}

要找出每个面和面之间的关系,不妨形成一个矩阵

/// <summary>
/// 形成关系矩阵
/// </summary>
/// <param name="shapes"></param>
/// <returns></returns>
private int[,] FormMatrixRelation(List<IShape> shapes)
{
    int n = shapes.Count;
    int[,] array = new int[n, n];

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (i != j)
            {
                //找出i和j之间是否有连线,要考虑线的起始端和终止端
                if (IsRelation(shapes[i], shapes[j]))
                    array[i, j] = 1;
            }
        }
    }

    return array;
}

根据矩阵找出根节点来

        /// <summary>
        /// 查找根节点,返回根节点的所有,有几个返回几个
        /// </summary>
        /// <param name="shapes"></param>
        /// <param name="array"></param>
        private int[] FindRootNode(List<IShape> shapes, int[,] array)
        {
            List<int> trees = new List<int>();
            //矩阵中列上全部为0的点则是顶点
            for (int colIndex = 0, n = array.GetLength(0); colIndex < n; colIndex++)
            {
                bool isNull = true;
                for (int rowIndex = 0; rowIndex < n; rowIndex++)
                {
                    if (array[rowIndex, colIndex] != 0)
                    {
                        isNull = false;
                        break;
                    }
                }

                if (isNull)//找到树上的一个根节点
                {
                    trees.Add(colIndex);
                }
            }

            return trees.ToArray();
        }
		//查找入向的行节点
		private int[] FindInputRowIndex(int[,] array, int colIdx)
		{
		    //查找列中为1的数量
		    List<int> list = new List<int>();
		    for (int rowIdx = 0, n = array.GetLength(0); rowIdx < n; rowIdx++)
		    {
		        if (array[rowIdx, colIdx] == 1)
		        {
		            list.Add(rowIdx);
		        }
		    }
		
		    return list.ToArray();
		}

找出最长的路径

//计算最长路径
private int CalcuNodeLevel(int[,] array, int rowIdx, int levelCount, List<int> existIdxs, int childIdx)
{
    if (existIdxs.Contains(rowIdx))
    {
        array[rowIdx, childIdx] = 0;
        return 0;
    }
    else
    {
        existIdxs.Insert(0, rowIdx);

        levelCount++;
        //找出最长路径
        int[] rowIdxs = FindInputRowIndex(array, rowIdx);
        if (rowIdxs.Length == 0)
            return levelCount;
        else
        {
            int level = 0;
            foreach (int ridx in rowIdxs)
            {
                int c = CalcuNodeLevel(array, ridx, levelCount, existIdxs, rowIdx);
                if (level < c)
                {
                    level = c;
                }
            }

            return level;
        }
    }
}

应用最长路径

//应用最长路径
private void ReviseArray(int[,] array)
{
    for (int colIdx = 0, n = array.GetLength(0); colIdx < n; colIdx++)
    {
        //查找列中为1的数量
        int[] rowIdxs = FindInputRowIndex(array, colIdx);

        if (rowIdxs.Length > 1)
        {
            //找出最长的,其它的赋值为0
            int level = 0;
            int ridx = -1;
            foreach (int rowIdx in rowIdxs)
            {
                List<int> existIdxs = new List<int>();
                existIdxs.Add(colIdx);
                int c = CalcuNodeLevel(array, rowIdx, 0, existIdxs, colIdx);
                if (level == 0)
                {
                    level = c;
                    ridx = rowIdx;
                }
                else
                {
                    if (level <= c)
                    {
                        level = c;
                        //先赋值为0;
                        array[ridx, colIdx] = 0;
                        ridx = rowIdx;
                    }
                    else
                    {
                        array[rowIdx, colIdx] = 0;
                    }
                }
            }
        }
    }
}

增加验证,是否有循环

/// <summary>
/// 验证树是否正确
/// </summary>
private void Verify(int[,] array, int[] rootIdxes)
{
    if (rootIdxes.Length == 0)
        throw new Exception("无法找到根节点");

    //是否存在闭环,导致死循环
    foreach (int rootIdx in rootIdxes)
    {
        List<int> list = new List<int>();
        list.Add(rootIdx);

        VerifyLoop(array, rootIdx, list);
    }
}

private void VerifyLoop(int[,] array, int rootIdx, List<int> list)
{
    list.Add(rootIdx);

    List<int> currList = new List<int>();

    for (int colIdx = 0, n = array.GetLength(0); colIdx < n; colIdx++)
    {
        if (array[rootIdx, colIdx] == 1)
        {
            if (list.Contains(colIdx))
                throw new Exception("出现了循环");
            else
                list.Add(colIdx);

            currList.Add(colIdx);
        }
    }

    foreach (int idx in currList)
    {
        VerifyLoop(array, idx, list);
    }
}

到这里其实核心思想已经完成了,整个代码就是应用矩阵来处理.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值