static void DebugVerifyRectsDisjoint(Rectangle rect1, Rectangle rect2, double dblPaddingX, double dblPaddingY, double dblEpsilon)
 {
     rect1.PadWidth(dblPaddingX/2.0 - dblEpsilon);
     rect1.PadHeight(dblPaddingY/2.0 - dblEpsilon);
     rect2.PadWidth(dblPaddingX/2.0 - dblEpsilon);
     rect2.PadHeight(dblPaddingY/2.0 - dblEpsilon);
     Debug.Assert(!rect1.Intersects(rect2));
 }
         List<Event> CreateEvents(Solver solver, ref Rectangle boundaryRect)
        {
            var events = new List<Event>();
            int cNodes = this.nodeList.Count; // cache for perf
            double leftBorderWidth = CalcBorderWidth(this.OpenBorderInfo.InnerMargin);
            double rightBorderWidth = CalcBorderWidth(this.CloseBorderInfo.InnerMargin);
            double openBorderWidth = CalcBorderWidth(this.OpenBorderInfoP.InnerMargin);
            double closeBorderWidth = CalcBorderWidth(this.CloseBorderInfoP.InnerMargin);
            for (int nodeIndex = 0; nodeIndex < cNodes; ++nodeIndex)
            {
                OverlapRemovalNode node = this.nodeList[nodeIndex];
                var cluster = node as OverlapRemovalCluster;
                if (null != cluster)
                {
                    // Child Clusters have already "recursively" been processed before the current cluster,
                    // so we just need to check to see if it had any events.  If so, then it has created its
                    // two fake nodes (and their variables) along the primary axis, but these are only put
                    // into the event list at the nested level; at this level, we put Node underlying the 
                    // entire Cluster span (in both directions) into the event list.

                    // If a child cluster is empty, it will have zero size and no way to set its position.
                    // That includes clusters containing nothing but empty clusters.  We skip those here.
                    if (!cluster.IsInSolver)
                    {
                        continue;
                    }
                }
                else
                {
                    // Not a cluster; just have it add its variable to the solver.
                    node.CreateVariable(solver);
                }

                // Now add the Node to the ScanLine event list.  Use paddingP because the scan line moves
                // perpendicularly to the direction we're generating the constraints in.
                AddEvents(node, events);

                // Update our boundaries if this node goes past any of them.
                if (!this.IsRootCluster)
                {
                    double pad = node.Size / 2 + ClusterPadding;
                    double padP = node.SizeP / 2 + ClusterPaddingP;
                    double newLeft = node.Position - pad - leftBorderWidth;
                    double newRight = node.Position + pad + rightBorderWidth;
                    double newBottom = node.PositionP - padP - openBorderWidth;
                    double newTop = node.PositionP + padP + closeBorderWidth;

                    boundaryRect.Left = Math.Min(boundaryRect.Left, newLeft);
                    boundaryRect.Right = Math.Max(boundaryRect.Right, newRight);
                    boundaryRect.Bottom = Math.Min(boundaryRect.Bottom, newBottom);
                    boundaryRect.Top = Math.Max(boundaryRect.Top, newTop);

#if VERBOSE
                    Console.WriteLine(" {0} BoundaryRect after AddEvents: L/R T/B {1:F5}/{2:F5} {3:F5}/{4:F5}"
                            , this.Name, boundaryRect.Left, boundaryRect.Right, boundaryRect.Top, boundaryRect.Bottom);
#endif
                }
            }
            if (!this.IsRootCluster)
            {
                // Force the cluster borders to the full minimum sizes if any were specified.
                // Without the full cluster boundaries being available at constraint generation time, Tuvalu was
                // getting unresolved overlaps when dragging an external node over the corner of a cluster boundary.
                double padMinSize = this.MinimumSize - boundaryRect.Width;
                if (padMinSize > 0)
                {
                    boundaryRect.PadWidth(padMinSize / 2);
                }
                double padMinSizeP = this.MinimumSizeP - boundaryRect.Height;
                if (padMinSizeP > 0)
                {
                    boundaryRect.PadHeight(padMinSizeP / 2);
                }

#if VERBOSE
                Console.WriteLine(" {0} BoundaryRect after CreateEvents: L/R T/B {1:F5}/{2:F5} {3:F5}/{4:F5}"
                        , this.Name, boundaryRect.Left, boundaryRect.Right, boundaryRect.Top, boundaryRect.Bottom);
#endif

            }

            return events;
        }
 static void DebugVerifyRectContains(Rectangle rectOuter, Rectangle rectInner, double dblPaddingX, double dblPaddingY, double dblEpsilon)
 {
     rectInner.PadWidth(dblPaddingX/2.0 - dblEpsilon);
     rectInner.PadHeight(dblPaddingY/2.0 - dblEpsilon);
     Debug.Assert(rectOuter.Contains(rectInner)
                 , "Inner Node/Cluster rectangle is not contained within outer Cluster"
                 );
 }
 internal void UpdateBoundary(Rectangle bounds) {
     Rectangle r = bounds;
     if (RectangularBoundary != null) {
         r = new Rectangle(
             r.Left - RectangularBoundary.LeftMargin,
             r.Bottom - RectangularBoundary.BottomMargin,
             r.Right + RectangularBoundary.RightMargin,
             r.Top + RectangularBoundary.TopMargin);
         double widthPad = (RectangularBoundary.MinWidth - r.Width)/2;
         if (widthPad > 0) {
             r.PadWidth(widthPad);
         }
         double heightPad = (RectangularBoundary.MinHeight - r.Height)/2;
         if (heightPad > 0) {
             r.PadHeight(heightPad);
         }
         RectangularBoundary.Rect = r;
     }
     BoundingBox = r;
 }