Example #1
0
        public void Insert(List <SDL.SDL_Rect> rects, FreeRectChoiceHeuristic method)
        {
            while (rects.Count > 0)
            {
                int          bestScore1    = int.MaxValue;
                int          bestScore2    = int.MaxValue;
                int          bestRectIndex = -1;
                SDL.SDL_Rect bestNode      = new SDL.SDL_Rect();

                for (int i = 0; i < rects.Count; ++i)
                {
                    int          score1  = 0;
                    int          score2  = 0;
                    SDL.SDL_Rect newNode = ScoreRect(rects[i].w, rects[i].h, method, ref score1, ref score2);

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

                if (bestRectIndex == -1)
                {
                    return;
                }

                PlaceRect(bestNode);
                rects.RemoveAt(bestRectIndex);
            }
        }
        /// Inserts the given list of rectangles in an offline/batch mode, possibly rotated.
        /// @param rects The list of rectangles to insert. This vector will be destroyed in the process.
        /// @param dst [out] This list will contain the packed rectangles. The indices will not correspond to that of rects.
        /// @param method The rectangle placement rule to use when packing.
        public bool Insert(List<RectSize> rects, FreeRectChoiceHeuristic method)
        {
            int numRects = rects.Count;
            while (rects.Count > 0)
            {
                int bestScore1 = Int32.MaxValue;
                int bestScore2 = Int32.MaxValue;
                int bestRectIndex = -1;
                Rect bestNode = null;

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

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

                if (bestRectIndex == -1)
                    return usedRectangles.Count == numRects;

                PlaceRect(bestNode);
                rects.RemoveAt(bestRectIndex);
            }

            return usedRectangles.Count == numRects;
        }
Example #3
0
		public void Insert(List<Rect> rects, List<Rect> dst, FreeRectChoiceHeuristic method) {
			dst.Clear();
	 
			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 = ScoreRect((int)rects[i].width, (int)rects[i].height, method, ref score1, ref score2);
	 
					if (score1 < bestScore1 || (score1 == bestScore1 && score2 < bestScore2)) {
						bestScore1 = score1;
						bestScore2 = score2;
						bestNode = newNode;
						bestRectIndex = i;
					}
				}
	 
				if (bestRectIndex == -1)
					return;
	 
				PlaceRect(bestNode);
				rects.RemoveAt(bestRectIndex);
			}
		}
Example #4
0
    public Rect Insert(int width, int height, FreeRectChoiceHeuristic method)
    {
        Rect newNode = new Rect();
        int score1 = 0; // Unused in this function. We don't need to know the score after finding the position.
        int score2 = 0;
        switch (method)
        {
            case FreeRectChoiceHeuristic.RectBestShortSideFit: newNode = FindPositionForNewNodeBestShortSideFit(width, height, ref score1, ref score2); break;
            case FreeRectChoiceHeuristic.RectBottomLeftRule: newNode = FindPositionForNewNodeBottomLeft(width, height, ref score1, ref score2); break;
            case FreeRectChoiceHeuristic.RectContactPointRule: newNode = FindPositionForNewNodeContactPoint(width, height, ref score1); 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;
        }

        if (newNode.height == 0)
            return newNode;

        int numRectanglesToProcess = freeRectangles.Count;
        for (int i = 0; i < numRectanglesToProcess; ++i)
        {
            if (SplitFreeNode(freeRectangles[i], ref newNode))
            {
                freeRectangles.RemoveAt(i);
                --i;
                --numRectanglesToProcess;
            }
        }

        PruneFreeList();

        usedRectangles.Add(newNode);
        return newNode;
    }
        // 计算放置给定矩形的位置得分
        Rect ScoreRect(int width, int height, FreeRectChoiceHeuristic method, ref int score1, ref int score2)
        {
            Rect newNode = null;

            score1 = Int32.MaxValue;
            score2 = Int32.MaxValue;
            switch (method)
            {
            case FreeRectChoiceHeuristic.RectBestShortSideFit: newNode = FindPositionForNewNodeBestShortSideFit(width, height, ref score1, ref score2); break;

            case FreeRectChoiceHeuristic.RectBottomLeftRule: newNode = FindPositionForNewNodeBottomLeft(width, height, ref score1, ref score2); break;

            case FreeRectChoiceHeuristic.RectContactPointRule: newNode = FindPositionForNewNodeContactPoint(width, height, ref score1);
                score1 = -score1;                         //反转得到最小的值,但接触点得分越大越好
                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;
            }

            //无法匹配当前矩形
            if (newNode.height == 0)
            {
                score1 = Int32.MaxValue;
                score2 = Int32.MaxValue;
            }

            return(newNode);
        }
Example #6
0
    public void Insert(List <Rect> rects, List <Rect> dst, FreeRectChoiceHeuristic method)
    {
        dst.Clear();

        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 = ScoreRect((int)rects[i].width, (int)rects[i].height, method, ref score1, ref score2);

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

            if (bestRectIndex == -1)
            {
                return;
            }

            PlaceRect(bestNode);
            rects.RemoveAt(bestRectIndex);
        }
    }
Example #7
0
	public Rect Insert (int width, int height, FreeRectChoiceHeuristic method)
	{
		Rect newNode = new Rect();
		int score1 = 0; // Unused in this function. We don't need to know the score after finding the position.
		int score2 = 0;
		switch (method)
		{
			case FreeRectChoiceHeuristic.RectBestShortSideFit: newNode = FindPositionForNewNodeBestShortSideFit(width, height, ref score1, ref score2); break;
			case FreeRectChoiceHeuristic.RectBottomLeftRule: newNode = FindPositionForNewNodeBottomLeft(width, height, ref score1, ref score2); break;
			case FreeRectChoiceHeuristic.RectContactPointRule: newNode = FindPositionForNewNodeContactPoint(width, height, ref score1); 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;
		}

		if (newNode.height == 0)
			return newNode;

		int numRectanglesToProcess = freeRectangles.Count;
		for (int i = 0; i < numRectanglesToProcess; ++i)
		{
			if (SplitFreeNode(freeRectangles[i], ref newNode))
			{
				freeRectangles.RemoveAt(i);
				--i;
				--numRectanglesToProcess;
			}
		}

		PruneFreeList();

		usedRectangles.Add(newNode);
		return newNode;
	}
