예제 #1
0
Option<Rect> sb::Guillotine::tryPack(const Vec2& r, sb::Guillotine::Context& c) {
	if ((c.packedArea + r.area()) > c.totalArea)
		return nullptr;

	Option<Rect> previousF = nullptr;

	for(auto& freeF : c.freeRectangles) {
		//Fits?
		if (freeF.containsRect(newRect(freeF.bottomLeft(), r))) {
			if (previousF && isBestFit(c.FitPolicy, freeF, previousF.value(), r))
				previousF = freeF;
			else if (!previousF)
				previousF = freeF;
		}
	}

	if (previousF == nullptr) //rectangle can't be packed
		return nullptr;
	else {
		c.packedRectangles.push_back(newRect(previousF.value().bottomLeft(), r));
		c.freeRectangles.erase(previousF.value());
		Rect r1, r2;
		performSplit(previousF.value(), r, bestSplit(c.SplitPolicy, previousF.value(), r), r1, r2);
		if (r1.area() != 0.0)
			c.freeRectangles.insert(r1);
		if (r2.area() != 0.0)
			c.freeRectangles.insert(r2);
		c.packedArea += r.area();
		return newRect(previousF.value().bottomLeft(), r);
	}
}
예제 #2
0
void sb::MaxRects::initializeContext(Context* c, const Vec2& freeRectangle, FitPolicy FitPolicy) {
	c->totalArea = freeRectangle.area();
	c->packedArea = 0.0;
	c->fp = FitPolicy;

	c->freeRectangles.clear();
	c->freeRectangles.insert(newRect(Vec2::zero, freeRectangle));

	c->packedRectangles.clear();
}
예제 #3
0
void sb::Guillotine::initializeContext(sb::Guillotine::Context* ctx, const Vec2& freeRectangle, FitPolicy FitPolicy, SplitPolicy SplitPolicy) {
	assert(ctx);
	ctx->totalArea = freeRectangle.area();
	ctx->packedArea = 0;
	ctx->FitPolicy = FitPolicy;
	ctx->SplitPolicy = SplitPolicy;
	ctx->freeRectangles.clear();
	ctx->freeRectangles.insert(newRect(Vec2::zero, freeRectangle));
	ctx->packedRectangles.clear();
}
예제 #4
0
void sb::Skyline::initializeContext(Context* c, const Vec2& freeRectangle, bool wasteImprovement) {
	c->totalArea = freeRectangle.area();
	c->packedArea = 0.0;

	c->guillotineContexts.clear();
	c->Skyline = createSkyline(freeRectangle);

	c->packedRectangles.clear();
	c->freeRectangle = freeRectangle;
	c->wasteImprovement = wasteImprovement;
}
예제 #5
0
Option<Rect> sb::Skyline::tryPack(const Vec2& r, Context& c) {
	Option<Rect> packedInWastedArea = nullptr;
	for(auto& gc : c.guillotineContexts) {
		auto gpacked = Guillotine::tryPack(r, gc.second);
		if (gpacked) {
			auto gpacked2 = gpacked.value();
			Matrix3x3::fromTranslation(gc.first.bottomLeft()).transformRect(&gpacked2);
			packedInWastedArea = gpacked2;
			c.packedRectangles.push_back(gpacked2);
		}
	}
	if (packedInWastedArea) {
		return packedInWastedArea;
	}

	if ((c.packedArea + r.area()) > c.totalArea)
		return nullptr;

	std::vector<Rect> lostAreas;
	auto bestPlace = bestPlaceToPack(c.Skyline, c.freeRectangle.height(), r, lostAreas);

	if (!bestPlace) //rectangle can't be packed
		return nullptr;
	else {
		auto packed = packIntoPlace(c.Skyline, r, bestPlace.value());
		c.packedRectangles.push_back(packed);
		if (lostAreas.size() != 0 && c.wasteImprovement) {
			for(auto& lostArea : lostAreas) {
				Guillotine::Context guiCtx;
				Guillotine::initializeContext(&guiCtx, lostArea.size(), Guillotine::FitPolicy::BSSF, Guillotine::SplitPolicy::MINAS);
				c.guillotineContexts.insert({ lostArea, guiCtx });
				c.packedArea += lostArea.area();
			}
		}
		c.packedArea += r.area();
		return packed;
	}
}
예제 #6
0
Option<Rect> sb::MaxRects::tryPack(const Vec2& r, Context& c) {
	std::vector<Rect> splitted;
	if ((c.packedArea + r.area()) > c.totalArea)
		return nullptr;

	Option<Rect> previousF = nullptr;

	for(auto& freeF : c.freeRectangles) {
		//Fits?
		if (freeF.containsRect(newRect(freeF.bottomLeft(), r))) {
			if (previousF && isBestFit(c.fp, freeF, previousF.value(), r))
				previousF = freeF;
			else if (!previousF)
				previousF = freeF;
		}
	}

	if (!previousF) //rectangle can't be packed
		return nullptr;
	else {
		auto packed = newRect(previousF->bottomLeft(), r);
		c.packedRectangles.push_back(packed);
		c.freeRectangles.erase(previousF.value());
		split(previousF.value(), packed, splitted);
		for(auto& sr : splitted)
			c.freeRectangles.insert(sr);
		std::vector<Rect> frCopy(c.freeRectangles.begin(), c.freeRectangles.end());
		for(auto& fr : frCopy) {
			split(fr, packed, splitted);
			if (splitted.size() != 0) {
				c.freeRectangles.erase(fr);
				for(auto& sr : splitted)
					c.freeRectangles.insert(sr);
			}
		}
		frCopy = std::vector<Rect>(c.freeRectangles.begin(), c.freeRectangles.end());
		auto pairs = allPairs(frCopy);
		for (auto& p : pairs) {
			if (p.first.containsRect(p.second)) {
				c.freeRectangles.erase(p.second);
			}
			else if (p.second.containsRect(p.first)) {
				c.freeRectangles.erase(p.first);
			}
		}
	}
	return newRect(previousF->bottomLeft(), r);
}
예제 #7
0
//Some Internal Methods
bool isBestFit(Guillotine::FitPolicy FitPolicy, const Rect& freeRectangle, const Rect& previousFreeRectangle, const Vec2& rectangle) {
	float a1 = 0, a2 = 0;
	switch (FitPolicy) {
		case Guillotine::FitPolicy::BAF:
			a1 = rectangle.area() / freeRectangle.area();
			a2 = rectangle.area() / previousFreeRectangle.area();
			return a1 > a2;
		case Guillotine::FitPolicy::BSSF:
			a1 = std::min(freeRectangle.width() - rectangle.width(), freeRectangle.height() - rectangle.height());
			a2 = std::min(previousFreeRectangle.width() - rectangle.width(), previousFreeRectangle.height() - rectangle.height());
			return a1 < a2;
		case Guillotine::FitPolicy::BLSF:
			a1 = std::max(freeRectangle.width() - rectangle.width(), freeRectangle.height() - rectangle.height());
			a2 = std::max(previousFreeRectangle.width() - rectangle.width(), previousFreeRectangle.height() - rectangle.height());
			return a1 < a2;
		default:
			throw "should never get here";
	}
}
예제 #8
0
bool isBestFit(MaxRects::FitPolicy FitPolicy, const Rect& freeRectangle, const Rect& previousFreeRectangle, const Vec2& rectangle) {
	float a1, a2, b1, b2, c1, c2;
	switch (FitPolicy) {
		case MaxRects::FitPolicy::BL:
			if (freeRectangle.bottom() == previousFreeRectangle.bottom())
				return freeRectangle.left() <= previousFreeRectangle.left();
			else
				return freeRectangle.bottom() <= previousFreeRectangle.bottom();
		case MaxRects::FitPolicy::BAF:
			a1 = rectangle.area() / freeRectangle.area();
			a2 = rectangle.area() / previousFreeRectangle.area();
			return a1 > a2;
		case MaxRects::FitPolicy::BSSF:
			b1 = std::min(freeRectangle.width() - rectangle.width(), freeRectangle.height() - rectangle.height());
			b2 = std::min(previousFreeRectangle.width() - rectangle.width(), previousFreeRectangle.height() - rectangle.height());
			return b1 < b2;
		case MaxRects::FitPolicy::BLSF:
			c1 = std::max(freeRectangle.width() - rectangle.width(), freeRectangle.height() - rectangle.height());
			c2 = std::max(previousFreeRectangle.width() - rectangle.width(), previousFreeRectangle.height() - rectangle.height());
			return c1 < c2;
		default:
			throw "should never get here.";
	}
}