TreeLayout.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. using Common.Logger;
  2. namespace Modules.BehaviorTreeModule
  3. {
  4. public class TreeLayout
  5. {
  6. private readonly TreeViewModel treeViewModel;
  7. private const double XGap = 20;
  8. private const double YGap = 10;
  9. private double rootOrigX;
  10. private double rootOrigY;
  11. private double rootOffsetX;
  12. private double rootOffsetY;
  13. public TreeLayout(TreeViewModel treeViewModel)
  14. {
  15. this.treeViewModel = treeViewModel;
  16. }
  17. private TreeNodeViewModel LeftMostOffspring(
  18. TreeNodeViewModel treeNodeViewModel, int currentLevel, int searchLevel)
  19. {
  20. if (currentLevel == searchLevel)
  21. {
  22. return treeNodeViewModel;
  23. }
  24. for (int i = 0; i < treeNodeViewModel.Children.Count; ++i)
  25. {
  26. TreeNodeViewModel child = treeNodeViewModel.Children[i];
  27. child.AncestorModify = treeNodeViewModel.Modify + treeNodeViewModel.AncestorModify;
  28. TreeNodeViewModel offspring = this.LeftMostOffspring(child, currentLevel + 1, searchLevel);
  29. if (offspring == null)
  30. {
  31. continue;
  32. }
  33. return offspring;
  34. }
  35. return null;
  36. }
  37. private TreeNodeViewModel RightMostOffspring(
  38. TreeNodeViewModel treeNodeViewModel, int currentLevel, int searchLevel)
  39. {
  40. if (currentLevel == searchLevel)
  41. {
  42. return treeNodeViewModel;
  43. }
  44. for (int i = treeNodeViewModel.Children.Count - 1; i >= 0; --i)
  45. {
  46. TreeNodeViewModel child = treeNodeViewModel.Children[i];
  47. child.AncestorModify = treeNodeViewModel.Modify + treeNodeViewModel.AncestorModify;
  48. TreeNodeViewModel offspring = this.RightMostOffspring(child, currentLevel + 1, searchLevel);
  49. if (offspring == null)
  50. {
  51. continue;
  52. }
  53. return offspring;
  54. }
  55. return null;
  56. }
  57. private void AjustSubTreeGap(TreeNodeViewModel left, TreeNodeViewModel right)
  58. {
  59. double offset = 0;
  60. TreeNodeViewModel tLeft = left;
  61. TreeNodeViewModel tRight = right;
  62. left.AncestorModify = 0;
  63. right.AncestorModify = 0;
  64. for (int i = 0; tLeft != null && tRight != null; ++i)
  65. {
  66. double tGap = (tRight.Prelim + tRight.AncestorModify) - (tLeft.Prelim + tLeft.AncestorModify);
  67. if (XGap + TreeNodeViewModel.Width - tGap > offset)
  68. {
  69. offset = XGap + TreeNodeViewModel.Width - tGap;
  70. }
  71. tLeft = this.RightMostOffspring(left, 0, i + 1);
  72. tRight = this.LeftMostOffspring(right, 0, i + 1);
  73. }
  74. right.Modify += offset;
  75. right.Prelim += offset;
  76. }
  77. private void AjustTreeGap(TreeNodeViewModel treeNodeViewModel)
  78. {
  79. for (int i = 0; i < treeNodeViewModel.Children.Count - 1; ++i)
  80. {
  81. for (int j = i + 1; j < treeNodeViewModel.Children.Count; ++j)
  82. {
  83. TreeNodeViewModel left = treeNodeViewModel.Children[i];
  84. TreeNodeViewModel right = treeNodeViewModel.Children[j];
  85. this.AjustSubTreeGap(left, right);
  86. }
  87. }
  88. }
  89. private void CalculatePrelimAndModify(TreeNodeViewModel treeNodeViewModel)
  90. {
  91. foreach (TreeNodeViewModel child in treeNodeViewModel.Children)
  92. {
  93. this.CalculatePrelimAndModify(child);
  94. }
  95. double prelim = 0;
  96. double modify = 0;
  97. if (treeNodeViewModel.IsLeaf)
  98. {
  99. if (treeNodeViewModel.LeftSibling == null)
  100. {
  101. // 如果没有左邻居,不需要设置modify
  102. prelim = 0;
  103. }
  104. else
  105. {
  106. prelim = treeNodeViewModel.LeftSibling.Prelim + TreeNodeViewModel.Width + XGap;
  107. }
  108. }
  109. else
  110. {
  111. // 调整子树间的间距
  112. this.AjustTreeGap(treeNodeViewModel);
  113. double childrenCenter = (treeNodeViewModel.FirstChild.Prelim +
  114. treeNodeViewModel.LastChild.Prelim) / 2;
  115. if (treeNodeViewModel.LeftSibling == null)
  116. {
  117. // 如果没有左邻居,不需要设置modify
  118. prelim = childrenCenter;
  119. }
  120. else
  121. {
  122. prelim = treeNodeViewModel.LeftSibling.Prelim + TreeNodeViewModel.Width + XGap;
  123. modify = prelim - childrenCenter;
  124. }
  125. }
  126. treeNodeViewModel.Prelim = prelim;
  127. treeNodeViewModel.Modify = modify;
  128. Log.Debug("Id: " + treeNodeViewModel.Id + " Prelim: " + treeNodeViewModel.Prelim + " Modify: " + treeNodeViewModel.Modify);
  129. }
  130. private void CalculateRelativeXAndY(
  131. TreeNodeViewModel treeNodeViewModel, int level, double totalModify)
  132. {
  133. foreach (TreeNodeViewModel child in treeNodeViewModel.Children)
  134. {
  135. this.CalculateRelativeXAndY(child, level + 1, treeNodeViewModel.Modify + totalModify);
  136. }
  137. if (treeNodeViewModel.IsLeaf)
  138. {
  139. treeNodeViewModel.XX = treeNodeViewModel.Prelim + totalModify;
  140. }
  141. else
  142. {
  143. treeNodeViewModel.XX = (treeNodeViewModel.FirstChild.XX + treeNodeViewModel.LastChild.XX) / 2;
  144. }
  145. treeNodeViewModel.YY = level * (TreeNodeViewModel.Height + YGap);
  146. }
  147. private void FixXAndY(TreeNodeViewModel treeNode)
  148. {
  149. treeNode.XX += this.rootOffsetX;
  150. treeNode.YY += this.rootOffsetY;
  151. foreach (TreeNodeViewModel child in treeNode.Children)
  152. {
  153. this.FixXAndY(child);
  154. }
  155. }
  156. public void ExcuteLayout()
  157. {
  158. TreeNodeViewModel root = this.treeViewModel.Root;
  159. if (root == null)
  160. {
  161. return;
  162. }
  163. this.rootOrigX = root.XX;
  164. this.rootOrigY = root.YY;
  165. this.CalculatePrelimAndModify(root);
  166. this.CalculateRelativeXAndY(root, 0, 0);
  167. this.rootOffsetX = this.rootOrigX - root.XX;
  168. this.rootOffsetY = this.rootOrigY - root.YY;
  169. this.FixXAndY(root);
  170. }
  171. }
  172. }