Example #8
0
    Rect ScoreRect(int width, int height, FreeRectChoiceHeuristic method, ref int score1, ref 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.RectBottomLeftRule: newNode = FindPositionForNewNodeBottomLeft(width, height, ref score1, ref score2); break;

        case FreeRectChoiceHeuristic.RectContactPointRule: newNode = FindPositionForNewNodeContactPoint(width, height, ref score1);
            score1 = -score1;             // Reverse since we are minimizing, but for contact point score bigger is better.
            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.height == 0)
        {
            score1 = int.MaxValue;
            score2 = int.MaxValue;
        }

        return(newNode);
    }
Example #9
0
        /// Inserts a single rectangle into the bin. The packer might rotate the rectangle, in which case the returned
        /// struct will have the width and height values swapped.
        /// @param merge If true, performs free Rectangle Merge procedure after packing the new rectangle. This procedure
        ///		tries to defragment the list of disjoint free rectangles to improve packing performance, but also takes up
        ///		some extra time.
        /// @param rectChoice The free rectangle choice heuristic rule to use.
        /// @param splitMethod The free rectangle split heuristic rule to use.
        public BinRect Insert(int width, int height, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
        {
            // Find where to put the new rectangle.
            int     freeNodeIndex = 0;
            BinRect newRect       = FindPositionForNewNode(width, height, rectChoice, ref freeNodeIndex);

            // Abort if we didn't have enough space in the bin.
            if (newRect.height == 0)
            {
                return(newRect);
            }

            // Remove the space that was just consumed by the new rectangle.
            {
                var item = freeRectangles[freeNodeIndex];
                SplitFreeRectByHeuristic(ref item, ref newRect, splitMethod);
                freeRectangles[freeNodeIndex] = item;
                freeRectangles.RemoveAt(freeNodeIndex);
            }
            // Perform a Rectangle Merge step if desired.
            if (merge)
            {
                MergeFreeList();
            }

            // Remember the new used rectangle.
            usedRectangles.Add(newRect);


            return(newRect);
        }
 public void Insert(
     Rectangle rect,
     FreeRectChoiceHeuristic rectChoice,
     out int freeRectIndex)
 {
     // Find where to put the new rectangle
     FindPositionForNewRect(rect, rectChoice, out freeRectIndex);
 }
 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;
 }
Example #12
0
        /// <summary>
        /// 插入一个Node
        /// </summary>
        public IntRect Insert(int width, int height, FreeRectChoiceHeuristic freeRectChoiceHeuristic)
        {
            IntRect newNode = IntRect.zero;

            // Unused in this function. We don't need to know the score after finding the position.
            int score1 = int.MaxValue;
            int score2 = int.MaxValue;

            switch (freeRectChoiceHeuristic)
            {
            case FreeRectChoiceHeuristic.RectBestShortSideFit:
                newNode = FindPositionForNewNodeBestShortSideFit(width, height, ref score1, ref score2);
                break;

            case FreeRectChoiceHeuristic.RectBestLongSideFit:
                newNode = FindPositionForNewNodeBottomLeft(width, height, ref score1, ref score2);
                break;

            case FreeRectChoiceHeuristic.RectContactPointRule:
                newNode = FindPositionForNewNodeContactPoint(width, height, ref score1);
                break;

            case FreeRectChoiceHeuristic.RectBottomLeftRule:
                newNode = FindPositionForNewNodeBestLongSideFit(width, height, ref score1, ref score2);
                break;

            case FreeRectChoiceHeuristic.RectBestAreaFit:
                newNode = FindPositionForNewNodeBestAreaFit(width, height, ref score1, ref score2);
                break;
            }

            if (newNode.height == 0)
            {
                return(newNode);
            }

            int numRectanglesToProcess = mFreeRectRangles.Count;

            for (int i = 0; i < numRectanglesToProcess; ++i)
            {
                if (SplitFreeNode(mFreeRectRangles[i], newNode))
                {
                    mFreeRectRangles.RemoveAt(i);

                    --i;
                    --numRectanglesToProcess;
                }
            }

            PruneFreeList();

            mUsedRectangles.Add(newNode);

            return(newNode);
        }
    /// <summary>
    /// Returns list of positions for newly added rects.
    /// Element in returned array corresponds to the element on same position in input array.
    /// </summary>
    /// <param name="rects">Rects.</param>
    /// <param name="method">Method.</param>
    public List <Rect> Insert(List <Rect> rects, FreeRectChoiceHeuristic method)
    {
        if (rects == null || rects.Count == 0)
        {
            return(null);
        }

        List <Rect> sortedUsedRects        = new List <Rect>(new Rect[rects.Count]);
        List <int>  indexesInOriginalArray = new List <int>();

        for (int i = 0; i < rects.Count; i++)
        {
            indexesInOriginalArray.Add(i);
        }

        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 = ScoreRect((int)rects[i].width, (int)rects[i].height, method, ref score1, ref score2);

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

            if (bestRectIndex == -1)
            {
                return(null);
            }

            PlaceRect(bestNode);
            rects.RemoveAt(bestRectIndex);

            int indexInOriginalArray = indexesInOriginalArray[bestRectIndex];
            sortedUsedRects[indexInOriginalArray] = bestNode;
            indexesInOriginalArray.RemoveAt(bestRectIndex);
        }

        return(sortedUsedRects);
    }
