コード例 #1
0
 public MaxRectsBinPack(int width, int height, FreeRectChoiceHeuristic method, IComparer<Rect> comparer)
 {
     binWidth = width;
     binHeight = height;
     Method = method;
     var n = new Rect(0, 0, width, height);
     FreeBoxes.Add(n);
     this.comparer = comparer;
 }
コード例 #2
0
ファイル: Rect.cs プロジェクト: SvenPetroll/Pack-O-Tron
        public int CompareRectShortSide(Rect a, Rect b)
        {
            int smallerSideA = Math.Min(a.width, a.height);
            int smallerSideB = Math.Min(b.width, b.height);

            if (smallerSideA != smallerSideB)
                return smallerSideA.CompareTo(smallerSideB);

            // Tie-break on the larger side.
            int largerSideA = Math.Max(a.width, a.height);
            int largerSideB = Math.Max(b.width, b.height);

            return largerSideA.CompareTo(largerSideB);
        }
コード例 #3
0
        public Rect FindPositionForNewNodeBestAreaFit(int width, int height, ref int bestAreaFit, ref int bestShortSideFit)
        {
            Rect bestNode = new Rect();

            bestAreaFit = int.MaxValue;

            foreach (Rect rect in FreeBoxes)
            {
                int areaFit = rect.width*rect.height - width*height;

                // Try to place the rectangle in upright (non-flipped) orientation.
                if (rect.width >= width && rect.height >= height)
                {
                    int leftoverHoriz = Math.Abs(rect.width - width);
                    int leftoverVert = Math.Abs(rect.height - height);
                    int shortSideFit = Math.Min(leftoverHoriz, leftoverVert);

                    if (areaFit < bestAreaFit || (areaFit == bestAreaFit && shortSideFit < bestShortSideFit))
                    {
                        bestNode.x = rect.x;
                        bestNode.y = rect.y;
                        bestNode.width = width;
                        bestNode.height = height;
                        bestShortSideFit = shortSideFit;
                        bestAreaFit = areaFit;
                    }
                }

                if (rect.width >= height && rect.height >= width)
                {
                    int leftoverHoriz = Math.Abs(rect.width - height);
                    int leftoverVert = Math.Abs(rect.height - width);
                    int shortSideFit = Math.Min(leftoverHoriz, leftoverVert);

                    if (areaFit < bestAreaFit || (areaFit == bestAreaFit && shortSideFit < bestShortSideFit))
                    {
                        bestNode.x = rect.x;
                        bestNode.y = rect.y;
                        bestNode.width = height;
                        bestNode.height = width;
                        bestShortSideFit = shortSideFit;
                        bestAreaFit = areaFit;
                    }
                }
            }
            return bestNode;
        }
コード例 #4
0
ファイル: Rect.cs プロジェクト: SvenPetroll/Pack-O-Tron
 public static bool IsContainedIn(Rect a, Rect b)
 {
     return a.x >= b.x && a.y >= b.y
            && a.x + a.width <= b.x + b.width
            && a.y + a.height <= b.y + b.height;
 }
コード例 #5
0
ファイル: Rect.cs プロジェクト: SvenPetroll/Pack-O-Tron
 public Rect(Rect b)
     : this(b.x, b.y, b.width, b.height)
 {
 }
コード例 #6
0
        private Rect ScoreRect(int width, int height, FreeRectChoiceHeuristic method, out int score1, out int score2)
        {
            Rect newNode = new Rect();
            score1 = int.MaxValue;
            score2 = int.MaxValue;
            switch (method)
            {
                case FreeRectChoiceHeuristic.RectBestShortSideFit:
                    newNode = FindPositionForNewNodeBestShortSideFit(width, height, ref score1, ref score2);
                    break;
                case FreeRectChoiceHeuristic.RectBestLongSideFit:
                    newNode = FindPositionForNewNodeBestLongSideFit(width, height, ref score2, ref score1);
                    break;
                case FreeRectChoiceHeuristic.RectBestAreaFit:
                    newNode = FindPositionForNewNodeBestAreaFit(width, height, ref score1, ref score2);
                    break;
            }

            // Cannot fit the current rectangle.
            if (newNode == null)
            {
                score1 = int.MaxValue;
                score2 = int.MaxValue;
            }

            return newNode;
        }
