-
Notifications
You must be signed in to change notification settings - Fork 1
/
MaxRectsBinPack.h
107 lines (81 loc) · 4 KB
/
MaxRectsBinPack.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/** @file MaxRectsBinPack.h
@author Jukka Jylänki
@brief Implements different bin packer algorithms that use the MAXRECTS data structure.
This work is released to Public Domain, do whatever you want with it.
*/
#pragma once
#include <vector>
#include <utility>
namespace rbp {
struct RectSize
{
int width;
int height;
int id;
};
struct Rect
{
int x;
int y;
int width;
int height;
int id;
};
/** MaxRectsBinPack implements the MAXRECTS data structure and different bin packing algorithms that
use this structure. */
class MaxRectsBinPack
{
public:
/// Instantiates a bin of size (0,0). Call Init to create a new bin.
MaxRectsBinPack();
/// Instantiates a bin of the given size.
/// @param allowFlip Specifies whether the packing algorithm is allowed to rotate the input rectangles by 90 degrees to consider a better placement.
MaxRectsBinPack(int width, int height, bool allowFlip = true);
/// (Re)initializes the packer to an empty bin of width x height units. Call whenever
/// you need to restart with a new bin.
void Init(int width, int height, bool allowFlip = true);
/// Specifies the different heuristic rules that can be used when deciding where to place a new rectangle.
enum FreeRectChoiceHeuristic
{
RectBestShortSideFit, ///< -BSSF: Positions the rectangle against the short side of a free rectangle into which it fits the best.
RectBestLongSideFit, ///< -BLSF: Positions the rectangle against the long side of a free rectangle into which it fits the best.
RectBestAreaFit, ///< -BAF: Positions the rectangle into the smallest free rect into which it fits.
RectBottomLeftRule, ///< -BL: Does the Tetris placement.
RectContactPointRule ///< -CP: Choosest the placement where the rectangle touches other rects as much as possible.
};
/// Inserts the given list of rectangles in an offline/batch mode, possibly rotated.
/// @param rects The list of rectangles to insert. This vector will be destroyed in the process.
/// @param dst [out] This list will contain the packed rectangles. The indices will not correspond to that of rects.
/// @param method The rectangle placement rule to use when packing.
void Insert(std::vector<RectSize> &rects, std::vector<Rect> &dst, FreeRectChoiceHeuristic method);
/// Inserts a single rectangle into the bin, possibly rotated.
Rect Insert(int width, int height, FreeRectChoiceHeuristic method);
/// Computes the ratio of used surface area to the total bin area.
float Occupancy() const;
std::pair<int, int> BottomRight() const;
private:
int binWidth;
int binHeight;
bool binAllowFlip;
std::vector<Rect> usedRectangles;
std::vector<Rect> freeRectangles;
/// Computes the placement score for placing the given rectangle with the given method.
/// @param score1 [out] The primary placement score will be outputted here.
/// @param score2 [out] The secondary placement score will be outputted here. This isu sed to break ties.
/// @return This struct identifies where the rectangle would be placed if it were placed.
Rect ScoreRect(int width, int height, FreeRectChoiceHeuristic method, int &score1, int &score2) const;
/// Places the given rectangle into the bin.
void PlaceRect(const Rect &node);
/// Computes the placement score for the -CP variant.
int ContactPointScoreNode(int x, int y, int width, int height) const;
Rect FindPositionForNewNodeBottomLeft(int width, int height, int &bestY, int &bestX) const;
Rect FindPositionForNewNodeBestShortSideFit(int width, int height, int &bestShortSideFit, int &bestLongSideFit) const;
Rect FindPositionForNewNodeBestLongSideFit(int width, int height, int &bestShortSideFit, int &bestLongSideFit) const;
Rect FindPositionForNewNodeBestAreaFit(int width, int height, int &bestAreaFit, int &bestShortSideFit) const;
Rect FindPositionForNewNodeContactPoint(int width, int height, int &contactScore) const;
/// @return True if the free node was split.
bool SplitFreeNode(Rect freeNode, const Rect &usedNode);
/// Goes through the free rectangle list and removes any redundant entries.
void PruneFreeList();
};
}