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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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;
 }
Beispiel #6
0
        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;
        }