Example #14
0
    // For online packing use only.
    // Not useful here.

    /*
     * public Rect Insert( int width, int height, FreeRectChoiceHeuristic method )
     * {
     *      Rect newNode = new Rect();
     *      int score1 = 0; // Unused in this function. We don't need to know the score after finding the position.
     *      int score2 = 0;
     *      switch( method )
     *      {
     *              case FreeRectChoiceHeuristic.RectBestShortSideFit:	newNode = FindPositionForNewNodeBestShortSideFit(width, height, ref score1, ref score2); break;
     *              case FreeRectChoiceHeuristic.RectBottomLeftRule:	newNode = FindPositionForNewNodeBottomLeft(width, height, ref score1, ref score2); break;
     *              case FreeRectChoiceHeuristic.RectContactPointRule:	newNode = FindPositionForNewNodeContactPoint(width, height, ref score1); 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;
     *      }
     *
     *      if( newNode.height == 0 )
     *      {
     *              return newNode;
     *      }
     *
     *      int numRectanglesToProcess = freeRectangles.Count;
     *      for( int i = 0; i < numRectanglesToProcess; ++i )
     *      {
     *              if( SplitFreeNode( freeRectangles[ i ], ref newNode ) )
     *              {
     *                      freeRectangles.RemoveAt(i);
     *                      --i;
     *                      --numRectanglesToProcess;
     *              }
     *      }
     *
     *      PruneFreeList();
     *
     *      usedRectangles.Add(newNode);
     *      return newNode;
     * }*/

    // Returns true if all rects have been inserted, false otherwise
    public bool Insert(Dictionary <int, Rect> a_rRectsDict, FreeRectChoiceHeuristic a_ePackingMethod)
    {
        int iRectCount = a_rRectsDict.Count;

        while (iRectCount > 0)
        {
            int iBestScore1 = int.MaxValue;
            int iBestScore2 = int.MaxValue;

            int  iBestRectIndex = -1;
            bool bBestIsFlipped = false;
            Rect oBestNode      = new Rect();

            foreach (KeyValuePair <int, Rect> rIndexedRect in a_rRectsDict)
            {
                int  iScore1    = 0;
                int  iScore2    = 0;
                bool bIsFlipped = false;

                // Score padded rect
                // Get a new padded (and probably flipped) rect
                Rect newNode = ScoreRect((int)(rIndexedRect.Value.width + rectPadding),
                                         (int)(rIndexedRect.Value.height + rectPadding),
                                         a_ePackingMethod,
                                         ref iScore1,
                                         ref iScore2,
                                         ref bIsFlipped);

                if (iScore1 < iBestScore1 || (iScore1 == iBestScore1 && iScore2 < iBestScore2))
                {
                    iBestScore1    = iScore1;
                    iBestScore2    = iScore2;
                    oBestNode      = newNode;
                    iBestRectIndex = rIndexedRect.Key;
                    bBestIsFlipped = bIsFlipped;
                }
            }

            if (iBestRectIndex == -1)
            {
                return(false);
            }

            PlaceRect(iBestRectIndex, oBestNode, bBestIsFlipped);
            a_rRectsDict.Remove(iBestRectIndex);

            --iRectCount;
        }

        return(true);           // iRectCount = 0
    }
Example #15
0
 public BinPackShelfAlgorithm(
     BinPackParameter parameter,
     FreeRectChoiceHeuristic rectChoice,
     GuillotineSplitHeuristic splitMethod,
     ShelfChoiceHeuristic shelfChoice)
 {
     _parameter     = parameter;
     _rectChoice    = rectChoice;
     _splitMethod   = splitMethod;
     _shelfChoice   = shelfChoice;
     _currentY      = 0;
     _shelves       = new List <Shelf>();
     _packedCuboids = new List <Cuboid>();
     StartNewShelf(0);
 }
        private static decimal ScoreByHeuristic(
            Rectangle rect,
            Rectangle freeRect,
            FreeRectChoiceHeuristic rectChoice)
        {
            switch (rectChoice)
            {
            case FreeRectChoiceHeuristic.RectBestAreaFit:
                return(ScoreBestAreaFit(rect, freeRect));

            case FreeRectChoiceHeuristic.RectBestShortSideFit:
                return(ScoreBestShortSideFit(rect, freeRect));

            default:
                throw new NotSupportedException($"rect choice is unsupported: {rectChoice}");
            }
        }
