/// <summary>
 /// Creates a new cluster with a minimum size within the specified parent cluster.  Clusters allow creating a subset of
 /// nodes that must be within a distinct rectangle.
 /// </summary>
 /// <param name="parentCluster">The cluster this cluster is to be a member of; if null, this is the root of a
 ///                             new hierarchy, otherwise must be non-NULL (perhaps DefaultClusterHierarchy).</param>
 /// <param name="userData">An object that is passed through.</param>
 /// <param name="minimumSize">Minimum cluster size along the primary axis.</param>
 /// <param name="minimumSizeP">Minimum cluster size along the perpendicular axis.</param>
 /// <param name="openBorderInfo">Information about the Left (if isHorizontal, else Top) border.</param>
 /// <param name="closeBorderInfo">Information about the Right (if isHorizontal, else Bottom) border.</param>
 /// <param name="openBorderInfoP">Same as OpenBorder, but in the secondary (Perpendicular) axis.</param>
 /// <param name="closeBorderInfoP">Same as CloseBorder, but in the secondary (Perpendicular) axis.</param>
 /// <returns>The new Cluster.</returns>
 /// 
 public OverlapRemovalCluster AddCluster(OverlapRemovalCluster parentCluster, object userData,
                     double minimumSize, double minimumSizeP,
                     BorderInfo openBorderInfo, BorderInfo closeBorderInfo,
                     BorderInfo openBorderInfoP, BorderInfo closeBorderInfoP)
 {
     var newCluster = new OverlapRemovalCluster(this.nextNodeId, parentCluster, userData, minimumSize, minimumSizeP,
                     this.Padding, this.PaddingP, this.ClusterPadding, this.ClusterPaddingP,
                     openBorderInfo, closeBorderInfo, openBorderInfoP, closeBorderInfoP);
     this.nextNodeId += OverlapRemovalCluster.NumInternalNodes;
     if (null == parentCluster)
     {
         this.clusterHierarchies.Add(newCluster);
     }
     else
     {
         // @@DCR: Enforce that Clusters live in only one hierarchy - they can have only one parent, so add a 
         //          Cluster.parentCluster to enforce this.
         parentCluster.AddNode(newCluster);
     }
     return newCluster;
 }
        public void AddNodeToCluster(OverlapRemovalCluster cluster, OverlapRemovalNode node)
        {
            // Node derives from Cluster so make sure we don't have this - the only way to create
            // cluster hierarchies is by AddCluster.
            ValidateArg.IsNotNull(cluster, "cluster");
            if (node is OverlapRemovalCluster)
            {
                throw new InvalidOperationException(
#if DEBUG
                        "Argument 'node' must not be a Cluster"
#endif // DEBUG
                        );
            }
            cluster.AddNode(node);
        }
 /// <summary>
 /// Add a new variable to the ConstraintGenerator.
 /// </summary>
 /// <param name="initialCluster">The cluster this node is to be a member of.  It may not be null; pass
 ///                     DefaultClusterHierarchy to create a node at the lowest level.  Subsequently a node 
 ///                     may be added to additional clusters, but only to one cluster per hierarchy.</param>
 /// <param name="userData">An object that is passed through.</param>
 /// <param name="position">Position of the node in the primary axis; if isHorizontal, it contains horizontal
 ///                     position and size, else it contains vertical position and size.</param>
 /// <param name="size">Size of the node in the primary axis.</param>
 /// <param name="positionP">Position of the node in the secondary (Perpendicular) axis.</param>
 /// <param name="sizeP">Size of the node in the secondary (Perpendicular) axis.</param>
 /// <param name="weight">Weight of the node (indicates how freely it should move).</param>
 /// <returns>The created node.</returns>
 public OverlapRemovalNode AddNode(OverlapRemovalCluster initialCluster, object userData, double position,
                     double positionP, double size, double sizeP, double weight)
 {
     ValidateArg.IsNotNull(initialCluster, "initialCluster");
     // @@PERF: Currently every node will have at least one constraint generated if there are any
     // other nodes along its line, regardless of whether the perpendicular coordinates result in overlap.
     // It might be worthwhile to add a check to avoid constraint generation in the case that there cannot
     // be such an overlap on a line, or if the nodes are separated by some amount of distance.
     Debug.Assert(null != initialCluster, "initialCluster must not be null");
     var nodNew = new OverlapRemovalNode(this.nextNodeId++, userData, position, positionP, size, sizeP, weight);
     initialCluster.AddNode(nodNew);
     return nodNew;
 }