コード例 #1
0
ファイル: RectanglePacker.cs プロジェクト: cataclys/XFrame
 private void filterSelfSubAreas(List <IntegerRectangle> areas)
 {
     for (int i = areas.Count - 1; i >= 0; i--)
     {
         IntegerRectangle filtered = areas[i];
         for (int j = areas.Count - 1; j >= 0; j--)
         {
             if (i != j)
             {
                 IntegerRectangle area = areas[j];
                 if (filtered.x >= area.x && filtered.y >= area.y && filtered.right <= area.right && filtered.bottom <= area.bottom)
                 {
                     freeRectangle(filtered);
                     IntegerRectangle topOfStack = areas.Pop();
                     if (i < areas.Count)
                     {
                         // Move the one on the top to the freed position
                         areas[i] = topOfStack;
                     }
                     break;
                 }
             }
         }
     }
 }
コード例 #2
0
        public IntegerRectangle GetRectangle(int index, IntegerRectangle rectangle)
        {
            IntegerRectangle inserted = m_InsertedRectangles[index];

            rectangle.x      = inserted.x;
            rectangle.y      = inserted.y;
            rectangle.width  = inserted.width;
            rectangle.height = inserted.height;
            return(rectangle);
        }
コード例 #3
0
 public IntegerRectangle AllocateIntegerRectangle(int x, int y, int width, int height)
 {
     if (m_IntegerRectangleList.Count > 0)
     {
         IntegerRectangle rectangle = m_IntegerRectangleList.Pop();
         rectangle.x      = x;
         rectangle.y      = y;
         rectangle.width  = width;
         rectangle.height = height;
     }
     return(new IntegerRectangle(x, y, width, height));
 }
コード例 #4
0
        public int packRectangles(bool sort = true)
        {
            if (sort)
            {
                mInsertList.Sort((emp1, emp2) => emp1.width.CompareTo(emp2.width));
            }

            while (mInsertList.Count > 0)
            {
                SortableSize sortableSize = mInsertList.Pop();

                int width  = sortableSize.width;
                int height = sortableSize.height;

                int index = getFreeAreaIndex(width, height);

                if (index >= 0)
                {
                    IntegerRectangle freeArea = mFreeAreas[index];
                    IntegerRectangle target   = allocateRectangle(freeArea.x, freeArea.y, width, height);

                    target.id = sortableSize.id;

                    // Generate the new free areas, these are parts of the old ones intersected or touched by the target
                    generateNewFreeAreas(target, mFreeAreas, mNewFreeAreas);

                    while (mNewFreeAreas.Count > 0)
                    {
                        mFreeAreas.Add(mNewFreeAreas.Pop());
                    }

                    mInsertedRectangles.Add(target);

                    if (target.right > mPackedWidth)
                    {
                        mPackedWidth = target.right;
                    }

                    if (target.bottom > mPackedHeight)
                    {
                        mPackedHeight = target.bottom;
                    }
                }

                freeSize(sortableSize);
            }

            return(rectangleCount);
        }
コード例 #5
0
ファイル: RectanglePacker.cs プロジェクト: cataclys/XFrame
        private IntegerRectangle allocateRectangle(int x, int y, int width, int height)
        {
            if (mRectangleStack.Count > 0)
            {
                IntegerRectangle rectangle = mRectangleStack.Pop();
                rectangle.x      = x;
                rectangle.y      = y;
                rectangle.width  = width;
                rectangle.height = height;
                rectangle.right  = x + width;
                rectangle.bottom = y + height;

                return(rectangle);
            }

            return(new IntegerRectangle(x, y, width, height));
        }
