| using System; | 
| using System.Collections.Generic; | 
| using System.Linq; | 
| using System.Text; | 
| using UnityEngine; | 
|   | 
| namespace Treemap | 
| { | 
|     public class Utility | 
|     { | 
|         public static Rect[] GetTreemapRects(float[] values, Rect targetRect) | 
|         { | 
|             if (values.Length == 0) | 
|                 throw new ArgumentException ("You need to at least pass in one valid value", "values"); | 
|                  | 
|             Rect[] result = new Rect[values.Length]; | 
|             | 
|             float totalInputArea = 0f; | 
|             for (int i = 0; i < values.Length; i++) | 
|                 totalInputArea += values[i]; | 
|   | 
|             float totalOutputArea = targetRect.width * targetRect.height; | 
|             bool vertical = targetRect.width > targetRect.height; | 
|   | 
|             var unfinishedRects = new List<Rect>(); | 
|   | 
|             for (int index = 0; index < values.Length; index++) | 
|             { | 
|                 bool lastItem = index == values.Length - 1; | 
|   | 
|                 float currentInputValue = values[index]; | 
|   | 
|                 if (currentInputValue < 0f) | 
|                     throw new ArgumentException ("only positive float values are supported. found: " + currentInputValue); | 
|   | 
|                 float currentOutputArea = currentInputValue * totalOutputArea / totalInputArea; | 
|                 unfinishedRects = AddRect(unfinishedRects, currentOutputArea, targetRect, vertical); | 
|                 float currentAspect = GetAverageAspect(unfinishedRects); | 
|   | 
|                 float nextInputValue = lastItem ? 0f : values[index + 1]; | 
|                 float nextOutputArea = nextInputValue * totalOutputArea / totalInputArea; | 
|                 float nextAspect = GetNextAspect(unfinishedRects, nextOutputArea, targetRect, vertical); | 
|   | 
|                 if (Mathf.Abs(1f - currentAspect) < Mathf.Abs(1f - nextAspect) || lastItem) | 
|                 { | 
|                     int resultIndex = index - unfinishedRects.Count + 1; | 
|                     for (int rectIndex = 0; rectIndex < unfinishedRects.Count; rectIndex++) | 
|                     { | 
|                         result[resultIndex++] = unfinishedRects[rectIndex]; | 
|                     } | 
|   | 
|                     targetRect = GetNewTarget(unfinishedRects, targetRect, vertical); | 
|                     vertical = !vertical; | 
|                     unfinishedRects.Clear(); | 
|                 } | 
|             } | 
|   | 
|             return result; | 
|         } | 
|   | 
|         private static List<Rect> AddRect(List<Rect> existing, float area, Rect space, bool vertical) | 
|         { | 
|             List<Rect> result = new List<Rect>(); | 
|             if (vertical) | 
|             { | 
|                 if (existing.Count == 0) | 
|                 { | 
|                     result.Add(new Rect(space.xMin, space.yMin, area / space.height, space.height)); | 
|                 } | 
|                 else | 
|                 { | 
|                     float totalSize = GetArea(existing) + area; | 
|                     float width = totalSize / space.height; | 
|                     float yPosition = space.yMin; | 
|                     foreach (Rect old in existing) | 
|                     { | 
|                         float itemArea = GetArea(old); | 
|                         result.Add(new Rect(old.xMin, yPosition, width, itemArea / width)); | 
|                         yPosition += itemArea / width; | 
|                     } | 
|                     result.Add(new Rect(space.xMin, yPosition, width, area / width)); | 
|                 } | 
|             } | 
|             else | 
|             { | 
|                 if (existing.Count == 0) | 
|                 { | 
|                     result.Add(new Rect(space.xMin, space.yMin, space.width, area / space.width)); | 
|                 } | 
|                 else | 
|                 { | 
|                     float totalSize = GetArea(existing) + area; | 
|                     float height = totalSize / space.width; | 
|                     float xPosition = space.xMin; | 
|                     foreach (Rect old in existing) | 
|                     { | 
|                         float itemArea = GetArea(old); | 
|                         result.Add(new Rect(xPosition, old.yMin, itemArea / height, height)); | 
|                         xPosition += itemArea / height; | 
|                     } | 
|                     result.Add(new Rect(xPosition, space.yMin, area / height, height)); | 
|                 } | 
|             } | 
|             return result; | 
|         } | 
|   | 
|         private static Rect GetNewTarget(List<Rect> unfinished, Rect oldTarget, bool vertical) | 
|         { | 
|             if (vertical) | 
|             { | 
|                 return new Rect(oldTarget.xMin + unfinished[0].width, oldTarget.yMin, oldTarget.width - unfinished[0].width, oldTarget.height); | 
|             } | 
|             else | 
|             { | 
|                 return new Rect(oldTarget.xMin, oldTarget.yMin + unfinished[0].height, oldTarget.width, oldTarget.height - unfinished[0].height); | 
|             } | 
|         } | 
|   | 
|         private static float GetNextAspect(List<Rect> existing, float area, Rect space, bool vertical) | 
|         { | 
|             List<Rect> newExisting = AddRect(existing, area, space, vertical); | 
|             return newExisting[newExisting.Count - 1].height / newExisting[newExisting.Count - 1].width; | 
|         } | 
|   | 
|         private static float GetAverageAspect(List<Rect> rects) | 
|         { | 
|             float aspect = 0f; | 
|             foreach (Rect r in rects) | 
|             { | 
|                 aspect += r.height / r.width; | 
|             } | 
|             return aspect / rects.Count; | 
|         } | 
|   | 
|         private static float GetArea(Rect rect) | 
|         { | 
|             return rect.width * rect.height; | 
|         } | 
|   | 
|         private static float GetArea(List<Rect> rects) | 
|         { | 
|             return rects.Sum(x => GetArea(x)); | 
|         } | 
|   | 
|         public static Color GetColorForName(string name) | 
|         { | 
|             int r = 0, g = 0, b = 0; | 
|   | 
|             for (int i = 0; i < name.Length; i++) | 
|             { | 
|                 if (i % 3 == 0) | 
|                 { | 
|                     r += (int)name[i]; | 
|                 } | 
|                 else if (i % 3 == 1) | 
|                 { | 
|                     g += (int)name[i]; | 
|                 } | 
|                 else | 
|                 { | 
|                     b += (int)name[i]; | 
|                 } | 
|             } | 
|   | 
|             r %= 128; | 
|             g %= 128; | 
|             b %= 128; | 
|   | 
|             return new Color32((byte)(r + 96), (byte)(g + 96), (byte)(b + 96), 255); | 
|         } | 
|   | 
|         public static bool IsInside(Rect lhs, Rect rhs) | 
|         { | 
|             return lhs.xMax > rhs.xMin && lhs.xMin < rhs.xMax && lhs.yMax > rhs.yMin && lhs.yMin < rhs.yMax; | 
|         } | 
|     } | 
| } |