组织结构图布局,有的人也叫它树状布局,在图形中是经常用到的布局算法.形成类似如下图的图形布局方式

首先创建一个类,
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);
}
}
到这里其实核心思想已经完成了,整个代码就是应用矩阵来处理.

被折叠的 条评论
为什么被折叠?



