public TreemapItem AddItem(TreemapData data, Geometric.Point center, double radius) { TreemapItem item = new TreemapItem(center.X - radius, center.Y - radius, 2 * radius, 2 * radius) { Indexes = data.Indexes, Size = data.Size, Color = data.Color }; Items.Add(item); return(item); }
public TreemapChart Build(double left, double top, double width, double height) { ChartArea = new Rect(left, top, width, height); BuildArea(); BuildTitle(Parameters); BuildLegend(Parameters); if (Parameters.Algorithm == TreemapAlgorithm.Circular) { double edge = Math.Min(PlotArea.Width, PlotArea.Height); double excessX = (PlotArea.Width - edge) / 2; double excessY = (PlotArea.Height - edge) / 2; PlotArea = new Rect(PlotArea.X + excessX, PlotArea.Y + excessY, edge, edge); } if (IsChartDegenerated()) { return(this); } Parent = new TreemapItem(PlotArea.Left, PlotArea.Top, PlotArea.Width, PlotArea.Height); Parent.Size = Sizes.Sum(); Parent.IndexParameters = new TreemapIndex() { LineVisible = false, LineWeight = 0 }; IndexesComparer comparer = new IndexesComparer(); List <TreemapItem> items = new List <TreemapItem>() { Parent }; for (int i = 0; i < Indexes.Count; i++) { List <TreemapData> data = GetDepthData(i); foreach (TreemapItem item in items) { List <TreemapData> itemData = data.Where(d => comparer.Equals(d.Indexes.Take(i).ToList(), item.Indexes)).ToList(); item.ApplyAlgorithm(itemData, Parameters.Algorithm); } items = items.SelectMany(item => item.Items).ToList(); SetTreemapItemsParameters(i, items); } return(this); }
private void Draw(TreemapItem item) { TreemapIndex index = item.IndexParameters; //Add background shapes if (!item.IsParent() && (index.HasHeader || item.IsChild() || Parameters.Algorithm == TreemapAlgorithm.Circular)) { Excel.Shape shape = AddShape(ShapeType, item.Rectangle, item.FillColor); SetShapeLine(shape, index.GetLineOptions()); SetShapeText(shape, item); } //Add Children Items foreach (var child in item.Items) { Draw(child); } //Add front shapes if (!item.IsParent() && !item.IsChild()) { Excel.Shape frontShape = AddShape(ShapeType, item.InnerRectangle, Color.Transparent); if (Parameters.Algorithm == TreemapAlgorithm.Circular) { frontShape.Line.Visible = GetState(false); SetShapeText(frontShape, item); } else if (!index.HasHeader) { SetShapeLine(frontShape, index.GetLineOptions()); SetShapeText(frontShape, item); } else //Case Header : inner border & no text { SetShapeLine(frontShape, index.GetLineOptions().With(o => o.Weight = 1)); } } }
public void Circlify(List <TreemapData> data) { //IL faut commencer par les 2 plus gros cercles, le milieu du cercle final étant le centre du segment reliant les extrémités de ces cercles. double a1 = GetInnerCircleArea() * data[0].Size / Size; double a2 = GetInnerCircleArea() * data[1].Size / Size; double r1 = Math.Sqrt(a1 / Math.PI); double r2 = Math.Sqrt(a2 / Math.PI); var items = new Dictionary <TreemapItem, List <TreemapItem> >(); Geometric.Point center = GetCenter(); TreemapItem item1 = AddItem(data[0], center.AddX(-r2), r1); TreemapItem item2 = AddItem(data[1], center.AddX(r1), r2); items.Add(item1, new List <TreemapItem> { item2 }); items.Add(item2, new List <TreemapItem> { item1 }); for (int d = 2; d < data.Count; d++) { double a = GetInnerCircleArea() * data[d].Size / Size; double r = Math.Sqrt(a / Math.PI); var results = new List <Tuple <TreemapItem, TreemapItem, Geometric.Point, double> >(); foreach (var kvp in items) { TreemapItem i1 = kvp.Key; foreach (TreemapItem i2 in kvp.Value) { Triangle t = Triangle.FromTwoPointsAndTwoLengths(i1.GetCenter(), i2.GetCenter(), i1.GetRadius() + r, i2.GetRadius() + r); double distance = center.Distance(t.Point3); if (Items.All(item => item.GetCenter().Distance(t.Point3) - (item.GetRadius() + r) >= -0.0001)) { results.Add(Tuple.Create(i1, i2, t.Point3, distance)); } } } var result = results.OrderBy(t => t.Item4).First(); TreemapItem newItem = AddItem(data[d], result.Item3, r); items[result.Item1].Add(newItem); items[result.Item2].Add(newItem); items.Add(newItem, new List <TreemapItem> { result.Item1, result.Item2 }); } //Identify the item farther from the center and expand the chart so that this item becomes adjacent to external circle var max = Items .Select(i => new { Item = i, Distance = i.GetCenter().Distance(center) + i.GetRadius() }) .OrderByDescending(o => o.Distance) .First(); Homothety homothety = new Homothety(center, GetRadius() / max.Distance); foreach (var item in Items) { item.Rectangle = homothety.Transform(item.Rectangle); item.InnerRectangle = homothety.Transform(item.InnerRectangle); item.Empty = homothety.Transform(item.Empty); } //Homothety from contact point Vector vector = new Segment(center, max.Item.GetCenter()).ToVector(); Geometric.Point contact = max.Item.GetCenter() .AddX(max.Item.GetRadius() / vector.Length * vector.X) .AddY(max.Item.GetRadius() / vector.Length * vector.Y); NewtonSolver solver = new NewtonSolver((c) => { Homothety h = new Homothety(contact, c); double min = Items .Except(new List <TreemapItem> { max.Item }) .Select(i => h.Transform(i.InnerRectangle)) .Select(r => new { Center = new Geometric.Point(r.Left + r.Width / 2, r.Top + r.Height / 2), Radius = r.Width / 2 }) .Min(r => GetRadius() - (r.Center.Distance(center) + r.Radius)); return(min); }) .Solve(1); homothety = new Homothety(contact, solver.Solution); foreach (var item in Items) { item.Rectangle = homothety.Transform(item.Rectangle); item.InnerRectangle = homothety.Transform(item.InnerRectangle); item.Empty = homothety.Transform(item.Empty); } }
public TreemapItem AddItem(TreemapData data, Geometric.Point center, double radius) { TreemapItem item = new TreemapItem(center.X - radius, center.Y - radius, 2 * radius, 2 * radius) { Indexes = data.Indexes, Size = data.Size, Color = data.Color }; Items.Add(item); return item; }
private void SetShapeText(Excel.Shape shape, TreemapItem item) { TreemapIndex index = item.IndexParameters; shape.TextFrame2.WordWrap = Microsoft.Office.Core.MsoTriState.msoTrue; shape.TextFrame2.MarginBottom = 0.01f; shape.TextFrame2.MarginTop = 0.01f; shape.TextFrame2.MarginLeft = 0.01f; shape.TextFrame2.MarginRight = 0.01f; if (index.HasHeader && Parameters.Algorithm != TreemapAlgorithm.Circular) { shape.TextFrame.VerticalAlignment = Excel.XlVAlign.xlVAlignTop; } else { shape.TextFrame.VerticalAlignment = Excel.XlVAlign.xlVAlignCenter; } shape.TextFrame.HorizontalAlignment = Excel.XlHAlign.xlHAlignCenter; shape.TextFrame.Characters().Font.Bold = index.FontBold; shape.TextFrame.Characters().Font.Size = index.FontSize; shape.TextFrame.Characters().Font.Color = index.FontColor.ToRgb(); if (index.FontOutline) { shape.TextFrame2.TextRange.Font.Line.Visible = GetState(index.FontOutline); shape.TextFrame2.TextRange.Font.Line.ForeColor.RGB = index.FontOutlineColor.ToRgb(); shape.TextFrame2.TextRange.Font.Line.Weight = (float)index.FontOutlineWeight; } if (item.Items.Count == 0) { if (item.FillColor.GetBrightness() < 0.7) { shape.TextFrame.Characters().Font.Color = Color.White.ToRgb(); } else { shape.TextFrame.Characters().Font.Color = Color.Black.ToRgb(); } } string text = item.Indexes.Last(); float size = (float)index.FontSize; SizeF textSize = new Font(DefaultFontFamily, size).RenderText(text); int lines = (int)Math.Floor(textSize.Width / item.Rectangle.Width) + 1; while (size > 1 && lines * textSize.Height > item.Rectangle.Height) { size--; textSize = new Font(DefaultFontFamily, size).RenderText(text); lines = (int)Math.Floor(textSize.Width / item.Rectangle.Width) + 1; } if (size > 3) { shape.TextFrame.Characters().Text = text; shape.TextFrame.Characters().Font.Size = size; } }
private void SetShapeText(Excel.Shape shape, TreemapItem item) { TreemapIndex index = item.IndexParameters; shape.TextFrame2.WordWrap = Microsoft.Office.Core.MsoTriState.msoTrue; shape.TextFrame2.MarginBottom = 0.01f; shape.TextFrame2.MarginTop = 0.01f; shape.TextFrame2.MarginLeft = 0.01f; shape.TextFrame2.MarginRight = 0.01f; if (index.HasHeader && Parameters.Algorithm != TreemapAlgorithm.Circular) shape.TextFrame.VerticalAlignment = Excel.XlVAlign.xlVAlignTop; else shape.TextFrame.VerticalAlignment = Excel.XlVAlign.xlVAlignCenter; shape.TextFrame.HorizontalAlignment = Excel.XlHAlign.xlHAlignCenter; shape.TextFrame.Characters().Font.Bold = index.FontBold; shape.TextFrame.Characters().Font.Size = index.FontSize; shape.TextFrame.Characters().Font.Color = index.FontColor.ToRgb(); if (index.FontOutline) { shape.TextFrame2.TextRange.Font.Line.Visible = GetState(index.FontOutline); shape.TextFrame2.TextRange.Font.Line.ForeColor.RGB = index.FontOutlineColor.ToRgb(); shape.TextFrame2.TextRange.Font.Line.Weight = (float)index.FontOutlineWeight; } if (item.Items.Count == 0) { if (item.FillColor.GetBrightness() < 0.7) shape.TextFrame.Characters().Font.Color = Color.White.ToRgb(); else shape.TextFrame.Characters().Font.Color = Color.Black.ToRgb(); } string text = item.Indexes.Last(); float size = (float)index.FontSize; SizeF textSize = new Font(DefaultFontFamily, size).RenderText(text); int lines = (int)Math.Floor(textSize.Width / item.Rectangle.Width) + 1; while (size > 1 && lines * textSize.Height > item.Rectangle.Height) { size--; textSize = new Font(DefaultFontFamily, size).RenderText(text); lines = (int)Math.Floor(textSize.Width / item.Rectangle.Width) + 1; } if (size > 3) { shape.TextFrame.Characters().Text = text; shape.TextFrame.Characters().Font.Size = size; } }
private void Draw(TreemapItem item) { TreemapIndex index = item.IndexParameters; //Add background shapes if (!item.IsParent() && (index.HasHeader || item.IsChild() || Parameters.Algorithm == TreemapAlgorithm.Circular)) { Excel.Shape shape = AddShape(ShapeType, item.Rectangle, item.FillColor); SetShapeLine(shape, index.GetLineOptions()); SetShapeText(shape, item); } //Add Children Items foreach (var child in item.Items) Draw(child); //Add front shapes if (!item.IsParent() && !item.IsChild()) { Excel.Shape frontShape = AddShape(ShapeType, item.InnerRectangle, Color.Transparent); if (Parameters.Algorithm == TreemapAlgorithm.Circular) { frontShape.Line.Visible = GetState(false); SetShapeText(frontShape, item); } else if (!index.HasHeader) { SetShapeLine(frontShape, index.GetLineOptions()); SetShapeText(frontShape, item); } else //Case Header : inner border & no text SetShapeLine(frontShape, index.GetLineOptions().With(o => o.Weight = 1)); } }
public TreemapChart Build(double left, double top, double width, double height) { ChartArea = new Rect(left, top, width, height); BuildArea(); BuildTitle(Parameters); BuildLegend(Parameters); if (Parameters.Algorithm == TreemapAlgorithm.Circular) { double edge = Math.Min(PlotArea.Width, PlotArea.Height); double excessX = (PlotArea.Width - edge) / 2; double excessY = (PlotArea.Height - edge) / 2; PlotArea = new Rect(PlotArea.X + excessX, PlotArea.Y + excessY, edge, edge); } if (IsChartDegenerated()) return this; Parent = new TreemapItem(PlotArea.Left, PlotArea.Top, PlotArea.Width, PlotArea.Height); Parent.Size = Sizes.Sum(); Parent.IndexParameters = new TreemapIndex() { LineVisible = false, LineWeight = 0 }; IndexesComparer comparer = new IndexesComparer(); List<TreemapItem> items = new List<TreemapItem>() { Parent }; for (int i = 0; i < Indexes.Count; i++) { List<TreemapData> data = GetDepthData(i); foreach (TreemapItem item in items) { List<TreemapData> itemData = data.Where(d => comparer.Equals(d.Indexes.Take(i).ToList(), item.Indexes)).ToList(); item.ApplyAlgorithm(itemData, Parameters.Algorithm); } items = items.SelectMany(item => item.Items).ToList(); SetTreemapItemsParameters(i, items); } return this; }