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