SkylineBinPack.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /** @file SkylineBinPack.h
  2. @author Jukka Jylänki
  3. @brief Implements different bin packer algorithms that use the SKYLINE data structure.
  4. This work is released to Public Domain, do whatever you want with it.
  5. */
  6. #pragma once
  7. #include "Rect.h"
  8. #include "GuillotineBinPack.h"
  9. /** Implements bin packing algorithms that use the SKYLINE data structure to store the bin contents. Uses
  10. GuillotineBinPack as the waste map. */
  11. class SkylineBinPack
  12. {
  13. public:
  14. /// Instantiates a bin of size (0,0). Call Init to create a new bin.
  15. SkylineBinPack();
  16. /// Instantiates a bin of the given size.
  17. SkylineBinPack(int binWidth, int binHeight, bool useWasteMap, bool allowRotate);
  18. /// (Re)initializes the packer to an empty bin of width x height units. Call whenever
  19. /// you need to restart with a new bin.
  20. void Init(int binWidth, int binHeight, bool useWasteMap, bool allowRotate);
  21. /// Defines the different heuristic rules that can be used to decide how to make the rectangle placements.
  22. enum LevelChoiceHeuristic
  23. {
  24. LevelBottomLeft,
  25. LevelMinWasteFit
  26. };
  27. /// Inserts the given list of rectangles in an offline/batch mode, possibly rotated.
  28. /// @param rects The list of rectangles to insert. This vector will be destroyed in the process.
  29. /// @param dst [out] This list will contain the packed rectangles. The indices will not correspond to that of rects.
  30. /// @param method The rectangle placement rule to use when packing.
  31. void Insert(Memp<RectSizeIndex> rects, Memp<RectIndex> dst, LevelChoiceHeuristic method);
  32. /// Inserts a single rectangle into the bin, possibly rotated.
  33. Rect Insert(int width, int height, LevelChoiceHeuristic method);
  34. /// Computes the ratio of used surface area to the total bin area.
  35. float Occupancy() const;
  36. private:
  37. int binWidth;
  38. int binHeight;
  39. bool useWasteMap;
  40. bool allowRotate;
  41. #ifdef DEBUG
  42. DisjointRectCollection disjointRects;
  43. #endif
  44. /// Represents a single level (a horizontal line) of the skyline/horizon/envelope.
  45. struct SkylineNode
  46. {
  47. /// The starting x-coordinate (leftmost).
  48. int x;
  49. /// The y-coordinate of the skyline level line.
  50. int y;
  51. /// The line width. The ending coordinate (inclusive) will be x+width-1.
  52. int width;
  53. };
  54. Memc<SkylineNode> skyLine;
  55. unsigned long usedSurfaceArea;
  56. /// If true, we use the GuillotineBinPack structure to recover wasted areas into a waste map.
  57. GuillotineBinPack wasteMap;
  58. Rect InsertBottomLeft(int width, int height);
  59. Rect InsertMinWaste(int width, int height);
  60. Rect FindPositionForNewNodeMinWaste(int width, int height, int &bestHeight, int &bestWastedArea, int &bestIndex) const;
  61. Rect FindPositionForNewNodeBottomLeft(int width, int height, int &bestHeight, int &bestWidth, int &bestIndex) const;
  62. bool RectangleFits(int skylineNodeIndex, int width, int height, int &y) const;
  63. bool RectangleFits(int skylineNodeIndex, int width, int height, int &y, int &wastedArea) const;
  64. int ComputeWastedArea(int skylineNodeIndex, int width, int height, int y) const;
  65. void AddWasteMapArea(int skylineNodeIndex, int width, int height, int y);
  66. void AddSkylineLevel(int skylineNodeIndex, const Rect &rect);
  67. /// Merges all skyline nodes that are at the same level.
  68. void MergeSkylines();
  69. };