BehaviorTreeLayout.cs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. namespace BehaviorTree
  2. {
  3. public class BehaviorTreeLayout
  4. {
  5. private const double XGap = 20;
  6. private const double YGap = 10;
  7. private static void CountPrelim(TreeNodeViewModel treeNode)
  8. {
  9. if (treeNode.Index == 0)
  10. {
  11. treeNode.Prelim = treeNode.Index * (TreeNodeViewModel.Width + XGap);
  12. return;
  13. }
  14. double childrenCenter;
  15. if (treeNode.Children.Count > 0)
  16. {
  17. int maxIndex = treeNode.Children.Count - 1;
  18. childrenCenter = (treeNode.Children[0].Prelim + treeNode.Children[maxIndex].Prelim) / 2;
  19. }
  20. else
  21. {
  22. childrenCenter = 0;
  23. }
  24. treeNode.Prelim = childrenCenter;
  25. }
  26. private static void CountModify(TreeNodeViewModel treeNode, double prelim)
  27. {
  28. double childrenCenter = 0;
  29. if (treeNode.Children.Count > 0)
  30. {
  31. int maxIndex = treeNode.Children.Count - 1;
  32. childrenCenter = (treeNode.Children[0].Prelim + treeNode.Children[maxIndex].Prelim) / 2;
  33. }
  34. treeNode.Modify = prelim - childrenCenter;
  35. }
  36. private static void CountPrelimAndModify(TreeNodeViewModel treeNode)
  37. {
  38. CountPrelim(treeNode);
  39. CountModify(treeNode, treeNode.Prelim);
  40. foreach (TreeNodeViewModel node in treeNode.Children)
  41. {
  42. CountPrelimAndModify(node);
  43. }
  44. }
  45. private static void AjustTwoSubTreeGap(TreeNodeViewModel left, TreeNodeViewModel right)
  46. {
  47. if (left.IsLeaf || right.IsLeaf)
  48. {
  49. return;
  50. }
  51. double offset = 0;
  52. TreeNodeViewModel tLeft = left;
  53. TreeNodeViewModel tRight = right;
  54. double leftTreeModify = 0;
  55. double rightTreeModify = 0;
  56. for (int i = 0;; ++i)
  57. {
  58. leftTreeModify += tLeft.Modify;
  59. rightTreeModify += tRight.Modify;
  60. tLeft = tLeft.RightMostChild;
  61. tRight = tRight.LeftMostChild;
  62. double tGap = (tRight.Prelim + rightTreeModify) - (tLeft.Prelim + leftTreeModify);
  63. if (tGap - XGap - TreeNodeViewModel.Width > offset)
  64. {
  65. offset = tGap - XGap - TreeNodeViewModel.Width;
  66. }
  67. if (tLeft.IsLeaf || tRight.IsLeaf)
  68. {
  69. break;
  70. }
  71. }
  72. right.Modify += offset;
  73. }
  74. private static void AjustTreeGap(TreeNodeViewModel treeNode)
  75. {
  76. for (int i = 0; i < treeNode.Children.Count - 1; ++i)
  77. {
  78. var left = treeNode.Children[i];
  79. var right = treeNode.Children[i + 1];
  80. AjustTwoSubTreeGap(left, right);
  81. }
  82. }
  83. private static void ApplyXY(int level, TreeNodeViewModel treeNode)
  84. {
  85. treeNode.X = treeNode.Prelim + treeNode.Modify;
  86. treeNode.Y = level * (TreeNodeViewModel.Height + YGap);
  87. ++level;
  88. foreach (TreeNodeViewModel node in treeNode.Children)
  89. {
  90. ApplyXY(level, node);
  91. }
  92. }
  93. public static void ExcuteLayout(TreeNodeViewModel root)
  94. {
  95. CountPrelimAndModify(root);
  96. AjustTreeGap(root);
  97. ApplyXY(0, root);
  98. }
  99. }
  100. }