コード例 #7
0
        public bool SplitFreeNode(Rect freeNode, Rect usedNode)
        {
            // Test with SAT if the rectangles even intersect.
            if (usedNode.x >= freeNode.x + freeNode.width || usedNode.x + usedNode.width <= freeNode.x ||
                usedNode.y >= freeNode.y + freeNode.height || usedNode.y + usedNode.height <= freeNode.y)
                return false;

            if (usedNode.x < freeNode.x + freeNode.width && usedNode.x + usedNode.width > freeNode.x)
            {
                // New node at the top side of the used node.
                if (usedNode.y > freeNode.y && usedNode.y < freeNode.y + freeNode.height)
                {
                    Rect newNode = new Rect(freeNode);
                    newNode.height = usedNode.y - newNode.y;
                    FreeBoxes.Add(newNode);
                }

                // New node at the bottom side of the used node.
                if (usedNode.y + usedNode.height < freeNode.y + freeNode.height)
                {
                    Rect newNode = new Rect(freeNode);
                    newNode.y = usedNode.y + usedNode.height;
                    newNode.height = freeNode.y + freeNode.height - (usedNode.y + usedNode.height);
                    FreeBoxes.Add(newNode);
                }
            }

            if (usedNode.y < freeNode.y + freeNode.height && usedNode.y + usedNode.height > freeNode.y)
            {
                // New node at the left side of the used node.
                if (usedNode.x > freeNode.x && usedNode.x < freeNode.x + freeNode.width)
                {
                    Rect newNode = new Rect(freeNode);
                    newNode.width = usedNode.x - newNode.x;
                    FreeBoxes.Add(newNode);
                }

                // New node at the right side of the used node.
                if (usedNode.x + usedNode.width < freeNode.x + freeNode.width)
                {
                    Rect newNode = new Rect(freeNode);
                    newNode.x = usedNode.x + usedNode.width;
                    newNode.width = freeNode.x + freeNode.width - (usedNode.x + usedNode.width);
                    FreeBoxes.Add(newNode);
                }
            }

            return true;
        }
コード例 #8
0
        public void PlaceRect(Rect node)
        {
            int numRectanglesToProcess = FreeBoxes.Count;
            for (int i = 0; i < numRectanglesToProcess; ++i)
            {
                if (SplitFreeNode(FreeBoxes[i], node))
                {
                    FreeBoxes.RemoveAt(i);
                    --i;
                    --numRectanglesToProcess;
                }
            }

            PruneFreeList();

            UsedBoxes.Add(node);
        }
コード例 #9
0
        public bool Insert(List<Rect> rects)
        {
            UsedBoxes.Clear();
            rects.Sort(comparer);
            while (rects.Count > 0)
            {
                int bestScore1 = int.MaxValue;
                int bestScore2 = int.MaxValue;
                int bestRectIndex = -1;
                Rect bestNode = new Rect();

                for (int i = 0; i < rects.Count; ++i)
                {
                    int score1 = 0;
                    int score2 = 0;
                    Rect newNode = new Rect(ScoreRect(rects[i].width, rects[i].height, Method, out score1, out score2));

                    if (score1 < bestScore1 || (score1 == bestScore1 && score2 < bestScore2))
                    {
                        bestScore1 = score1;
                        bestScore2 = score2;
                        bestNode = newNode;
                        bestRectIndex = i;
                    }
                }

                if (bestRectIndex == -1)
                    return false;

                PlaceRect(bestNode);
                rects.RemoveAt(bestRectIndex);
            }
            return true;
        }
コード例 #10
0
        public Rect FindPositionForNewNodeContactPoint(int width, int height, ref int bestContactScore)
        {
            Rect bestNode = new Rect();

            bestContactScore = -1;

            for (int i = 0; i < FreeBoxes.Count; ++i)
            {
                // Try to place the rectangle in upright (non-flipped) orientation.
                if (FreeBoxes[i].width >= width && FreeBoxes[i].height >= height)
                {
                    int score = ContactPointScoreNode(FreeBoxes[i].x, FreeBoxes[i].y, width, height);
                    if (score > bestContactScore)
                    {
                        bestNode.x = FreeBoxes[i].x;
                        bestNode.y = FreeBoxes[i].y;
                        bestNode.width = width;
                        bestNode.height = height;
                        bestContactScore = score;
                    }
                }
                if (FreeBoxes[i].width >= height && FreeBoxes[i].height >= width)
                {
                    int score = ContactPointScoreNode(FreeBoxes[i].x, FreeBoxes[i].y, width, height);
                    if (score > bestContactScore)
                    {
                        bestNode.x = FreeBoxes[i].x;
                        bestNode.y = FreeBoxes[i].y;
                        bestNode.width = height;
                        bestNode.height = width;
                        bestContactScore = score;
                    }
                }
            }
            return bestNode;
        }
コード例 #11
0
        public Rect FindPositionForNewNodeBottomLeft(int width, int height, ref int bestY, ref int bestX)
        {
            Rect bestNode = new Rect();

            bestY = int.MaxValue;

            foreach (Rect t in FreeBoxes)
            {
                // Try to place the rectangle in upright (non-flipped) orientation.
                if (t.width >= width && t.height >= height)
                {
                    int topSideY = t.y + height;
                    if (topSideY < bestY || (topSideY == bestY && t.x < bestX))
                    {
                        bestNode.x = t.x;
                        bestNode.y = t.y;
                        bestNode.width = width;
                        bestNode.height = height;
                        bestY = topSideY;
                        bestX = t.x;
                    }
                }
                if (t.width >= height && t.height >= width)
                {
                    int topSideY = t.y + width;
                    if (topSideY < bestY || (topSideY == bestY && t.x < bestX))
                    {
                        bestNode.x = t.x;
                        bestNode.y = t.y;
                        bestNode.width = height;
                        bestNode.height = width;
                        bestY = topSideY;
                        bestX = t.x;
                    }
                }
            }
            return bestNode;
        }