BehaviorTreeLayout.cs 4.4 KB

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