示例#1
0
Rect GuillotineBinPack::Insert(long width, long height, bool merge, FreeRectChoiceHeuristic rectChoice, 
	GuillotineSplitHeuristic splitMethod)
{
	// Find where to put the new rectangle.
	long freeNodeIndex = 0;
	Rect newRect = FindPositionForNewNode(width, height, rectChoice, &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.
	SplitFreeRectByHeuristic(freeRectangles[freeNodeIndex], newRect, splitMethod);
	freeRectangles.erase(freeRectangles.begin() + freeNodeIndex);

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

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

	// Check that we're really producing correct packings here.
	assert(disjolongRects.Add(newRect) == true);

	return newRect;
}
示例#2
0
void GuillotineBinPack::Insert(std::vector<RectSize> &rects, std::vector<Rect> &dst, bool merge, 
	FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
{
	dst.clear();

	// Remember variables about the best packing choice we have made so far during the iteration process.
	long bestFreeRect = 0;
	long 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.size() > 0)
	{
		// Stores the penalty score of the best rectangle placement - bigger=worse, smaller=better.
		long bestScore = std::numeric_limits<long>::max();

		for(size_t i = 0; i < freeRectangles.size(); ++i)
		{
			for(size_t j = 0; j < rects.size(); ++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 = std::numeric_limits<long>::min();
					i = freeRectangles.size(); // 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 = std::numeric_limits<long>::min();
					i = freeRectangles.size(); // 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)
				{
					long score = ScoreByHeuristic(rects[j].width, rects[j].height, freeRectangles[i], rectChoice);
					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)
				{
					long score = ScoreByHeuristic(rects[j].height, rects[j].width, freeRectangles[i], rectChoice);
					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 == std::numeric_limits<long>::max())
			return;

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

		if (bestFlipped)
			std::swap(newNode.width, newNode.height);

		// Remove the free space we lost in the bin.
		SplitFreeRectByHeuristic(freeRectangles[bestFreeRect], newNode, splitMethod);
		freeRectangles.erase(freeRectangles.begin() + bestFreeRect);

		// Remove the rectangle we just packed from the input list.
		rects.erase(rects.begin() + bestRect);

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

		// Remember the new used rectangle.
		usedRectangles.push_back(newNode);

		// Check that we're really producing correct packings here.
		assert(disjolongRects.Add(newNode) == true);
	}
}
bool NzGuillotineBinPack::Insert(NzRectui* rects, bool* flipped, bool* inserted, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
{
	std::vector<NzRectui*> remainingRects(count); // La position du rectangle
	for (unsigned int i = 0; i < count; ++i)
		remainingRects[i] = &rects[i];

	// Pack rectangles one at a time until we have cleared the rects array of all rectangles.
	while (!remainingRects.empty())
	{
		// Stores the penalty score of the best rectangle placement - bigger=worse, smaller=better.
		bool bestFlipped;
		int bestFreeRect;
		int bestRect;
		int bestScore = std::numeric_limits<int>::max();

		for (std::size_t i = 0; i < m_freeRectangles.size(); ++i)
		{
			NzRectui& freeRect = m_freeRectangles[i];

			for (std::size_t j = 0; j < remainingRects.size(); ++j)
			{
				NzRectui& rect = *remainingRects[j];

				// If this rectangle is a perfect match, we pick it instantly.
				if (rect.width == freeRect.width && rect.height == freeRect.height)
				{
					bestFreeRect = i;
					bestRect = j;
					bestFlipped = false;
					bestScore = std::numeric_limits<int>::min();
					i = m_freeRectangles.size(); // 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 (rect.height == freeRect.width && rect.width == freeRect.height)
				{
					bestFreeRect = i;
					bestRect = j;
					bestFlipped = true;
					bestScore = std::numeric_limits<int>::min();
					i = m_freeRectangles.size(); // 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 (rect.width <= freeRect.width && rect.height <= freeRect.height)
				{
					int score = ScoreByHeuristic(rect.width, rect.height, freeRect, rectChoice);
					if (score < bestScore)
					{
						bestFreeRect = i;
						bestRect = j;
						bestFlipped = false;
						bestScore = score;
					}
				}
				// If not, then perhaps flipping sideways will make it fit?
				else if (rect.height <= freeRect.width && rect.width <= freeRect.height)
				{
					int score = ScoreByHeuristic(rect.height, rect.width, freeRect, rectChoice);
					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 == std::numeric_limits<int>::max())
		{
			// Si nous le pouvons, on marque les rectangles n'ayant pas pu être insérés
			if (inserted)
			{
				for (NzRectui* rect : remainingRects)
				{
					unsigned int position = rect - rects;
					inserted[position] = false;
				}
			}

			return false;
		}

		// Otherwise, we're good to go and do the actual packing.
		unsigned int position = remainingRects[bestRect] - rects;
		NzRectui& rect = *remainingRects[bestRect];
		rect.x = m_freeRectangles[bestFreeRect].x;
		rect.y = m_freeRectangles[bestFreeRect].y;

		if (bestFlipped)
			std::swap(rect.width, rect.height);

		if (flipped)
			flipped[position] = bestFlipped;

		if (inserted)
			inserted[position] = true;

		// Remove the free space we lost in the bin.
		SplitFreeRectByHeuristic(m_freeRectangles[bestFreeRect], rect, splitMethod);
		m_freeRectangles.erase(m_freeRectangles.begin() + bestFreeRect);

		// Remove the rectangle we just packed from the input list.
		remainingRects.erase(remainingRects.begin() + bestRect);

		// Perform a Rectangle Merge step if desired.
		if (merge)
			MergeFreeRectangles();

		m_usedArea += rect.width * rect.height;
	}

	return true;
}