/// <summary>
        /// Recursively lay out the given clusters using the specified settings for each cluster, or if none is given for a particular
        /// cluster then inherit from the cluster's ancestor - or from the specifed defaultSettings.
        /// Clusters (other than the root) will be translated (together with their descendants) such that their 
        /// bottom-left point of their new boundaries are the same as the bottom-left of their old boundaries 
        /// (i.e. clusters are laid-out in place).
        /// </summary>
        /// <param name="graph">The graph being operated on.</param>
        /// <param name="clusters">The clusters to layout.</param>
        /// <param name="clusterSettings">Settings to use for each cluster and its descendents (if none provided for that descendent.</param>
        public InitialLayoutByCluster(GeometryGraph graph, IEnumerable<Cluster> clusters,
            Func<Cluster, LayoutAlgorithmSettings> clusterSettings) {
            ValidateArg.IsNotNull(graph, "graph");
            ValidateArg.IsNotNull(clusters, "clusters");
            ValidateArg.IsNotNull(clusterSettings, "clusterSettings");
#if TEST_MSAGL
            graph.SetDebugIds();
#endif

            this.graph = graph;
            this.clusters = clusters.ToList();
            this.clusterSettings = clusterSettings;
        }
        /// <summary>
        /// Recursively lay out the given clusters using the specified settings for each cluster, or if none is given for a particular
        /// cluster then inherit from the cluster's ancestor - or from the specifed defaultSettings.
        /// Clusters (other than the root) will be translated (together with their descendants) such that their 
        /// bottom-left point of their new boundaries are the same as the bottom-left of their old boundaries 
        /// (i.e. clusters are laid-out in place).
        /// </summary>
        /// <param name="graph">The graph being operated on.</param>
        /// <param name="modifiedNodes">The nodes whose bounds are modified.</param>
        /// <param name="addedNodes">Nodes added to the graph - a new initial position will be found for these nodes close to their neighbors</param>
        /// <param name="clusterSettings">Settings to use for each cluster.</param>
        public Relayout(GeometryGraph graph, IEnumerable<Node> modifiedNodes, IEnumerable<Node> addedNodes,
            Func<Cluster, LayoutAlgorithmSettings> clusterSettings) {
            ValidateArg.IsNotNull(graph, "graph");
            ValidateArg.IsNotNull(clusterSettings, "clusterSettings");
#if TEST_MSAGL
            graph.SetDebugIds();
#endif
            this.graph = graph;
            this.modifiedNodes = modifiedNodes;
            this.clusterSettings = clusterSettings;
            ancestorsOfModifiedNodes =
                new Set<Cluster>(modifiedNodes.SelectMany(v => v.AllClusterAncestors));
            if (addedNodes == null) return;
        
            foreach (var v in addedNodes)
                CreateOrGetAddedChildrenOfParent(v.ClusterParents.First()).Add(v);
            ancestorsOfModifiedNodes.InsertRange(addedNodes.SelectMany(v => v.AllClusterAncestors));
        }