Example #17
0
        public void Insert(List <ImRect> rects, List <ImRect> dst, FreeRectChoiceHeuristic method)
        {
            dst.Clear();
            dst.AddRange(new ImRect[rects.Count]);

            var remaining = rects.Count;
            var completed = new bool[rects.Count];

            while (remaining > 0)
            {
                int    bestScore1    = int.MaxValue;
                int    bestScore2    = int.MaxValue;
                int    bestRectIndex = -1;
                ImRect bestNode      = new ImRect();

                for (int i = 0; i < rects.Count; ++i)
                {
                    if (!completed[i])
                    {
                        int    score1  = 0;
                        int    score2  = 0;
                        ImRect newNode = ScoreRect((int)rects[i].width, (int)rects[i].height, method, ref score1, ref score2);

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

                if (bestRectIndex == -1)
                {
                    return;
                }

                PlaceRect(bestNode);
                completed[bestRectIndex] = true;
                dst[bestRectIndex]       = bestNode;
                remaining--;
                //rects.RemoveAt(bestRectIndex);
            }
        }
 public BinPackShelfAlgorithm(
     decimal binWidth,
     decimal binHeight,
     decimal binDepth,
     FreeRectChoiceHeuristic rectChoice,
     GuillotineSplitHeuristic splitMethod,
     ShelfChoiceHeuristic shelfChoice)
 {
     _binWidth    = binWidth;
     _binHeight   = binHeight;
     _binDepth    = binDepth;
     _rectChoice  = rectChoice;
     _splitMethod = splitMethod;
     _shelfChoice = shelfChoice;
     _currentY    = 0;
     _shelves     = new List <Shelf>();
     StartNewShelf(0);
 }
Example #19
0
            /// <summary>
            /// For each rectangle, packs each one then chooses the best and packs that. Slow!
            /// </summary>
            public Page Pack(List <Rect> rects, FreeRectChoiceHeuristic method)
            {
                rects = new List <Rect>(rects);
                while (rects.Count > 0)
                {
                    int  bestRectIndex = -1;
                    Rect bestNode      = new Rect()
                    {
                        Score1 = int.MaxValue,
                        Score2 = int.MaxValue,
                    };

                    for (int i = 0; i < rects.Count; i++)
                    {
                        Rect newNode = ScoreRect(rects[i], method);
                        if (newNode.Score1 < bestNode.Score1 || (newNode.Score1 == bestNode.Score1 && newNode.Score2 < bestNode.Score2))
                        {
                            bestNode.Set(rects[i]);
                            bestNode.Score1  = newNode.Score1;
                            bestNode.Score2  = newNode.Score2;
                            bestNode.X       = newNode.X;
                            bestNode.Y       = newNode.Y;
                            bestNode.Width   = newNode.Width;
                            bestNode.Height  = newNode.Height;
                            bestNode.Rotated = newNode.Rotated;
                            bestRectIndex    = i;
                        }
                    }

                    if (bestRectIndex == -1)
                    {
                        break;
                    }

                    PlaceRect(bestNode);
                    rects.RemoveAt(bestRectIndex);
                }

                Page result = GetResult();

                result.RemainingRects = rects;

                return(result);
            }
Example #20
0
        static int ScoreByHeuristic(int width, int height, ref BinRect freeRect, FreeRectChoiceHeuristic rectChoice)
        {
            switch (rectChoice)
            {
            case FreeRectChoiceHeuristic.RectBestAreaFit: return(ScoreBestAreaFit(width, height, ref freeRect));

            case FreeRectChoiceHeuristic.RectBestShortSideFit: return(ScoreBestShortSideFit(width, height, ref freeRect));

            case FreeRectChoiceHeuristic.RectBestLongSideFit: return(ScoreBestLongSideFit(width, height, ref freeRect));

            case FreeRectChoiceHeuristic.RectWorstAreaFit: return(ScoreWorstAreaFit(width, height, ref freeRect));

            case FreeRectChoiceHeuristic.RectWorstShortSideFit: return(ScoreWorstShortSideFit(width, height, ref freeRect));

            case FreeRectChoiceHeuristic.RectWorstLongSideFit: return(ScoreWorstLongSideFit(width, height, ref freeRect));

            default: return(int.MaxValue);
            }
        }
Example #21
0
        private Rect Insert(int width, int height, FreeRectChoiceHeuristic method)
        {
            var newNode = new Rect();

            var score1 = 0;
            var score2 = 0;

            switch (method)
            {
            case FreeRectChoiceHeuristic.RectBestShortSideFit: newNode = FindPositionForNewNodeBestShortSideFit(width, height, ref score1, ref score2); break;

            case FreeRectChoiceHeuristic.RectBottomLeftRule: newNode = FindPositionForNewNodeBottomLeft(width, height, ref score1, ref score2); break;

            case FreeRectChoiceHeuristic.RectContactPointRule: newNode = FindPositionForNewNodeContactPoint(width, height, ref score1); 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;
            }

            if (newNode.height == 0)
            {
                return(newNode);
            }

            var numRectanglesToProcess = freeRectangles.Count;

            for (var i = 0; i < numRectanglesToProcess; ++i)
            {
                if (SplitFreeNode(freeRectangles[i], ref newNode))
                {
                    freeRectangles.RemoveAt(i);
                    --i;
                    --numRectanglesToProcess;
                }
            }

            PruneFreeList();

            usedRectangles.Add(newNode);

            return(newNode);
        }
Example #22
0
            private Rect ScoreRect(Rect rect, FreeRectChoiceHeuristic method)
            {
                int  width         = rect.Width;
                int  height        = rect.Height;
                int  rotatedWidth  = height - _outer._settings.PaddingY + _outer._settings.PaddingX;
                int  rotatedHeight = width - _outer._settings.PaddingX + _outer._settings.PaddingY;
                bool rotate        = rect.CanRotate && _outer._settings.Rotation;

                Rect newNode = null;

                switch (method)
                {
                case FreeRectChoiceHeuristic.BestShortSideFit:
                    newNode = FindPositionForNewNodeBestShortSideFit(width, height, rotatedWidth, rotatedHeight, rotate);
                    break;

                case FreeRectChoiceHeuristic.BottomLeftRule:
                    newNode = FindPositionForNewNodeBottomLeft(width, height, rotatedWidth, rotatedHeight, rotate);
                    break;

                case FreeRectChoiceHeuristic.ContactPointRule:
                    newNode        = FindPositionForNewNodeContactPoint(width, height, rotatedWidth, rotatedHeight, rotate);
                    newNode.Score1 = -newNode.Score1;
                    break;

                case FreeRectChoiceHeuristic.BestLongSideFit:
                    newNode = FindPositionForNewNodeBestLongSideFit(width, height, rotatedWidth, rotatedHeight, rotate);
                    break;

                case FreeRectChoiceHeuristic.BestAreaFit:
                    newNode = FindPositionForNewNodeBestAreaFit(width, height, rotatedWidth, rotatedHeight, rotate);
                    break;
                }

                if (newNode.Height == 0)
                {
                    newNode.Score1 = int.MaxValue;
                    newNode.Score2 = int.MaxValue;
                }

                return(newNode);
            }
        public void Insert(Span <PackRect> rects, Span <PackRect> dst, FreeRectChoiceHeuristic method)
        {
            var remaining = rects.Length;
            var completed = new bool[rects.Length];

            while (remaining > 0)
            {
                int      bestScore1    = int.MaxValue;
                int      bestScore2    = int.MaxValue;
                int      bestRectIndex = -1;
                PackRect bestNode      = new PackRect();

                for (int i = 0; i < rects.Length; ++i)
                {
                    if (!completed[i])
                    {
                        int      score1  = 0;
                        int      score2  = 0;
                        PackRect newNode = ScoreRect((int)rects[i].Width, (int)rects[i].Height, method, ref score1, ref score2);

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

                if (bestRectIndex == -1)
                {
                    return;
                }

                PlaceRect(bestNode);
                completed[bestRectIndex] = true;
                dst[bestRectIndex]       = bestNode;
                remaining--;
            }
        }
Example #24
0
        public void Insert(List <IntRect> rects, List <IntRect> dst, FreeRectChoiceHeuristic freeRectChoiceHeuristic)
        {
            dst.Clear();

            while (rects.Count > 0)
            {
                int bestScore1 = int.MaxValue;
                int bestScore2 = int.MaxValue;

                int bestRectIndex = -1;

                IntRect bestNode = IntRect.zero;

                for (int i = 0; i < rects.Count; ++i)
                {
                    int score1 = int.MaxValue;
                    int score2 = int.MaxValue;

                    IntRect newNode = ScoreRect(rects[i].x, rects[i].y, freeRectChoiceHeuristic, ref score1, ref score2);

                    if (score1 < bestScore1 || (score1 == bestScore1 && score2 < bestScore2))
                    {
                        bestScore1 = score1;
                        bestScore2 = score2;

                        bestNode      = newNode;
                        bestRectIndex = i;
                    }
                }

                if (bestRectIndex == -1 || bestNode == IntRect.zero)
                {
                    return;
                }

                PlaceRect(bestNode);

                dst.Add(bestNode);
                rects.RemoveAt(bestRectIndex);
            }
        }
Example #25
0
        private Rect ScoreRect(int width, int height, FreeRectChoiceHeuristic method, ref int score1, ref int score2)
        {
            var 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.RectBottomLeftRule:
                newNode = FindPositionForNewNodeBottomLeft(width, height, ref score1, ref score2);
                break;

            case FreeRectChoiceHeuristic.RectContactPointRule:
                newNode = FindPositionForNewNodeContactPoint(width, height, ref score1);
                score1  = -score1;
                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;
            }

            if (newNode.height == 0)
            {
                score1 = int.MaxValue;
                score2 = int.MaxValue;
            }

            return(newNode);
        }
Example #26
0
        /// <summary>
        /// IntRect的匹配度计算
        /// </summary>
        private IntRect ScoreRect(int width, int height, FreeRectChoiceHeuristic freeRectChoiceHeuristic, ref int score1, ref int score2)
        {
            IntRect newNode = IntRect.zero;

            score1 = int.MaxValue;
            score2 = int.MaxValue;

            switch (freeRectChoiceHeuristic)
            {
            case FreeRectChoiceHeuristic.RectBestShortSideFit:
                newNode = FindPositionForNewNodeBestShortSideFit(width, height, ref score1, ref score2);
                break;

            case FreeRectChoiceHeuristic.RectBottomLeftRule:
                newNode = FindPositionForNewNodeBottomLeft(width, height, ref score1, ref score2);
                break;

            case FreeRectChoiceHeuristic.RectContactPointRule:
                newNode = FindPositionForNewNodeContactPoint(width, height, ref score1);
                score1  = -score1;    // Reverse since we are minimizing, but for contact point score bigger is better.
                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;
            }

            if (newNode.height == 0)
            {
                score1 = int.MaxValue;
                score2 = int.MaxValue;
            }

            return(newNode);
        }
Example #27
0
            /// <summary>
            /// Packs a single image. Order is defined externally.
            /// </summary>
            public Rect Insert(Rect rect, FreeRectChoiceHeuristic method)
            {
                Rect newNode = ScoreRect(rect, method);

                if (newNode.Height == 0)
                {
                    return(null);
                }

                int numRectanglesToProcess = _freeRectangles.Count;

                for (int i = 0; i < numRectanglesToProcess; i++)
                {
                    if (SplitFreeNode(_freeRectangles[i], newNode))
                    {
                        _freeRectangles.RemoveAt(i);
                        i--;
                        numRectanglesToProcess--;
                    }
                }

                PruneFreeList();

                Rect bestNode = new Rect();

                bestNode.Set(rect);
                bestNode.Score1  = newNode.Score1;
                bestNode.Score2  = newNode.Score2;
                bestNode.X       = newNode.X;
                bestNode.Y       = newNode.Y;
                bestNode.Width   = newNode.Width;
                bestNode.Height  = newNode.Height;
                bestNode.Rotated = newNode.Rotated;

                _usedRectangles.Add(bestNode);
                return(bestNode);
            }
        /// Inserts the given list of rectangles in an offline/batch mode, possibly rotated.
        /// @param rects The list of rectangles to insert. This vector will be destroyed in the process.
        /// @param dst [out] This list will contain the packed rectangles. The indices will not correspond to that of rects.
        /// @param method The rectangle placement rule to use when packing.
        public bool Insert(List <RectSize> rects, FreeRectChoiceHeuristic method)
        {
            int numRects = rects.Count;

            while (rects.Count > 0)
            {
                int  bestScore1    = Int32.MaxValue;
                int  bestScore2    = Int32.MaxValue;
                int  bestRectIndex = -1;
                Rect bestNode      = null;

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

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

                if (bestRectIndex == -1)
                {
                    return(usedRectangles.Count == numRects);
                }

                PlaceRect(bestNode);
                rects.RemoveAt(bestRectIndex);
            }

            return(usedRectangles.Count == numRects);
        }
Example #29
0
        /// Inserts a list of rectangles into the bin.
        /// @param rects The list of rectangles to add. This list will be destroyed in the packing process.
        /// @param merge If true, performs Rectangle Merge operations during the packing process.
        /// @param rectChoice The free rectangle choice heuristic rule to use.
        /// @param splitMethod The free rectangle split heuristic rule to use.
        public void Insert(List <RectSize> rects, bool merge,
                           FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
        { // Remember variables about the best packing choice we have made so far during the iteration process.
            int  bestFreeRect = 0;
            int  bestRect     = 0;
            bool bestFlipped  = false;

            // Pack rectangles one at a time until we have cleared the rects array of all rectangles.
            // rects will get destroyed in the process.
            while (rects.Count > 0)
            {
                // Stores the penalty score of the best rectangle placement - bigger=worse, smaller=better.
                int bestScore = int.MaxValue;

                for (int i = 0; i < freeRectangles.Count; ++i)
                {
                    for (int j = 0; j < rects.Count; ++j)
                    {
                        // If this rectangle is a perfect match, we pick it instantly.
                        if (rects[j].width == freeRectangles[i].width && rects[j].height == freeRectangles[i].height)
                        {
                            bestFreeRect = i;
                            bestRect     = j;
                            bestFlipped  = false;
                            bestScore    = int.MinValue;
                            i            = freeRectangles.Count; // Force a jump out of the outer loop as well - we got an instant fit.
                            break;
                        }
                        // If flipping this rectangle is a perfect match, pick that then.
                        else if (rects[j].height == freeRectangles[i].width && rects[j].width == freeRectangles[i].height)
                        {
                            bestFreeRect = i;
                            bestRect     = j;
                            bestFlipped  = true;
                            bestScore    = int.MinValue;
                            i            = freeRectangles.Count; // Force a jump out of the outer loop as well - we got an instant fit.
                            break;
                        }
                        // Try if we can fit the rectangle upright.
                        else if (rects[j].width <= freeRectangles[i].width && rects[j].height <= freeRectangles[i].height)
                        {
                            var item  = freeRectangles[i];
                            int score = ScoreByHeuristic(rects[j].width, rects[j].height, ref item, rectChoice);
                            freeRectangles[i] = item;
                            if (score < bestScore)
                            {
                                bestFreeRect = i;
                                bestRect     = j;
                                bestFlipped  = false;
                                bestScore    = score;
                            }
                        }
                        // If not, then perhaps flipping sideways will make it fit?
                        else if (rects[j].height <= freeRectangles[i].width && rects[j].width <= freeRectangles[i].height)
                        {
                            var item  = freeRectangles[i];
                            int score = ScoreByHeuristic(rects[j].height, rects[j].width, ref item, rectChoice);
                            freeRectangles[i] = item;
                            if (score < bestScore)
                            {
                                bestFreeRect = i;
                                bestRect     = j;
                                bestFlipped  = true;
                                bestScore    = score;
                            }
                        }
                    }
                }

                // If we didn't manage to find any rectangle to pack, abort.
                if (bestScore == int.MaxValue)
                {
                    return;
                }

                // Otherwise, we're good to go and do the actual packing.
                BinRect newNode;
                newNode.x      = freeRectangles[bestFreeRect].x;
                newNode.y      = freeRectangles[bestFreeRect].y;
                newNode.width  = rects[bestRect].width;
                newNode.height = rects[bestRect].height;

                if (bestFlipped)
                {
                    int temp = newNode.width;
                    newNode.width  = newNode.height;
                    newNode.height = temp;
                }

                // Remove the free space we lost in the bin.
                {
                    var item = freeRectangles[bestFreeRect];
                    SplitFreeRectByHeuristic(ref item, ref newNode, splitMethod);
                    freeRectangles[bestFreeRect] = item;
                    freeRectangles.RemoveAt(bestFreeRect);
                }
                // Remove the rectangle we just packed from the input list.
                rects.RemoveAt(bestRect);

                // Perform a Rectangle Merge step if desired.
                if (merge)
                {
                    MergeFreeList();
                }

                // Remember the new used rectangle.
                usedRectangles.Add(newNode);
            }
        }
 public Rect Insert(Vector2 size, FreeRectChoiceHeuristic method)
 {
     return(Insert((int)size.x, (int)size.y, method));
 }
Example #31
0
        /// Goes through the list of free rectangles and finds the best one to place a rectangle of given size into.
        /// Running time is Theta(|freeRectangles|).
        /// @param nodeIndex [out] The index of the free rectangle in the freeRectangles array into which the new
        ///		rect was placed.
        /// @return A Rect structure that represents the placement of the new rect into the best free rectangle.
        private Rect FindPositionForNewNode(int width, int height, FreeRectChoiceHeuristic rectChoice, ref int nodeIndex)
        {
            Rect bestNode  = new Rect();
            int  bestScore = int.MaxValue;

            /// Try each free rectangle to find the best one for placement.
            for (int i = 0; i < freeRectangles.Count; ++i)
            {
                // If this is a perfect fit upright, choose it immediately.
                if (width == freeRectangles[i].Width && height == freeRectangles[i].Height)
                {
                    bestNode.X      = freeRectangles[i].X;
                    bestNode.Y      = freeRectangles[i].Y;
                    bestNode.Width  = width;
                    bestNode.Height = height;
                    nodeIndex       = i;
                    disjointRects.Disjoint(bestNode);
                    break;
                }
                // If this is a perfect fit sideways, choose it.
                else if (height == freeRectangles[i].Width && width == freeRectangles[i].Height)
                {
                    bestNode.X      = freeRectangles[i].X;
                    bestNode.Y      = freeRectangles[i].Y;
                    bestNode.Width  = height;
                    bestNode.Height = width;
                    nodeIndex       = i;
                    disjointRects.Disjoint(bestNode);
                    break;
                }
                // Does the rectangle fit upright?
                else if (width <= freeRectangles[i].Width && height <= freeRectangles[i].Height)
                {
                    int score = ScoreByHeuristic(width, height, freeRectangles[i], rectChoice);

                    if (score < bestScore)
                    {
                        bestNode.X      = freeRectangles[i].X;
                        bestNode.Y      = freeRectangles[i].Y;
                        bestNode.Width  = width;
                        bestNode.Height = height;
                        bestScore       = score;
                        nodeIndex       = i;
                        disjointRects.Disjoint(bestNode);
                    }
                }
                // Does the rectangle fit sideways?
                else if (height <= freeRectangles[i].Width && width <= freeRectangles[i].Height)
                {
                    int score = ScoreByHeuristic(height, width, freeRectangles[i], rectChoice);

                    if (score < bestScore)
                    {
                        bestNode.X      = freeRectangles[i].X;
                        bestNode.Y      = freeRectangles[i].Y;
                        bestNode.Width  = height;
                        bestNode.Height = width;
                        bestScore       = score;
                        nodeIndex       = i;
                        disjointRects.Disjoint(bestNode);
                    }
                }
            }
            return(bestNode);
        }
    public static Rect[] PackTexturesSpec(Texture2D texture, Texture2D[] textures, int width, int height, int padding, int maxSize, FreeRectChoiceHeuristic heuristic)
    {
        if (width > maxSize && height > maxSize) return null;
        if (width > maxSize || height > maxSize) { int temp = width; width = height; height = temp; }

        // Force square by sizing up
        if (NGUISettings.forceSquareAtlas)
        {
            if (width > height)
                height = width;
            else if (height > width)
                width = height;
        }
        Storage[] storage;
        using (var bp = new UITexturePackerSpec(width, height, false))
        {
            storage = new Storage[textures.Length];

            for (int i = 0; i < textures.Length; i++)
            {
                Texture2D tex = textures[i];
                if (!tex) continue;

                Rect rect = new Rect();

                int xPadding = 1;
                int yPadding = 1;

                for (xPadding = 1; xPadding >= 0; --xPadding)
                {
                    for (yPadding = 1; yPadding >= 0; --yPadding)
                    {
                        rect = bp.Insert(tex.width + (xPadding * padding), tex.height + (yPadding * padding), heuristic);
                        if (rect.width > 0 && rect.height > 0) break;

                            // After having no padding if it still doesn't fit -- increase texture size.
                        else if (xPadding == 0 && yPadding == 0)
                        {
                            return PackTexturesSpec(texture, textures, width * (width <= height ? 2 : 1),
                                height * (height < width ? 2 : 1), padding, maxSize, heuristic);
                        }
                    }
                    if (rect.width > 0 && rect.height > 0) break;
                }

                storage[i] = new Storage();
                storage[i].rect = rect;
                storage[i].paddingX = (xPadding != 0);
                storage[i].paddingY = (yPadding != 0);
            }
        }

        texture.Resize(width, height);
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                texture.SetPixel(i, j, new Color());
            }
        }

        // The returned rects
        Rect[] rects = new Rect[textures.Length];

        for (int i = 0; i < textures.Length; i++)
        {
            Texture2D tex = textures[i];
            if (!tex) continue;

            Rect rect = storage[i].rect;
            int xPadding = (storage[i].paddingX ? padding : 0);
            int yPadding = (storage[i].paddingY ? padding : 0);
            Color[] colors = tex.GetPixels();

            // Would be used to rotate the texture if need be.
            if (rect.width != tex.width + xPadding)
            {
                Color[] newColors = tex.GetPixels();

                for (int x = 0; x < rect.width; x++)
                {
                    for (int y = 0; y < rect.height; y++)
                    {
                        int prevIndex = ((int)rect.height - (y + 1)) + x * (int)tex.width;
                        newColors[x + y * (int)rect.width] = colors[prevIndex];
                    }
                }

                colors = newColors;
            }

            texture.SetPixels((int)rect.x, (int)rect.y, (int)rect.width - xPadding, (int)rect.height - yPadding, colors);
            rect.x /= width;
            rect.y /= height;
            rect.width = (rect.width - xPadding) / width;
            rect.height = (rect.height - yPadding) / height;
            rects[i] = rect;
        }
        texture.Apply();
        return rects;
    }
        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;
        }
        private void FindPositionForNewRect(
            Rectangle rect,
            FreeRectChoiceHeuristic rectChoice,
            out int freeRectIndex)
        {
            decimal width     = rect.Width;
            decimal height    = rect.Height;
            decimal bestScore = decimal.MaxValue;

            freeRectIndex = -1;

            // Try each free rectangle to find the best one for placement
            for (int index = 0; index < _freeRectangles.Count; ++index)
            {
                // If this is a perfect fit upright, choose it immediately.
                var freeRectangle = _freeRectangles[index];
                if (width == freeRectangle.Width &&
                    height == freeRectangle.Height)
                {
                    rect.IsPlaced = true;
                    rect.X        = freeRectangle.X;
                    rect.Y        = freeRectangle.Y;
                    rect.Width    = width;
                    rect.Height   = height;
                    freeRectIndex = index;
                    break;
                }
                // If this is a perfect fit sideways, choose it.
                else if (height == freeRectangle.Width &&
                         width == freeRectangle.Height)
                {
                    rect.IsPlaced = true;
                    rect.X        = freeRectangle.X;
                    rect.Y        = freeRectangle.Y;
                    rect.Width    = height;
                    rect.Height   = width;
                    freeRectIndex = index;
                    break;
                }
                // Does the rectangle fit upright?
                if (width <= freeRectangle.Width &&
                    height <= freeRectangle.Height)
                {
                    decimal score = ScoreByHeuristic(rect, freeRectangle, rectChoice);

                    if (score < bestScore)
                    {
                        rect.IsPlaced = true;
                        rect.X        = freeRectangle.X;
                        rect.Y        = freeRectangle.Y;
                        rect.Width    = width;
                        rect.Height   = height;
                        bestScore     = score;
                        freeRectIndex = index;
                    }
                }
                // Does the rectangle fit sideways?
                if (height <= freeRectangle.Width &&
                    width <= freeRectangle.Height)
                {
                    decimal score = ScoreByHeuristic(rect, freeRectangle, rectChoice);

                    if (score < bestScore)
                    {
                        rect.IsPlaced = true;
                        rect.X        = freeRectangle.X;
                        rect.Y        = freeRectangle.Y;
                        rect.Width    = height;
                        rect.Height   = width;
                        bestScore     = score;
                        freeRectIndex = index;
                    }
                }
            }
        }
	// For online packing use only.
	// Not useful here.
	/*
	public Rect Insert( int width, int height, FreeRectChoiceHeuristic method )
	{
		Rect newNode = new Rect();
		int score1 = 0; // Unused in this function. We don't need to know the score after finding the position.
		int score2 = 0;
		switch( method )
		{
			case FreeRectChoiceHeuristic.RectBestShortSideFit:	newNode = FindPositionForNewNodeBestShortSideFit(width, height, ref score1, ref score2); break;
			case FreeRectChoiceHeuristic.RectBottomLeftRule:	newNode = FindPositionForNewNodeBottomLeft(width, height, ref score1, ref score2); break;
			case FreeRectChoiceHeuristic.RectContactPointRule:	newNode = FindPositionForNewNodeContactPoint(width, height, ref score1); 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;
		}
 
		if( newNode.height == 0 )
		{
			return newNode;
		}
 
		int numRectanglesToProcess = freeRectangles.Count;
		for( int i = 0; i < numRectanglesToProcess; ++i )
		{
			if( SplitFreeNode( freeRectangles[ i ], ref newNode ) )
			{
				freeRectangles.RemoveAt(i);
				--i;
				--numRectanglesToProcess;
			}
		}
 
		PruneFreeList();
 
		usedRectangles.Add(newNode);
		return newNode;
	}*/
 
	// Returns true if all rects have been inserted, false otherwise
	public bool Insert( Dictionary<int,Rect> a_rRectsDict, FreeRectChoiceHeuristic a_ePackingMethod )
	{
		int iRectCount = a_rRectsDict.Count;
 
		while( iRectCount > 0 )
		{
			int iBestScore1 = int.MaxValue;
			int iBestScore2 = int.MaxValue;

			int iBestRectIndex  = -1;
			bool bBestIsFlipped = false;
			Rect oBestNode      = new Rect();
 
			foreach( KeyValuePair<int,Rect> rIndexedRect in a_rRectsDict )
			{
				int iScore1 = 0;
				int iScore2 = 0;
				bool bIsFlipped = false;

				// Score padded rect
				// Get a new padded (and probably flipped) rect
				Rect newNode = ScoreRect( (int) ( rIndexedRect.Value.width + rectPadding ),
					(int) ( rIndexedRect.Value.height + rectPadding ),
					a_ePackingMethod,
					ref iScore1,
					ref iScore2,
					ref bIsFlipped );
 
				if( iScore1 < iBestScore1 || ( iScore1 == iBestScore1 && iScore2 < iBestScore2 ) )
				{
					iBestScore1    = iScore1;
					iBestScore2    = iScore2;
					oBestNode      = newNode;
					iBestRectIndex = rIndexedRect.Key;
					bBestIsFlipped = bIsFlipped;
				}
			}
 
			if( iBestRectIndex == -1 )
			{
				return false;
			}
 
			PlaceRect( iBestRectIndex, oBestNode, bBestIsFlipped );
			a_rRectsDict.Remove( iBestRectIndex );

			--iRectCount;
		}

		return true;	// iRectCount = 0
	}
    public static Rect[] PackTexturesSpec(Texture2D texture, Texture2D[] textures, int width, int height, int padding, int maxSize, FreeRectChoiceHeuristic heuristic)
    {
        if (width > maxSize && height > maxSize)
        {
            return(null);
        }
        if (width > maxSize || height > maxSize)
        {
            int temp = width; width = height; height = temp;
        }

        // Force square by sizing up
        if (NGUISettings.forceSquareAtlas)
        {
            if (width > height)
            {
                height = width;
            }
            else if (height > width)
            {
                width = height;
            }
        }
        Storage[] storage;
        using (var bp = new UITexturePackerSpec(width, height, false))
        {
            storage = new Storage[textures.Length];

            for (int i = 0; i < textures.Length; i++)
            {
                Texture2D tex = textures[i];
                if (!tex)
                {
                    continue;
                }

                Rect rect = new Rect();

                int xPadding = 1;
                int yPadding = 1;

                for (xPadding = 1; xPadding >= 0; --xPadding)
                {
                    for (yPadding = 1; yPadding >= 0; --yPadding)
                    {
                        rect = bp.Insert(tex.width + (xPadding * padding), tex.height + (yPadding * padding), heuristic);
                        if (rect.width > 0 && rect.height > 0)
                        {
                            break;
                        }

                        // After having no padding if it still doesn't fit -- increase texture size.
                        else if (xPadding == 0 && yPadding == 0)
                        {
                            return(PackTexturesSpec(texture, textures, width * (width <= height ? 2 : 1),
                                                    height * (height < width ? 2 : 1), padding, maxSize, heuristic));
                        }
                    }
                    if (rect.width > 0 && rect.height > 0)
                    {
                        break;
                    }
                }

                storage[i]          = new Storage();
                storage[i].rect     = rect;
                storage[i].paddingX = (xPadding != 0);
                storage[i].paddingY = (yPadding != 0);
            }
        }

        texture.Resize(width, height);
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                texture.SetPixel(i, j, new Color());
            }
        }


        // The returned rects
        Rect[] rects = new Rect[textures.Length];

        for (int i = 0; i < textures.Length; i++)
        {
            Texture2D tex = textures[i];
            if (!tex)
            {
                continue;
            }

            Rect    rect     = storage[i].rect;
            int     xPadding = (storage[i].paddingX ? padding : 0);
            int     yPadding = (storage[i].paddingY ? padding : 0);
            Color[] colors   = tex.GetPixels();

            // Would be used to rotate the texture if need be.
            if (rect.width != tex.width + xPadding)
            {
                Color[] newColors = tex.GetPixels();

                for (int x = 0; x < rect.width; x++)
                {
                    for (int y = 0; y < rect.height; y++)
                    {
                        int prevIndex = ((int)rect.height - (y + 1)) + x * (int)tex.width;
                        newColors[x + y * (int)rect.width] = colors[prevIndex];
                    }
                }

                colors = newColors;
            }

            texture.SetPixels((int)rect.x, (int)rect.y, (int)rect.width - xPadding, (int)rect.height - yPadding, colors);
            rect.x     /= width;
            rect.y     /= height;
            rect.width  = (rect.width - xPadding) / width;
            rect.height = (rect.height - yPadding) / height;
            rects[i]    = rect;
        }
        texture.Apply();
        return(rects);
    }
