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; 
 | 
        } 
 | 
    } 
 | 
} 
 |