25 #ifndef DP_RECT_PACK_H 26 #define DP_RECT_PACK_H 33 #define DP_RECT_PACK_VERSION_MAJOR 1 34 #define DP_RECT_PACK_VERSION_MINOR 1 35 #define DP_RECT_PACK_VERSION_PATCH 3 93 template<
typename GeomT =
int>
130 Padding(GeomT top, GeomT bottom, GeomT left, GeomT right)
212 GeomT maxPageWidth, GeomT maxPageHeight,
215 : ctx(maxPageWidth, maxPageHeight, rectsSpacing, pagePadding)
238 void getPageSize(std::size_t pageIndex, GeomT& width, GeomT& height)
const 240 const Size size = pages[pageIndex].getSize(ctx);
271 Size(GeomT w, GeomT h)
283 , growDownRootBottomIdx(0)
286 Size getSize(
const Context& ctx)
const 289 ctx.padding.left + rootSize.w + ctx.padding.right,
290 ctx.padding.top + rootSize.h + ctx.padding.bottom);
293 bool insert(Context& ctx,
const Size& rect,
Position& pos);
299 Node(GeomT x, GeomT y, GeomT w, GeomT h)
306 std::vector<Node> nodes;
310 std::size_t growDownRootBottomIdx;
312 bool tryInsert(Context& ctx,
const Size& rect,
Position& pos);
315 std::size_t& nodeIdx,
Position& pos)
const;
317 Context& ctx, std::size_t nodeIdx,
const Size& rect);
318 bool tryGrow(Context& ctx,
const Size& rect,
Position& pos);
319 void growDown(Context& ctx,
const Size& rect,
Position& pos);
320 void growRight(Context& ctx,
const Size& rect,
Position& pos);
329 GeomT maxPageWidth, GeomT maxPageHeight,
332 static void subtractPadding(GeomT& padding, GeomT& size);
336 std::vector<Page> pages;
340 template<
typename GeomT>
346 if (width < 0 || height < 0) {
351 if (width == 0 || height == 0) {
356 if (width > ctx.maxSize.w || height > ctx.maxSize.h) {
361 const Size rect(width, height);
363 for (std::size_t i = 0; i < pages.size(); ++i)
364 if (pages[i].insert(ctx, rect, result.
pos)) {
370 pages.push_back(Page());
371 Page& page = pages.back();
372 page.insert(ctx, rect, result.
pos);
380 template<
typename GeomT>
382 Context& ctx,
const Size& rect,
Position& pos)
385 assert(rect.w <= ctx.maxSize.w);
387 assert(rect.h <= ctx.maxSize.h);
392 if (rootSize.w == 0) {
394 pos.
x = ctx.padding.left;
395 pos.
y = ctx.padding.top;
400 return tryInsert(ctx, rect, pos) || tryGrow(ctx, rect, pos);
404 template<
typename GeomT>
406 Context& ctx,
const Size& rect,
Position& pos)
409 if (findNode(rect, nodeIdx, pos)) {
410 subdivideNode(ctx, nodeIdx, rect);
418 template<
typename GeomT>
420 const Size& rect, std::size_t& nodeIdx,
Position& pos)
const 422 for (nodeIdx = 0; nodeIdx < nodes.size(); ++nodeIdx) {
423 const Node& node = nodes[nodeIdx];
424 if (rect.w <= node.size.w && rect.h <= node.size.h) {
448 template<
typename GeomT>
450 Context& ctx, std::size_t nodeIdx,
const Size& rect)
452 assert(nodeIdx < nodes.size());
454 Node& node = nodes[nodeIdx];
456 assert(node.size.w >= rect.w);
457 const GeomT rightW = node.size.w - rect.w;
458 const bool hasSpaceRight = rightW > ctx.spacing.x;
460 assert(node.size.h >= rect.h);
461 const GeomT bottomH = node.size.h - rect.h;
462 const bool hasSpaceBelow = bottomH > ctx.spacing.y;
467 const GeomT bottomX = node.pos.x;
468 const GeomT bottomW = node.size.w;
470 node.pos.x += rect.w + ctx.spacing.x;
471 node.size.w = rightW - ctx.spacing.x;
472 node.size.h = rect.h;
476 nodes.begin() + nodeIdx + 1,
479 node.pos.y + rect.h + ctx.spacing.y,
481 bottomH - ctx.spacing.y));
483 if (nodeIdx <= growDownRootBottomIdx)
484 ++growDownRootBottomIdx;
486 }
else if (hasSpaceBelow) {
488 node.pos.y += rect.h + ctx.spacing.y;
489 node.size.h = bottomH - ctx.spacing.y;
491 nodes.erase(nodes.begin() + nodeIdx);
492 if (nodeIdx < growDownRootBottomIdx)
493 --growDownRootBottomIdx;
498 template<
typename GeomT>
500 Context& ctx,
const Size& rect,
Position& pos)
502 assert(ctx.maxSize.w >= rootSize.w);
503 const GeomT freeW = ctx.maxSize.w - rootSize.w;
504 assert(ctx.maxSize.h >= rootSize.h);
505 const GeomT freeH = ctx.maxSize.h - rootSize.h;
507 const bool canGrowDown = (
508 freeH >= rect.h && freeH - rect.h >= ctx.spacing.y);
509 const bool mustGrowDown = (
511 && freeW >= ctx.spacing.x
512 && (rootSize.w + ctx.spacing.x
513 >= rootSize.h + rect.h + ctx.spacing.y));
515 growDown(ctx, rect, pos);
519 const bool canGrowRight = (
520 freeW >= rect.w && freeW - rect.w >= ctx.spacing.x);
522 growRight(ctx, rect, pos);
527 growDown(ctx, rect, pos);
535 template<
typename GeomT>
537 Context& ctx,
const Size& rect,
Position& pos)
539 assert(ctx.maxSize.h > rootSize.h);
540 assert(ctx.maxSize.h - rootSize.h >= rect.h);
541 assert(ctx.maxSize.h - rootSize.h - rect.h >= ctx.spacing.y);
543 pos.
x = ctx.padding.left;
544 pos.
y = ctx.padding.top + rootSize.h + ctx.spacing.y;
546 if (rootSize.w < rect.w) {
547 if (rect.w - rootSize.w > ctx.spacing.x) {
554 ctx.padding.left + rootSize.w + ctx.spacing.x,
556 rect.w - rootSize.w - ctx.spacing.x,
558 ++growDownRootBottomIdx;
562 }
else if (rootSize.w - rect.w > ctx.spacing.x) {
567 nodes.begin() + growDownRootBottomIdx,
569 pos.
x + rect.w + ctx.spacing.x,
571 rootSize.w - rect.w - ctx.spacing.x,
577 ++growDownRootBottomIdx;
580 rootSize.h += ctx.spacing.y + rect.h;
584 template<
typename GeomT>
586 Context& ctx,
const Size& rect,
Position& pos)
588 assert(ctx.maxSize.w > rootSize.w);
589 assert(ctx.maxSize.w - rootSize.w >= rect.w);
590 assert(ctx.maxSize.w - rootSize.w - rect.w >= ctx.spacing.x);
592 pos.
x = ctx.padding.left + rootSize.w + ctx.spacing.x;
593 pos.
y = ctx.padding.top;
595 if (rootSize.h < rect.h) {
596 if (rect.h - rootSize.h > ctx.spacing.y)
605 ctx.padding.top + rootSize.h + ctx.spacing.y,
607 rect.h - rootSize.h - ctx.spacing.y));
610 }
else if (rootSize.h - rect.h > ctx.spacing.y) {
618 pos.
y + rect.h + ctx.spacing.y,
620 rootSize.h - rect.h - ctx.spacing.y));
621 ++growDownRootBottomIdx;
624 rootSize.w += ctx.spacing.x + rect.w;
628 template<
typename GeomT>
630 GeomT maxPageWidth, GeomT maxPageHeight,
632 : maxSize(maxPageWidth, maxPageHeight)
633 , spacing(rectsSpacing)
634 , padding(pagePadding)
646 subtractPadding(padding.top, maxSize.h);
647 subtractPadding(padding.bottom, maxSize.h);
648 subtractPadding(padding.left, maxSize.w);
649 subtractPadding(padding.right, maxSize.w);
653 template<
typename GeomT>
655 GeomT& padding, GeomT& size)
659 else if (padding < size)
672 #endif // DP_RECT_PACK_H GeomT top
Definition: dp_rect_pack.h:115
Spacing(GeomT spacing)
Construct Spacing with the same spacing for both dimensions.
Definition: dp_rect_pack.h:103
InsertStatus::Type status
Status of the insertion.
Definition: dp_rect_pack.h:163
Definition: dp_rect_pack.h:138
Definition: dp_rect_pack.h:96
std::size_t pageIndex
Index of the page in which the rectangle was inserted.
Definition: dp_rect_pack.h:175
Successful insertion.
Definition: dp_rect_pack.h:50
Position pos
Position of the inserted rectangle within the page.
Definition: dp_rect_pack.h:168
Rectangle is too big to fit in a single page.
Definition: dp_rect_pack.h:63
Type
Definition: dp_rect_pack.h:49
Width and/or height is zero.
Definition: dp_rect_pack.h:52
GeomT y
Vertical spacing.
Definition: dp_rect_pack.h:98
Padding(GeomT top, GeomT bottom, GeomT left, GeomT right)
Definition: dp_rect_pack.h:130
RectPacker(GeomT maxPageWidth, GeomT maxPageHeight, const Spacing &rectsSpacing=Spacing(0), const Padding &pagePadding=Padding(0))
RectPacker constructor.
Definition: dp_rect_pack.h:211
Spacing(GeomT x, GeomT y)
Definition: dp_rect_pack.h:108
Width and/or height is negative.
Definition: dp_rect_pack.h:51
GeomT bottom
Definition: dp_rect_pack.h:116
InsertResult insert(GeomT width, GeomT height)
Insert a rectangle.
Definition: dp_rect_pack.h:342
std::size_t getNumPages() const
Return the current number of pages.
Definition: dp_rect_pack.h:224
GeomT y
Definition: dp_rect_pack.h:140
GeomT left
Definition: dp_rect_pack.h:117
GeomT x
Definition: dp_rect_pack.h:139
void getPageSize(std::size_t pageIndex, GeomT &width, GeomT &height) const
Return the current size of the page.
Definition: dp_rect_pack.h:238
Result returned by RectPacker::insert().
Definition: dp_rect_pack.h:156
GeomT right
Definition: dp_rect_pack.h:118
Position(GeomT x, GeomT y)
Definition: dp_rect_pack.h:147
GeomT x
Horizontal spacing.
Definition: dp_rect_pack.h:97
Definition: dp_rect_pack.h:114
Padding(GeomT padding)
Construct Padding with the same padding for all sides.
Definition: dp_rect_pack.h:123
Definition: dp_rect_pack.h:38
Rectangle packer.
Definition: dp_rect_pack.h:94
Status of the RectPacker::InsertResult.
Definition: dp_rect_pack.h:48
Position()
Definition: dp_rect_pack.h:142