Example #37
0
    Rect ScoreRect(int width, int height, FreeRectChoiceHeuristic method, ref int score1, ref 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.RectBottomLeftRule: newNode = FindPositionForNewNodeBottomLeft(width, height, ref score1, ref score2); break;
            case FreeRectChoiceHeuristic.RectContactPointRule: newNode = FindPositionForNewNodeContactPoint(width, height, ref score1);
                score1 = -score1; // Reverse since we are minimizing, but for contact point score bigger is better.
                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.height == 0) {
            score1 = int.MaxValue;
            score2 = int.MaxValue;
        }

        return newNode;
    }
Example #38
0
        /// Goes through the list of free rectangles and finds the best one to place a rectangle of given size into.
        /// Running time is Theta(|freeRectangles|).
        /// @param nodeIndex [out] The index of the free rectangle in the freeRectangles array into which the new
        ///		rect was placed.
        /// @return A Rect structure that represents the placement of the new rect into the best free rectangle.
        public BinRect FindPositionForNewNode(int width, int height, FreeRectChoiceHeuristic rectChoice, ref int nodeIndex)
        {
            BinRect bestNode = new BinRect();

            int bestScore = int.MaxValue;

            /// Try each free rectangle to find the best one for placement.
            for (int i = 0; i < freeRectangles.Count; ++i)
            {
                // If this is a perfect fit upright, choose it immediately.
                if (width == freeRectangles[i].width && height == freeRectangles[i].height)
                {
                    bestNode.x      = freeRectangles[i].x;
                    bestNode.y      = freeRectangles[i].y;
                    bestNode.width  = width;
                    bestNode.height = height;
                    bestScore       = int.MinValue;
                    break;
                }
                // If this is a perfect fit sideways, choose it.
                else if (height == freeRectangles[i].width && width == freeRectangles[i].height)
                {
                    bestNode.x      = freeRectangles[i].x;
                    bestNode.y      = freeRectangles[i].y;
                    bestNode.width  = height;
                    bestNode.height = width;
                    bestScore       = int.MinValue;
                    break;
                }
                // Does the rectangle fit upright?
                else if (width <= freeRectangles[i].width && height <= freeRectangles[i].height)
                {
                    var item  = freeRectangles[i];
                    int score = ScoreByHeuristic(width, height, ref item, rectChoice);
                    freeRectangles[i] = item;
                    if (score < bestScore)
                    {
                        bestNode.x      = freeRectangles[i].x;
                        bestNode.y      = freeRectangles[i].y;
                        bestNode.width  = width;
                        bestNode.height = height;
                        bestScore       = score;
                    }
                }
                // Does the rectangle fit sideways?
                else if (height <= freeRectangles[i].width && width <= freeRectangles[i].height)
                {
                    var item  = freeRectangles[i];
                    int score = ScoreByHeuristic(width, height, ref item, rectChoice);
                    freeRectangles[i] = item;
                    if (score < bestScore)
                    {
                        bestNode.x      = freeRectangles[i].x;
                        bestNode.y      = freeRectangles[i].y;
                        bestNode.width  = height;
                        bestNode.height = width;
                        bestScore       = score;
                    }
                }
            }
            return(bestNode);
        }