/// <summary>
 /// Copies the labels from <paramref name="source"/> to <paramref name="target"/>.
 /// </summary>
 /// <param name="source"></param>
 /// <param name="target"></param>
 private void CopyLabels(INode source, INode target)
 {
     foreach (var label in source.Labels)
     {
         AggregateGraph.AddLabel(target, label.Text, FreeNodeLabelModel.Instance.CreateDefaultParameter(), label.Style);
     }
 }
        /// <summary>
        /// Aggregates the <paramref name="aggregate"/> as well as all its children recursively.
        /// </summary>
        /// <remarks>
        /// Can be used to apply the initial aggregation. If this is not the initial aggregation run, it will reuse existing
        /// aggregation nodes.
        /// </remarks>
        /// <param name="aggregate">The "root" aggregate.</param>
        /// <returns>The aggregation node representing the passed <paramref name="aggregate"/></returns>
        public INode AggregateRecursively(NodeAggregation.Aggregate aggregate)
        {
            if (aggregate.Children.Count == 0)
            {
                return(aggregate.Node);
            }

            PointD originalCenter;

            if (aggregateToNode.TryGetValue(aggregate, out var node))
            {
                originalCenter = node.Layout.GetCenter();
                var aggregationInfo = (AggregationNodeInfo)node.Tag;
                if (aggregationInfo.IsAggregated)
                {
                    return(node);
                }
                else
                {
                    AggregateGraph.Separate(node);
                }
            }
            else
            {
                originalCenter = PointD.Origin;
            }

            var nodesToAggregate = aggregate.Children.Select(AggregateRecursively).ToList();

            if (aggregate.Node != null)
            {
                nodesToAggregate.Add(aggregate.Node);
            }

            var size            = 30 + Math.Sqrt(aggregate.DescendantWeightSum) * 4;
            var layout          = RectD.FromCenter(originalCenter, new SizeD(size, size));
            var aggregationNode =
                AggregateGraph.Aggregate(new ListEnumerable <INode>(nodesToAggregate), layout, AggregationNodeStyle);

            aggregateToNode[aggregate] = aggregationNode;
            aggregationNode.Tag        = new AggregationNodeInfo(aggregate, true);

            if (aggregate.Node != null)
            {
                placeholderMap[aggregate.Node] = aggregationNode;
                CopyLabels(aggregate.Node, aggregationNode);
            }
            else
            {
                var maxChild = GetMostImportantDescendant(aggregate);
                if (maxChild.Node != null && maxChild.Node.Labels.Any())
                {
                    AggregateGraph.AddLabel(aggregationNode, $"({maxChild.Node.Labels[0].Text}, …)",
                                            FreeNodeLabelModel.Instance.CreateDefaultParameter(), DescendantLabelStyle);
                }
            }

            return(aggregationNode);
        }