diff --git a/src/maths/LMPacker.cpp b/src/maths/LMPacker.cpp index 298c1586..c23ac2f6 100644 --- a/src/maths/LMPacker.cpp +++ b/src/maths/LMPacker.cpp @@ -3,83 +3,83 @@ #include inline int getPackerScore(rectangle& rect) { - if (rect.width * rect.height > 100) - return rect.height * rect.height * 1000; - return (rect.width * rect.height * rect.height); + if (rect.width * rect.height > 100) + return rect.height * rect.height * 1000; + return (rect.width * rect.height * rect.height); } LMPacker::LMPacker(const uint32_t sizes[], size_t length) { - for (unsigned int i = 0; i < length/2; i++) { - rectangle rect(i, 0, 0, (int)sizes[i * 2], (int)sizes[i * 2 + 1]); - rects.push_back(rect); - } - sort(rects.begin(), rects.end(), [](rectangle a, rectangle b) { - return -getPackerScore(a) < -getPackerScore(b); - }); + for (unsigned int i = 0; i < length/2; i++) { + rectangle rect(i, 0, 0, (int)sizes[i * 2], (int)sizes[i * 2 + 1]); + rects.push_back(rect); + } + sort(rects.begin(), rects.end(), [](rectangle a, rectangle b) { + return -getPackerScore(a) < -getPackerScore(b); + }); } LMPacker::~LMPacker() { - if (matrix) { - for (unsigned int y = 0; y < (height >> mbit); y++) { - delete[] matrix[y]; - } - delete[] matrix; - } + if (matrix) { + for (unsigned int y = 0; y < (height >> mbit); y++) { + delete[] matrix[y]; + } + delete[] matrix; + } } void LMPacker::cleanup() { - placed.clear(); + placed.clear(); } bool LMPacker::build(uint32_t width, uint32_t height, uint16_t extension, uint32_t mbit, uint32_t vstep) { - cleanup(); - this->mbit = mbit; - this->width = width; - this->height = height; - int mpix = 1 << mbit; + cleanup(); + this->mbit = mbit; + this->width = width; + this->height = height; + int mpix = 1 << mbit; - const unsigned int mwidth = width >> mbit; - const unsigned int mheight = height >> mbit; - matrix = new rectangle**[mheight]; - for (unsigned int y = 0; y < mheight; y++) { - matrix[y] = new rectangle*[mwidth]; - for (unsigned int x = 0; x < mwidth; x++) { - matrix[y][x] = nullptr; - } - } - for (unsigned int i = 0; i < rects.size(); i++) { - rectangle& rect = rects[i]; - rect = rectangle(rect.idx, 0, 0, rect.width, rect.height); + const unsigned int mwidth = width >> mbit; + const unsigned int mheight = height >> mbit; + matrix = new rectangle**[mheight]; + for (unsigned int y = 0; y < mheight; y++) { + matrix[y] = new rectangle*[mwidth]; + for (unsigned int x = 0; x < mwidth; x++) { + matrix[y][x] = nullptr; + } + } + for (unsigned int i = 0; i < rects.size(); i++) { + rectangle& rect = rects[i]; + rect = rectangle(rect.idx, 0, 0, rect.width, rect.height); rect.width += extension * 2; rect.height += extension * 2; if (mpix > 1) { - if (rect.width % mpix > 0) { - rect.extX = mpix - (rect.width % mpix); - } - if (rect.height % mpix > 0) { - rect.extY = mpix - (rect.height % mpix); - } - } - rect.width += rect.extX; - rect.height += rect.extY; - } - bool built = true; - for (unsigned int i = 0; i < rects.size(); i++) { - rectangle* rect = &rects[i]; - if (!place(rect, vstep)) { - built = false; - break; - } - } - for (unsigned int i = 0; i < rects.size(); i++) { - rectangle& rect = rects[i]; + if (rect.width % mpix > 0) { + rect.extX = mpix - (rect.width % mpix); + } + if (rect.height % mpix > 0) { + rect.extY = mpix - (rect.height % mpix); + } + } + rect.width += rect.extX; + rect.height += rect.extY; + } + bool built = true; + for (unsigned int i = 0; i < rects.size(); i++) { + rectangle* rect = &rects[i]; + if (!place(rect, vstep)) { + built = false; + break; + } + } + for (unsigned int i = 0; i < rects.size(); i++) { + rectangle& rect = rects[i]; rect.x += extension; rect.y += extension; rect.width -= extension * 2 + rect.extX; rect.height -= extension * 2 + rect.extY; - } - return built; + } + return built; } inline rectangle* findCollision(rectangle*** matrix, int x, int y, int w, int h) { @@ -103,47 +103,47 @@ inline void fill(rectangle*** matrix, rectangle* rect, int x, int y, int w, int } bool LMPacker::place(rectangle* rectptr, uint32_t vstep) { - rectangle& rect = *rectptr; - const unsigned int rw = rect.width >> mbit; - const unsigned int rh = rect.height >> mbit; - if (vstep > 1) { - vstep = (vstep > rh ? vstep : rh); - } - const unsigned int mwidth = width >> mbit; - const unsigned int mheight = height >> mbit; - for (unsigned int y = 0; y + rh < mheight; y += vstep) { - rectangle** line = matrix[y]; - bool skiplines = true; - rectangle** lower = matrix[y + rh - 1]; - for (unsigned int x = 0; x + rw < mwidth; x++) { - rectangle* prect = line[x]; - if (prect) { - x = (prect->x >> mbit) + (prect->width >> mbit) - 1; - } else { - if (skiplines) { - unsigned int lfree = 0; - while (lfree + x < mwidth && !lower[x + lfree] && lfree < rw) { - lfree++; - } - if (lfree >= rw) - skiplines = false; - } - prect = findCollision(matrix, x, y, rw, rh); - if (prect) { - x = (prect->x >> mbit) + (prect->width >> mbit) - 1; - continue; - } - fill(matrix, rectptr, x, y, rw, rh); + rectangle& rect = *rectptr; + const unsigned int rw = rect.width >> mbit; + const unsigned int rh = rect.height >> mbit; + if (vstep > 1) { + vstep = (vstep > rh ? vstep : rh); + } + const unsigned int mwidth = width >> mbit; + const unsigned int mheight = height >> mbit; + for (unsigned int y = 0; y + rh < mheight; y += vstep) { + rectangle** line = matrix[y]; + bool skiplines = true; + rectangle** lower = matrix[y + rh - 1]; + for (unsigned int x = 0; x + rw < mwidth; x++) { + rectangle* prect = line[x]; + if (prect) { + x = (prect->x >> mbit) + (prect->width >> mbit) - 1; + } else { + if (skiplines) { + unsigned int lfree = 0; + while (lfree + x < mwidth && !lower[x + lfree] && lfree < rw) { + lfree++; + } + if (lfree >= rw) + skiplines = false; + } + prect = findCollision(matrix, x, y, rw, rh); + if (prect) { + x = (prect->x >> mbit) + (prect->width >> mbit) - 1; + continue; + } + fill(matrix, rectptr, x, y, rw, rh); rectptr->x = x << mbit; rectptr->y = y << mbit; placed.push_back(rectptr); return true; - } - } - if (skiplines) { - y += rh - vstep; - } - } - return false; + } + } + if (skiplines) { + y += rh - vstep; + } + } + return false; } diff --git a/src/maths/LMPacker.h b/src/maths/LMPacker.h index 78f6c1c5..9c49b07f 100644 --- a/src/maths/LMPacker.h +++ b/src/maths/LMPacker.h @@ -10,44 +10,44 @@ #include struct rectangle { - unsigned int idx; - int x; - int y; - int width; - int height; - int extX = 0; - int extY = 0; + unsigned int idx; + int x; + int y; + int width; + int height; + int extX = 0; + int extY = 0; - rectangle(unsigned int idx, int x, int y, int width, int height) - : idx(idx), x(x), y(y), width(width), height(height){ - } + rectangle(unsigned int idx, int x, int y, int width, int height) + : idx(idx), x(x), y(y), width(width), height(height){ + } }; class LMPacker { - std::vector rects; - std::vector placed; - uint32_t width = 0; - uint32_t height = 0; - rectangle*** matrix = nullptr; - uint32_t mbit = 0; + std::vector rects; + std::vector placed; + uint32_t width = 0; + uint32_t height = 0; + rectangle*** matrix = nullptr; + uint32_t mbit = 0; - void cleanup(); - bool place(rectangle* rect, uint32_t vstep); + void cleanup(); + bool place(rectangle* rect, uint32_t vstep); public: - LMPacker(const uint32_t sizes[], size_t length); - virtual ~LMPacker(); + LMPacker(const uint32_t sizes[], size_t length); + virtual ~LMPacker(); - bool buildCompact(uint32_t width, uint32_t height, uint16_t extension) { - return build(width, height, extension, 0, 1); - } - bool buildFast(uint32_t width, uint32_t height, uint16_t extension) { - return build(width, height, extension, 1, 2); - } - bool build(uint32_t width, uint32_t height, uint16_t extension, uint32_t mbit, uint32_t vstep); + bool buildCompact(uint32_t width, uint32_t height, uint16_t extension) { + return build(width, height, extension, 0, 1); + } + bool buildFast(uint32_t width, uint32_t height, uint16_t extension) { + return build(width, height, extension, 1, 2); + } + bool build(uint32_t width, uint32_t height, uint16_t extension, uint32_t mbit, uint32_t vstep); - std::vector getResult() { - return rects; - } + std::vector getResult() { + return rects; + } }; #endif /* LMPACKER_H_ */ \ No newline at end of file