Exemplo n.º 1
0
 /// <summary>
 /// Frees the specified old rectangle.
 /// </summary>
 /// <param name="oldRectangle">The old rectangle.</param>
 public void Free(ref Rectangle oldRectangle)
 {
     freeRectangles.Add(oldRectangle);
 }
Exemplo n.º 2
0
 /// <summary>
 /// Tries to fit a single rectangle with the specified width and height.
 /// </summary>
 /// <param name="width">Width requested.</param>
 /// <param name="height">Height requested</param>
 /// <param name="bestRectangle">Fill with the rectangle if it was successfully inserted.</param>
 /// <returns><c>true</c> if it was successfully inserted.</returns>
 public bool Insert(int width, int height, ref Rectangle bestRectangle)
 {
     return(Insert(width, height, freeRectangles, ref bestRectangle));
 }
Exemplo n.º 3
0
        private static bool Insert(int width, int height, List <Rectangle> freeRectanglesList, ref Rectangle bestRectangle)
        {
            // Info on algorithm: http://clb.demon.fi/files/RectangleBinPack.pdf
            int bestScore          = int.MaxValue;
            int freeRectangleIndex = -1;

            // Find space for new rectangle
            for (int i = 0; i < freeRectanglesList.Count; ++i)
            {
                var currentFreeRectangle = freeRectanglesList[i];
                if (width == currentFreeRectangle.Width && height == currentFreeRectangle.Height)
                {
                    // Perfect fit
                    bestRectangle.X      = currentFreeRectangle.X;
                    bestRectangle.Y      = currentFreeRectangle.Y;
                    bestRectangle.Width  = width;
                    bestRectangle.Height = height;
                    freeRectangleIndex   = i;
                    break;
                }
                if (width <= currentFreeRectangle.Width && height <= currentFreeRectangle.Height)
                {
                    // Can fit inside
                    // Use "BAF" heuristic (best area fit)
                    var score = currentFreeRectangle.Width * currentFreeRectangle.Height - width * height;
                    if (score < bestScore)
                    {
                        bestRectangle.X      = currentFreeRectangle.X;
                        bestRectangle.Y      = currentFreeRectangle.Y;
                        bestRectangle.Width  = width;
                        bestRectangle.Height = height;
                        bestScore            = score;
                        freeRectangleIndex   = i;
                    }
                }
            }

            // No space could be found
            if (freeRectangleIndex == -1)
            {
                return(false);
            }

            var freeRectangle = freeRectanglesList[freeRectangleIndex];

            // Choose an axis to split (trying to minimize the smaller area "MINAS")
            int w = freeRectangle.Width - bestRectangle.Width;
            int h = freeRectangle.Height - bestRectangle.Height;
            var splitHorizontal = (bestRectangle.Width * h > w * bestRectangle.Height);

            // Form the two new rectangles.
            var bottom = new Rectangle {
                X = freeRectangle.X, Y = freeRectangle.Y + bestRectangle.Height, Width = splitHorizontal ? freeRectangle.Width : bestRectangle.Width, Height = h
            };
            var right = new Rectangle {
                X = freeRectangle.X + bestRectangle.Width, Y = freeRectangle.Y, Width = w, Height = splitHorizontal ? bestRectangle.Height : freeRectangle.Height
            };

            if (bottom.Width > 0 && bottom.Height > 0)
            {
                freeRectanglesList.Add(bottom);
            }
            if (right.Width > 0 && right.Height > 0)
            {
                freeRectanglesList.Add(right);
            }

            // Remove previously selected freeRectangle
            if (freeRectangleIndex != freeRectanglesList.Count - 1)
            {
                freeRectanglesList[freeRectangleIndex] = freeRectanglesList[freeRectanglesList.Count - 1];
            }
            freeRectanglesList.RemoveAt(freeRectanglesList.Count - 1);

            return(true);
        }