Rect GuillotineBinPack::FindPositionForNewNode(long width, long height, FreeRectChoiceHeuristic rectChoice, long *nodeIndex)
{
	Rect bestNode;
	memset(&bestNode, 0, sizeof(Rect));

	long bestScore = std::numeric_limits<long>::max();

	/// Try each free rectangle to find the best one for placement.
	for(size_t i = 0; i < freeRectangles.size(); ++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 = std::numeric_limits<long>::min();
			*nodeIndex = i;
			assert(disjolongRects.Disjolong(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;
			bestScore = std::numeric_limits<long>::min();
			*nodeIndex = i;
			assert(disjolongRects.Disjolong(bestNode));
			break;
		}
		// Does the rectangle fit upright?
		else if (width <= freeRectangles[i].width && height <= freeRectangles[i].height)
		{
			long 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;
				assert(disjolongRects.Disjolong(bestNode));
			}
		}
		// Does the rectangle fit sideways?
		else if (height <= freeRectangles[i].width && width <= freeRectangles[i].height)
		{
			long 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;
				assert(disjolongRects.Disjolong(bestNode));
			}
		}
	}
	return bestNode;
}
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;
}