Alternate packing strategy test

This commit is contained in:
Chlumsky 2024-11-23 15:18:15 +01:00
parent c4e45732ce
commit b5710b7b17
3 changed files with 72 additions and 8 deletions

@ -1 +1 @@
Subproject commit 888674220216d1d326c6f29cf89165b545279c1f
Subproject commit af79386abe0857fe1c30be97eec760dbd84022c5

View File

@ -1,8 +1,6 @@
#include "RectanglePacker.h"
#include <algorithm>
namespace msdf_atlas {
#define WORST_FIT 0x7fffffff
@ -10,7 +8,7 @@ namespace msdf_atlas {
template <typename T>
static void removeFromUnorderedVector(std::vector<T> &vector, size_t index) {
if (index != vector.size()-1)
std::swap(vector[index], vector.back());
vector[index] = (T &&) vector.back();
vector.pop_back();
}
@ -55,7 +53,57 @@ void RectanglePacker::splitSpace(int index, int w, int h) {
}
int RectanglePacker::pack(Rectangle *rectangles, int count) {
std::vector<int> remainingRects(count);
struct RectangleCache {
Rectangle *rectangle;
int bestFit;
int bestSpaceIndex;
};
std::vector<RectangleCache> remainingRects;
remainingRects.reserve(count);
int modifiedSpaceIndex0 = -1, modifiedSpaceIndex1 = -1;
bool spaceAdded = false;
RectangleCache initialCache = { rectangles, WORST_FIT, modifiedSpaceIndex0 };
for (Rectangle *end = rectangles+count; initialCache.rectangle < end; ++initialCache.rectangle) {
if (initialCache.rectangle->w > 0 && initialCache.rectangle->h > 0)
remainingRects.push_back(initialCache);
}
while (!remainingRects.empty()) {
int bestRectFit = WORST_FIT;
int bestRectIndex = -1;
for (int rectIndex = 0; rectIndex < (int) remainingRects.size(); ++rectIndex) {
RectangleCache &rectCache = remainingRects[rectIndex];
if (rectCache.bestSpaceIndex == modifiedSpaceIndex0 || rectCache.bestSpaceIndex == modifiedSpaceIndex1) {
int bestSpaceFit = WORST_FIT;
for (int spaceIndex = 0; spaceIndex < (int) spaces.size() && bestSpaceFit > 0; ++spaceIndex) {
if (spaces[spaceIndex].w >= rectCache.rectangle->w && spaces[spaceIndex].h >= rectCache.rectangle->h) {
int fit = rateFit(rectCache.rectangle->w, rectCache.rectangle->h, spaces[spaceIndex].w, spaces[spaceIndex].h);
if (fit < bestSpaceFit) {
bestSpaceFit = fit;
rectCache.bestSpaceIndex = spaceIndex;
}
}
}
rectCache.bestFit = bestSpaceFit;
}
if (rectCache.bestFit < bestRectFit) {
bestRectFit = rectCache.bestFit;
bestRectIndex = rectIndex;
}
}
if (bestRectIndex < 0) // None of the remaining rectangles fits
break;
RectangleCache &rectCache = remainingRects[bestRectIndex];
rectCache.rectangle->x = spaces[rectCache.bestSpaceIndex].x;
rectCache.rectangle->y = spaces[rectCache.bestSpaceIndex].y;
modifiedSpaceIndex0 = rectCache.bestSpaceIndex;
modifiedSpaceIndex1 = (int) (spaces.size()-1);
splitSpace(rectCache.bestSpaceIndex, rectCache.rectangle->w, rectCache.rectangle->h);
spaceAdded = modifiedSpaceIndex1 < (int) (spaces.size()-1);
removeFromUnorderedVector(remainingRects, bestRectIndex);
}
return (int) remainingRects.size();
/*std::vector<int> remainingRects(count);
for (int i = 0; i < count; ++i)
remainingRects[i] = i;
while (!remainingRects.empty()) {
@ -90,7 +138,7 @@ int RectanglePacker::pack(Rectangle *rectangles, int count) {
splitSpace(bestSpace, rect.w, rect.h);
removeFromUnorderedVector(remainingRects, bestRect);
}
return (int) remainingRects.size();
return (int) remainingRects.size();*/
}
int RectanglePacker::pack(OrientedRectangle *rectangles, int count) {

View File

@ -17,6 +17,20 @@ static void copyRectanglePlacement(OrientedRectangle &dst, const OrientedRectang
dst.rotated = src.rotated;
}
#define CHUNK_SIZE 256
template <typename RectangleType>
static int chunkPack(int w, int h, RectangleType *rectangles, int count) {
RectanglePacker packer(w, h);
while (count > CHUNK_SIZE) {
count -= CHUNK_SIZE;
if (int result = packer.pack(rectangles, CHUNK_SIZE))
return result+count;
rectangles += CHUNK_SIZE;
}
return packer.pack(rectangles, count);
}
template <typename RectangleType>
int packRectangles(RectangleType *rectangles, int count, int width, int height, int spacing) {
if (spacing)
@ -24,7 +38,8 @@ int packRectangles(RectangleType *rectangles, int count, int width, int height,
rectangles[i].w += spacing;
rectangles[i].h += spacing;
}
int result = RectanglePacker(width+spacing, height+spacing).pack(rectangles, count);
//int result = RectanglePacker(width+spacing, height+spacing).pack(rectangles, count);
int result = chunkPack(width+spacing, height+spacing, rectangles, count);
if (spacing)
for (int i = 0; i < count; ++i) {
rectangles[i].w -= spacing;
@ -46,7 +61,8 @@ std::pair<int, int> packRectangles(RectangleType *rectangles, int count, int spa
SizeSelector sizeSelector(totalArea);
int width, height;
while (sizeSelector(width, height)) {
if (!RectanglePacker(width+spacing, height+spacing).pack(rectanglesCopy.data(), count)) {
//if (!RectanglePacker(width+spacing, height+spacing).pack(rectanglesCopy.data(), count)) {
if (!chunkPack(width+spacing, height+spacing, rectanglesCopy.data(), count)) {
dimensions.first = width;
dimensions.second = height;
for (int i = 0; i < count; ++i)