コード例 #6
0
ファイル: RectanglePacker.cs プロジェクト: cataclys/XFrame
        private void generateDividedAreas(IntegerRectangle divider, IntegerRectangle area, List <IntegerRectangle> results)
        {
            int count = 0;

            int rightDelta = area.right - divider.right;

            if (rightDelta > 0)
            {
                results.Add(allocateRectangle(divider.right, area.y, rightDelta, area.height));
                count++;
            }

            int leftDelta = divider.x - area.x;

            if (leftDelta > 0)
            {
                results.Add(allocateRectangle(area.x, area.y, leftDelta, area.height));
                count++;
            }

            int bottomDelta = area.bottom - divider.bottom;

            if (bottomDelta > 0)
            {
                results.Add(allocateRectangle(area.x, divider.bottom, area.width, bottomDelta));
                count++;
            }

            int topDelta = divider.y - area.y;

            if (topDelta > 0)
            {
                results.Add(allocateRectangle(area.x, area.y, area.width, topDelta));
                count++;
            }

            if (count == 0 && (divider.width < area.width || divider.height < area.height))
            {
                // Only touching the area, store the area itself
                results.Add(area);
            }
            else
            {
                freeRectangle(area);
            }
        }
コード例 #7
0
        public int PackRectangles(bool sort = true)
        {
            if (sort)
            {
                m_InsertList.Sort((emp1, emp2) => emp1.width.CompareTo(emp2.width));
            }

            while (m_InsertList.Count > 0)
            {
                SortableSize sortableSize = m_InsertList.Pop();
                int          width        = sortableSize.width;
                int          height       = sortableSize.height;

                int index = GetFreeAreaIndex(width, height);//根据W,H 得到下标
                if (index >= 0)
                {
                    IntegerRectangle freeArea = m_FreeAreas[index];//得到一个可以容纳target的Area
                    IntegerRectangle target   = RectanglePackerMgr.S.AllocateIntegerRectangle(freeArea.x, freeArea.y, width, height);
                    target.id = sortableSize.id;

                    // Generate the new free areas, these are parts of the old ones intersected or touched by the target
                    GenerateNewFreeAreas(target, m_TempFreeAreas);

                    while (m_TempFreeAreas.Count > 0)
                    {
                        m_FreeAreas.Add(m_TempFreeAreas.Pop());
                    }

                    m_InsertedRectangles.Add(target);

                    if (target.right > m_PackedWidth)
                    {
                        m_PackedWidth = target.right;
                    }

                    if (target.top > m_PackedHeight)
                    {
                        m_PackedHeight = target.top;
                    }
                }

                RectanglePackerMgr.S.ReleaseSize(sortableSize);
            }

            return(rectangleCount);
        }
コード例 #8
0
        private int getFreeAreaIndex(int width, int height)
        {
            IntegerRectangle best = mOutsideRectangle;
            int index             = -1;

            int paddedWidth  = width + mPadding;
            int paddedHeight = height + mPadding;

            int count = mFreeAreas.Count;

            for (int i = count - 1; i >= 0; i--)
            {
                IntegerRectangle free = mFreeAreas[i];

                if (free.x < mPackedWidth || free.y < mPackedHeight)
                {
                    // Within the packed area, padding required
                    if (free.x < best.x && paddedWidth <= free.width && paddedHeight <= free.height)
                    {
                        index = i;
                        if ((paddedWidth == free.width && free.width <= free.height && free.right < mWidth) || (paddedHeight == free.height && free.height <= free.width))
                        {
                            break;
                        }

                        best = free;
                    }
                }
                else
                {
                    // Outside the current packed area, no padding required
                    if (free.x < best.x && width <= free.width && height <= free.height)
                    {
                        index = i;
                        if ((width == free.width && free.width <= free.height && free.right < mWidth) || (height == free.height && free.height <= free.width))
                        {
                            break;
                        }

                        best = free;
                    }
                }
            }

            return(index);
        }
