BehaviorTreeLayout.cs 4.1 KB

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