源战役客户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
6.2 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using UnityEngine;
  6. namespace Treemap
  7. {
  8. public class Utility
  9. {
  10. public static Rect[] GetTreemapRects(float[] values, Rect targetRect)
  11. {
  12. if (values.Length == 0)
  13. throw new ArgumentException ("You need to at least pass in one valid value", "values");
  14. Rect[] result = new Rect[values.Length];
  15. float totalInputArea = 0f;
  16. for (int i = 0; i < values.Length; i++)
  17. totalInputArea += values[i];
  18. float totalOutputArea = targetRect.width * targetRect.height;
  19. bool vertical = targetRect.width > targetRect.height;
  20. var unfinishedRects = new List<Rect>();
  21. for (int index = 0; index < values.Length; index++)
  22. {
  23. bool lastItem = index == values.Length - 1;
  24. float currentInputValue = values[index];
  25. if (currentInputValue <= 0f)
  26. throw new ArgumentException ("only positive float values are supported. found: " + currentInputValue);
  27. float currentOutputArea = currentInputValue * totalOutputArea / totalInputArea;
  28. unfinishedRects = AddRect(unfinishedRects, currentOutputArea, targetRect, vertical);
  29. float currentAspect = GetAverageAspect(unfinishedRects);
  30. float nextInputValue = lastItem ? 0f : values[index + 1];
  31. float nextOutputArea = nextInputValue * totalOutputArea / totalInputArea;
  32. float nextAspect = GetNextAspect(unfinishedRects, nextOutputArea, targetRect, vertical);
  33. if (Mathf.Abs(1f - currentAspect) < Mathf.Abs(1f - nextAspect) || lastItem)
  34. {
  35. int resultIndex = index - unfinishedRects.Count + 1;
  36. for (int rectIndex = 0; rectIndex < unfinishedRects.Count; rectIndex++)
  37. {
  38. result[resultIndex++] = unfinishedRects[rectIndex];
  39. }
  40. targetRect = GetNewTarget(unfinishedRects, targetRect, vertical);
  41. vertical = !vertical;
  42. unfinishedRects.Clear();
  43. }
  44. }
  45. return result;
  46. }
  47. private static List<Rect> AddRect(List<Rect> existing, float area, Rect space, bool vertical)
  48. {
  49. List<Rect> result = new List<Rect>();
  50. if (vertical)
  51. {
  52. if (existing.Count == 0)
  53. {
  54. result.Add(new Rect(space.xMin, space.yMin, area / space.height, space.height));
  55. }
  56. else
  57. {
  58. float totalSize = GetArea(existing) + area;
  59. float width = totalSize / space.height;
  60. float yPosition = space.yMin;
  61. foreach (Rect old in existing)
  62. {
  63. float itemArea = GetArea(old);
  64. result.Add(new Rect(old.xMin, yPosition, width, itemArea / width));
  65. yPosition += itemArea / width;
  66. }
  67. result.Add(new Rect(space.xMin, yPosition, width, area / width));
  68. }
  69. }
  70. else
  71. {
  72. if (existing.Count == 0)
  73. {
  74. result.Add(new Rect(space.xMin, space.yMin, space.width, area / space.width));
  75. }
  76. else
  77. {
  78. float totalSize = GetArea(existing) + area;
  79. float height = totalSize / space.width;
  80. float xPosition = space.xMin;
  81. foreach (Rect old in existing)
  82. {
  83. float itemArea = GetArea(old);
  84. result.Add(new Rect(xPosition, old.yMin, itemArea / height, height));
  85. xPosition += itemArea / height;
  86. }
  87. result.Add(new Rect(xPosition, space.yMin, area / height, height));
  88. }
  89. }
  90. return result;
  91. }
  92. private static Rect GetNewTarget(List<Rect> unfinished, Rect oldTarget, bool vertical)
  93. {
  94. if (vertical)
  95. {
  96. return new Rect(oldTarget.xMin + unfinished[0].width, oldTarget.yMin, oldTarget.width - unfinished[0].width, oldTarget.height);
  97. }
  98. else
  99. {
  100. return new Rect(oldTarget.xMin, oldTarget.yMin + unfinished[0].height, oldTarget.width, oldTarget.height - unfinished[0].height);
  101. }
  102. }
  103. private static float GetNextAspect(List<Rect> existing, float area, Rect space, bool vertical)
  104. {
  105. List<Rect> newExisting = AddRect(existing, area, space, vertical);
  106. return newExisting[newExisting.Count - 1].height / newExisting[newExisting.Count - 1].width;
  107. }
  108. private static float GetAverageAspect(List<Rect> rects)
  109. {
  110. float aspect = 0f;
  111. foreach (Rect r in rects)
  112. {
  113. aspect += r.height / r.width;
  114. }
  115. return aspect / rects.Count;
  116. }
  117. private static float GetArea(Rect rect)
  118. {
  119. return rect.width * rect.height;
  120. }
  121. private static float GetArea(List<Rect> rects)
  122. {
  123. return rects.Sum(x => GetArea(x));
  124. }
  125. public static Color GetColorForName(string name)
  126. {
  127. int r = 0, g = 0, b = 0;
  128. for (int i = 0; i < name.Length; i++)
  129. {
  130. if (i % 3 == 0)
  131. {
  132. r += (int)name[i];
  133. }
  134. else if (i % 3 == 1)
  135. {
  136. g += (int)name[i];
  137. }
  138. else
  139. {
  140. b += (int)name[i];
  141. }
  142. }
  143. r %= 128;
  144. g %= 128;
  145. b %= 128;
  146. return new Color32((byte)(r + 96), (byte)(g + 96), (byte)(b + 96), 255);
  147. }
  148. public static bool IsInside(Rect lhs, Rect rhs)
  149. {
  150. return lhs.xMax > rhs.xMin && lhs.xMin < rhs.xMax && lhs.yMax > rhs.yMin && lhs.yMin < rhs.yMax;
  151. }
  152. }
  153. }