コード例 #9
0
        private void GenerateNewFreeAreas(IntegerRectangle target, List <IntegerRectangle> results)
        {
            // Increase dimensions by one to get the areas on right / bottom this rectangle touches
            // Also add the padding here
            int x     = target.x;
            int y     = target.y;
            int right = target.right + 1 + m_Padding;
            int top   = target.top + 1 + m_Padding;

            IntegerRectangle targetWithPadding = null;

            if (m_Padding == 0)
            {
                targetWithPadding = target;
            }

            for (int i = m_FreeAreas.Count - 1; i >= 0; i--)
            {
                IntegerRectangle area = m_FreeAreas[i];
                if (!(x >= area.right || right <= area.x || y >= area.top || top <= area.y))
                {
                    UnityEngine.Debug.LogError(target.x + ":" + area.x);
                    if (targetWithPadding == null)
                    {
                        targetWithPadding = RectanglePackerMgr.S.AllocateIntegerRectangle(target.x, target.y, target.width + m_Padding, target.height + m_Padding);
                    }

                    GenerateDividedAreas(targetWithPadding, area, results);
                    IntegerRectangle topOfStack = m_FreeAreas.Pop();
                    if (i < m_FreeAreas.Count)
                    {
                        // Move the one on the top to the freed position
                        m_FreeAreas[i] = topOfStack;
                    }
                }
            }

            if (targetWithPadding != null && targetWithPadding != target)
            {
                RectanglePackerMgr.S.ReleaseIntegerRectangle(targetWithPadding);
            }

            FilterSelfSubAreas(results);
        }
コード例 #10
0
ファイル: RectanglePacker.cs プロジェクト: cataclys/XFrame
        private void generateNewFreeAreas(IntegerRectangle target, List <IntegerRectangle> areas, List <IntegerRectangle> results)
        {
            // Increase dimensions by one to get the areas on right / bottom this rectangle touches
            // Also add the padding here
            int x      = target.x;
            int y      = target.y;
            int right  = target.right + 1 + mPadding;
            int bottom = target.bottom + 1 + mPadding;

            IntegerRectangle targetWithPadding = null;

            if (mPadding == 0)
            {
                targetWithPadding = target;
            }

            for (int i = areas.Count - 1; i >= 0; i--)
            {
                IntegerRectangle area = areas[i];
                if (!(x >= area.right || right <= area.x || y >= area.bottom || bottom <= area.y))
                {
                    if (targetWithPadding == null)
                    {
                        targetWithPadding = allocateRectangle(target.x, target.y, target.width + mPadding, target.height + mPadding);
                    }

                    generateDividedAreas(targetWithPadding, area, results);
                    IntegerRectangle topOfStack = areas.Pop();
                    if (i < areas.Count)
                    {
                        // Move the one on the top to the freed position
                        areas[i] = topOfStack;
                    }
                }
            }

            if (targetWithPadding != null && targetWithPadding != target)
            {
                freeRectangle(targetWithPadding);
            }

            filterSelfSubAreas(results);
        }
コード例 #11
0
ファイル: RectanglePacker.cs プロジェクト: cataclys/XFrame
 public RectanglePacker(int width, int height, int padding = 0)
 {
     mOutsideRectangle = new IntegerRectangle(width + 1, height + 1, 0, 0);
     reset(width, height, padding);
 }
コード例 #12
0
ファイル: RectanglePacker.cs プロジェクト: cataclys/XFrame
 private void freeRectangle(IntegerRectangle rectangle)
 {
     mRectangleStack.Add(rectangle);
 }
コード例 #13
0
ファイル: RectanglePacker.cs プロジェクト: cataclys/XFrame
        public int getRectangleId(int index)
        {
            IntegerRectangle inserted = mInsertedRectangles[index];

            return(inserted.id);
        }
コード例 #14
0
        // public int packedWidth { get { return mPackedWidth; } }
        // public int packedHeight { get { return mPackedHeight; } }
        // public int padding { get { return mPadding; } }

        public RectanglePacker(int width, int height, int padding = 0)
        {
            mOutsideRectangle = RectanglePackerMgr.S.AllocateIntegerRectangle(width + 1, height + 1, 0, 0);
            Reset(width, height, padding);
        }
コード例 #15
0
 public void ReleaseIntegerRectangle(IntegerRectangle rectangle)
 {
     m_IntegerRectangleList.Add(rectangle);
 }