Esempio n. 1
0
            /// <summary>Attempts to add a rectangle of the given size to this node. The X and Y offsets keep track of the
            /// offset of this node from the origin.
            /// </summary>
            public Point?TryAdd(int width, int height, int spacing)
            {
                if (width > this.Width || height > this.Height)
                {
                    return(null);
                }

                if (RectangleStored)
                {
                    // if this node has a rectangle stored here already, delegate to the children
                    if (Child1 != null) // try adding it to the right first
                    {
                        Point?pt = Child1.TryAdd(width, height, spacing);
                        // as an optimization, we'll prevent degenerate subtrees (linked lists) from forming by replacing this
                        // child with our grandchild if it's an only child, or removing this child if we have no grandchildren
                        if (pt.HasValue && (Child1.Child1 == null || Child1.Child2 == null))
                        {
                            Child1 = Child1.Child1 == null ? Child1.Child2 : Child1.Child1;
                            if (Child1 != null)
                            {
                                Child1.Parent = this;
                            }
                        }
                        if (pt.HasValue || Child2 == null)
                        {
                            return(pt);
                        }
                    }

                    if (Child2 != null) // if we couldn't add it to the first child, try adding it to the second
                    {
                        Point?pt = Child2.TryAdd(width, height, spacing);
                        if (pt.HasValue)
                        {
                            // prevent degenerate subtrees (linked lists) from forming (see comment above for details)
                            if (Child2.Child1 == null || Child2.Child2 == null)
                            {
                                Child2 = Child2.Child1 == null ? Child2.Child2 : Child2.Child1;
                                if (Child2 != null)
                                {
                                    Child2.Parent = this;
                                }
                            }
                        }
                        return(pt);
                    }

                    return(null);
                }
                else // this node does not have a rectangle stored here yet, so store it here and subdivide this space
                {
                    // only add children if they'd have a non-empty area
                    if (this.Width > width + spacing)
                    {
                        Child1 = new Node(this, X + (width + spacing), Y, this.Width - (width + spacing), height);
                    }
                    if (this.Height > height + spacing)
                    {
                        Child2 = new Node(this, X, Y + (height + spacing), this.Width, this.Height - (height + spacing));
                    }
                    RectangleStored = true;
                    return(new Point(X, Y));
                }
            }