Repository files navigation

rectpack Build Status

Rectpack is a collection of heuristic algorithms for solving the 2D knapsack problem, also known as the bin packing problem. In essence packing a set of rectangles into the smallest number of bins.

alt tag

Installation

Download the package or clone the repository, and then install with:

python setup.py install

or use pypi:

pip install rectpack

Basic Usage

Packing rectangles into a number of bins is very simple:

fromrectpackimportnewPackerrectangles= [(100, 30), (40, 60), (30, 30),(70, 70), (100, 50), (30, 30)]
bins= [(300, 450), (80, 40), (200, 150)]
packer=newPacker()
# Add the rectangles to packing queueforrinrectangles:
packer.add_rect(*r)
# Add the bins where the rectangles will be placedforbinbins:
packer.add_bin(*b)
# Start packingpacker.pack()

Once the rectangles have been packed the results can be accessed individually

# Obtain number of bins used for packingnbins=len(packer)
# Index first binabin=packer[0]
# Bin dimmensions (bins can be reordered during packing)width, height=abin.width, abin.height# Number of rectangles packed into first binnrect=len(packer[0])
# Second bin first rectanglerect=packer[1][0]
# rect is a Rectangle objectx=rect.x# rectangle bottom-left x coordinatey=rect.y# rectangle bottom-left y coordinatew=rect.widthh=rect.height

looping over all of them

forabininpacker:
print(abin.bid) # Bin id if it has oneforrectinabin:
print(rect)

or using rect_list()

# Full rectangle listall_rects=packer.rect_list()
forrectinall_rects:
b, x, y, w, h, rid=rect# b - Bin index# x - Rectangle bottom-left corner x coordinate# y - Rectangle bottom-left corner y coordinate# w - Rectangle width# h - Rectangle height# rid - User asigned rectangle id or None

Lastly all the dimmension (bins and rectangles) must be integers or decimals to avoid collisions caused by floating point rounding. If your data is floating point use float2dec to convert float values to decimals (see float below)

API

A more detailed description of API calls:

  • class newPacker([, mode][, bin_algo][, pack_algo][, sort_algo][, rotation])
    Return a new packer object

    • mode: Mode of operations
      • PackingMode.Offline: The set of rectangles is known beforehand, packing won't start until pack() is called.
      • PackingMode.Online: The rectangles are unknown at the beginning of the job, and will be packed as soon as they are added.
    • bin_algo: Bin selection heuristic
      • PackingBin.BNF: (Bin Next Fit) If a rectangle doesn't fit into the current bin, close it and try next one.
      • PackingBin.BFF: (Bin First Fit) Pack rectangle into the first bin it fits (without closing)
      • PackingBin.BBF: (Bin Best Fit) Pack rectangle into the bin that gives best fitness.
      • PackingBin.Global: For each bin pack the rectangle with the best fitness until it is full, then continue with next bin.
    • pack_algo: One of the supported packing algorithms (see list below)
    • sort_algo: Rectangle sort order before packing (only for offline mode)
      • SORT_NONE: Rectangles left unsorted.
      • SORT_AREA: Sort by descending area.
      • SORT_PERI: Sort by descending perimeter.
      • SORT_DIFF: Sort by difference of rectangle sides.
      • SORT_SSIDE: Sort by shortest side.
      • SORT_LSIDE: Sort by longest side.
      • SORT_RATIO: Sort by ration between sides.
    • rotation: Enable or disable rectangle rotation.
  • packer.add_bin(width, height[, count][, bid])
    Add empty bin or bins to a packer

    • width: Bin width
    • height: Bin height
    • count: Number of bins to add, 1 by default. It's possible to add infinie bins with count=float("inf")
    • bid: Optional bin identifier
  • packer.add_rect(width, height[, rid])
    Add rectangle to packing queue

    • width: Rectangle width
    • height: Rectangle height
    • rid: User assigned rectangle id
  • packer.pack():
    Starts packing process (only for offline mode).

  • packer.rect_list():
    Returns the list of packed rectangles, each one represented by the tuple (b, x, y, w, h, rid) where:

    • b: Index for the bin the rectangle was packed into
    • x: X coordinate for the rectangle bottom-left corner
    • y: Y coordinate for the rectangle bottom-left corner
    • w: Rectangle width
    • h: Rectangle height
    • rid: User provided id or None

Supported Algorithms

This library implements three of the algorithms described in [1] Skyline, Maxrects, and Guillotine, with the following variants:

  • MaxRects

    • MaxRectsBl
    • MaxRectsBssf
    • MaxRectsBaf
    • MaxRectsBlsf
  • Skyline

    • SkylineBl
    • SkylineBlWm
    • SkylineMwf
    • SkylineMwfl
    • SkylineMwfWm
    • SkylineMwflWm
  • Guillotine

    • GuillotineBssfSas
    • GuillotineBssfLas
    • GuillotineBssfSlas
    • GuillotineBssfLlas
    • GuillotineBssfMaxas
    • GuillotineBssfMinas
    • GuillotineBlsfSas
    • GuillotineBlsfLas
    • GuillotineBlsfSlas
    • GuillotineBlsfLlas
    • GuillotineBlsfMaxas
    • GuillotineBlsfMinas
    • GuillotineBafSas
    • GuillotineBafLas
    • GuillotineBafSlas
    • GuillotineBafLlas
    • GuillotineBafMaxas
    • GuillotineBafMinas

I recommend to use the default algorithm unless the packing is too slow, in that case switch to one of the Guillotine variants for example GuillotineBssfSas. You can learn more about the algorithms in [1].

Testing

Rectpack is thoroughly tested, run the tests with:

python setup.py test

or

python -m unittest discover

Float

If you need to use floats just convert them to fixed-point using a Decimal type, be carefull rounding up so the actual rectangle size is always smaller than the conversion. Rectpack provides helper funcion float2dec for this task, it accepts a number and the number of decimals to round to, and returns the rounded Decimal.

fromrectpackimportfloat2dec, newPackerfloat_rects= [...]
dec_rects= [(float2dec(r[0], 3), float2dec(r[1], 3)) forrinfloat_rects]
p=newPacker()
...

References

[1] Jukka Jylang - A Thousand Ways to Pack the Bin - A Practical Approach to Two-Dimensional Rectangle Bin Packing (2010)

[2] Huang, E. Korf - Optimal Rectangle Packing: An Absolute Placement Approach (2013)

About

Python 2D rectangle packing library, with supporting the weight factor

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

rectpack Build Status

Rectpack is a collection of heuristic algorithms for solving the 2D knapsack problem, also known as the bin packing problem. In essence packing a set of rectangles into the smallest number of bins.

alt tag

Installation

Download the package or clone the repository, and then install with:

python setup.py install

or use pypi:

pip install rectpack

Basic Usage

Packing rectangles into a number of bins is very simple:

fromrectpackimportnewPackerrectangles= [(100, 30), (40, 60), (30, 30),(70, 70), (100, 50), (30, 30)]
bins= [(300, 450), (80, 40), (200, 150)]
packer=newPacker()
# Add the rectangles to packing queueforrinrectangles:
packer.add_rect(*r)
# Add the bins where the rectangles will be placedforbinbins:
packer.add_bin(*b)
# Start packingpacker.pack()

Once the rectangles have been packed the results can be accessed individually

# Obtain number of bins used for packingnbins=len(packer)
# Index first binabin=packer[0]
# Bin dimmensions (bins can be reordered during packing)width, height=abin.width, abin.height# Number of rectangles packed into first binnrect=len(packer[0])
# Second bin first rectanglerect=packer[1][0]
# rect is a Rectangle objectx=rect.x# rectangle bottom-left x coordinatey=rect.y# rectangle bottom-left y coordinatew=rect.widthh=rect.height

looping over all of them

forabininpacker:
print(abin.bid) # Bin id if it has oneforrectinabin:
print(rect)

or using rect_list()

# Full rectangle listall_rects=packer.rect_list()
forrectinall_rects:
b, x, y, w, h, rid=rect# b - Bin index# x - Rectangle bottom-left corner x coordinate# y - Rectangle bottom-left corner y coordinate# w - Rectangle width# h - Rectangle height# rid - User asigned rectangle id or None

Lastly all the dimmension (bins and rectangles) must be integers or decimals to avoid collisions caused by floating point rounding. If your data is floating point use float2dec to convert float values to decimals (see float below)

API

A more detailed description of API calls:

  • class newPacker([, mode][, bin_algo][, pack_algo][, sort_algo][, rotation])
    Return a new packer object

    • mode: Mode of operations
      • PackingMode.Offline: The set of rectangles is known beforehand, packing won't start until pack() is called.
      • PackingMode.Online: The rectangles are unknown at the beginning of the job, and will be packed as soon as they are added.
    • bin_algo: Bin selection heuristic
      • PackingBin.BNF: (Bin Next Fit) If a rectangle doesn't fit into the current bin, close it and try next one.
      • PackingBin.BFF: (Bin First Fit) Pack rectangle into the first bin it fits (without closing)
      • PackingBin.BBF: (Bin Best Fit) Pack rectangle into the bin that gives best fitness.
      • PackingBin.Global: For each bin pack the rectangle with the best fitness until it is full, then continue with next bin.
    • pack_algo: One of the supported packing algorithms (see list below)
    • sort_algo: Rectangle sort order before packing (only for offline mode)
      • SORT_NONE: Rectangles left unsorted.
      • SORT_AREA: Sort by descending area.
      • SORT_PERI: Sort by descending perimeter.
      • SORT_DIFF: Sort by difference of rectangle sides.
      • SORT_SSIDE: Sort by shortest side.
      • SORT_LSIDE: Sort by longest side.
      • SORT_RATIO: Sort by ration between sides.
    • rotation: Enable or disable rectangle rotation.
  • packer.add_bin(width, height[, count][, bid])
    Add empty bin or bins to a packer

    • width: Bin width
    • height: Bin height
    • count: Number of bins to add, 1 by default. It's possible to add infinie bins with count=float("inf")
    • bid: Optional bin identifier
  • packer.add_rect(width, height[, rid])
    Add rectangle to packing queue

    • width: Rectangle width
    • height: Rectangle height
    • rid: User assigned rectangle id
  • packer.pack():
    Starts packing process (only for offline mode).

  • packer.rect_list():
    Returns the list of packed rectangles, each one represented by the tuple (b, x, y, w, h, rid) where:

    • b: Index for the bin the rectangle was packed into
    • x: X coordinate for the rectangle bottom-left corner
    • y: Y coordinate for the rectangle bottom-left corner
    • w: Rectangle width
    • h: Rectangle height
    • rid: User provided id or None

Supported Algorithms

This library implements three of the algorithms described in [1] Skyline, Maxrects, and Guillotine, with the following variants:

  • MaxRects

    • MaxRectsBl
    • MaxRectsBssf
    • MaxRectsBaf
    • MaxRectsBlsf
  • Skyline

    • SkylineBl
    • SkylineBlWm
    • SkylineMwf
    • SkylineMwfl
    • SkylineMwfWm
    • SkylineMwflWm
  • Guillotine

    • GuillotineBssfSas
    • GuillotineBssfLas
    • GuillotineBssfSlas
    • GuillotineBssfLlas
    • GuillotineBssfMaxas
    • GuillotineBssfMinas
    • GuillotineBlsfSas
    • GuillotineBlsfLas
    • GuillotineBlsfSlas
    • GuillotineBlsfLlas
    • GuillotineBlsfMaxas
    • GuillotineBlsfMinas
    • GuillotineBafSas
    • GuillotineBafLas
    • GuillotineBafSlas
    • GuillotineBafLlas
    • GuillotineBafMaxas
    • GuillotineBafMinas

I recommend to use the default algorithm unless the packing is too slow, in that case switch to one of the Guillotine variants for example GuillotineBssfSas. You can learn more about the algorithms in [1].

Testing

Rectpack is thoroughly tested, run the tests with:

python setup.py test

or

python -m unittest discover

Float

If you need to use floats just convert them to fixed-point using a Decimal type, be carefull rounding up so the actual rectangle size is always smaller than the conversion. Rectpack provides helper funcion float2dec for this task, it accepts a number and the number of decimals to round to, and returns the rounded Decimal.

fromrectpackimportfloat2dec, newPackerfloat_rects= [...]
dec_rects= [(float2dec(r[0], 3), float2dec(r[1], 3)) forrinfloat_rects]
p=newPacker()
...

References

[1] Jukka Jylang - A Thousand Ways to Pack the Bin - A Practical Approach to Two-Dimensional Rectangle Bin Packing (2010)

[2] Huang, E. Korf - Optimal Rectangle Packing: An Absolute Placement Approach (2013)

About

Python 2D rectangle packing library, with supporting the weight factor

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

rectpack Build Status

Rectpack is a collection of heuristic algorithms for solving the 2D knapsack problem, also known as the bin packing problem. In essence packing a set of rectangles into the smallest number of bins.

alt tag

Installation

Download the package or clone the repository, and then install with:

python setup.py install

or use pypi:

pip install rectpack

Basic Usage

Packing rectangles into a number of bins is very simple:

fromrectpackimportnewPackerrectangles= [(100, 30), (40, 60), (30, 30),(70, 70), (100, 50), (30, 30)]
bins= [(300, 450), (80, 40), (200, 150)]
packer=newPacker()
# Add the rectangles to packing queueforrinrectangles:
packer.add_rect(*r)
# Add the bins where the rectangles will be placedforbinbins:
packer.add_bin(*b)
# Start packingpacker.pack()

Once the rectangles have been packed the results can be accessed individually

# Obtain number of bins used for packingnbins=len(packer)
# Index first binabin=packer[0]
# Bin dimmensions (bins can be reordered during packing)width, height=abin.width, abin.height# Number of rectangles packed into first binnrect=len(packer[0])
# Second bin first rectanglerect=packer[1][0]
# rect is a Rectangle objectx=rect.x# rectangle bottom-left x coordinatey=rect.y# rectangle bottom-left y coordinatew=rect.widthh=rect.height

looping over all of them

forabininpacker:
print(abin.bid) # Bin id if it has oneforrectinabin:
print(rect)

or using rect_list()

# Full rectangle listall_rects=packer.rect_list()
forrectinall_rects:
b, x, y, w, h, rid=rect# b - Bin index# x - Rectangle bottom-left corner x coordinate# y - Rectangle bottom-left corner y coordinate# w - Rectangle width# h - Rectangle height# rid - User asigned rectangle id or None

Lastly all the dimmension (bins and rectangles) must be integers or decimals to avoid collisions caused by floating point rounding. If your data is floating point use float2dec to convert float values to decimals (see float below)

API

A more detailed description of API calls:

  • class newPacker([, mode][, bin_algo][, pack_algo][, sort_algo][, rotation])
    Return a new packer object

    • mode: Mode of operations
      • PackingMode.Offline: The set of rectangles is known beforehand, packing won't start until pack() is called.
      • PackingMode.Online: The rectangles are unknown at the beginning of the job, and will be packed as soon as they are added.
    • bin_algo: Bin selection heuristic
      • PackingBin.BNF: (Bin Next Fit) If a rectangle doesn't fit into the current bin, close it and try next one.
      • PackingBin.BFF: (Bin First Fit) Pack rectangle into the first bin it fits (without closing)
      • PackingBin.BBF: (Bin Best Fit) Pack rectangle into the bin that gives best fitness.
      • PackingBin.Global: For each bin pack the rectangle with the best fitness until it is full, then continue with next bin.
    • pack_algo: One of the supported packing algorithms (see list below)
    • sort_algo: Rectangle sort order before packing (only for offline mode)
      • SORT_NONE: Rectangles left unsorted.
      • SORT_AREA: Sort by descending area.
      • SORT_PERI: Sort by descending perimeter.
      • SORT_DIFF: Sort by difference of rectangle sides.
      • SORT_SSIDE: Sort by shortest side.
      • SORT_LSIDE: Sort by longest side.
      • SORT_RATIO: Sort by ration between sides.
    • rotation: Enable or disable rectangle rotation.
  • packer.add_bin(width, height[, count][, bid])
    Add empty bin or bins to a packer

    • width: Bin width
    • height: Bin height
    • count: Number of bins to add, 1 by default. It's possible to add infinie bins with count=float("inf")
    • bid: Optional bin identifier
  • packer.add_rect(width, height[, rid])
    Add rectangle to packing queue

    • width: Rectangle width
    • height: Rectangle height
    • rid: User assigned rectangle id
  • packer.pack():
    Starts packing process (only for offline mode).

  • packer.rect_list():
    Returns the list of packed rectangles, each one represented by the tuple (b, x, y, w, h, rid) where:

    • b: Index for the bin the rectangle was packed into
    • x: X coordinate for the rectangle bottom-left corner
    • y: Y coordinate for the rectangle bottom-left corner
    • w: Rectangle width
    • h: Rectangle height
    • rid: User provided id or None

Supported Algorithms

This library implements three of the algorithms described in [1] Skyline, Maxrects, and Guillotine, with the following variants:

  • MaxRects

    • MaxRectsBl
    • MaxRectsBssf
    • MaxRectsBaf
    • MaxRectsBlsf
  • Skyline

    • SkylineBl
    • SkylineBlWm
    • SkylineMwf
    • SkylineMwfl
    • SkylineMwfWm
    • SkylineMwflWm
  • Guillotine

    • GuillotineBssfSas
    • GuillotineBssfLas
    • GuillotineBssfSlas
    • GuillotineBssfLlas
    • GuillotineBssfMaxas
    • GuillotineBssfMinas
    • GuillotineBlsfSas
    • GuillotineBlsfLas
    • GuillotineBlsfSlas
    • GuillotineBlsfLlas
    • GuillotineBlsfMaxas
    • GuillotineBlsfMinas
    • GuillotineBafSas
    • GuillotineBafLas
    • GuillotineBafSlas
    • GuillotineBafLlas
    • GuillotineBafMaxas
    • GuillotineBafMinas

I recommend to use the default algorithm unless the packing is too slow, in that case switch to one of the Guillotine variants for example GuillotineBssfSas. You can learn more about the algorithms in [1].

Testing

Rectpack is thoroughly tested, run the tests with:

python setup.py test

or

python -m unittest discover

Float

If you need to use floats just convert them to fixed-point using a Decimal type, be carefull rounding up so the actual rectangle size is always smaller than the conversion. Rectpack provides helper funcion float2dec for this task, it accepts a number and the number of decimals to round to, and returns the rounded Decimal.

fromrectpackimportfloat2dec, newPackerfloat_rects= [...]
dec_rects= [(float2dec(r[0], 3), float2dec(r[1], 3)) forrinfloat_rects]
p=newPacker()
...

References

[1] Jukka Jylang - A Thousand Ways to Pack the Bin - A Practical Approach to Two-Dimensional Rectangle Bin Packing (2010)

[2] Huang, E. Korf - Optimal Rectangle Packing: An Absolute Placement Approach (2013)

About

Python 2D rectangle packing library, with supporting the weight factor

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

rectpack Build Status

Rectpack is a collection of heuristic algorithms for solving the 2D knapsack problem, also known as the bin packing problem. In essence packing a set of rectangles into the smallest number of bins.

alt tag

Installation

Download the package or clone the repository, and then install with:

python setup.py install

or use pypi:

pip install rectpack

Basic Usage

Packing rectangles into a number of bins is very simple:

fromrectpackimportnewPackerrectangles= [(100, 30), (40, 60), (30, 30),(70, 70), (100, 50), (30, 30)]
bins= [(300, 450), (80, 40), (200, 150)]
packer=newPacker()
# Add the rectangles to packing queueforrinrectangles:
packer.add_rect(*r)
# Add the bins where the rectangles will be placedforbinbins:
packer.add_bin(*b)
# Start packingpacker.pack()

Once the rectangles have been packed the results can be accessed individually

# Obtain number of bins used for packingnbins=len(packer)
# Index first binabin=packer[0]
# Bin dimmensions (bins can be reordered during packing)width, height=abin.width, abin.height# Number of rectangles packed into first binnrect=len(packer[0])
# Second bin first rectanglerect=packer[1][0]
# rect is a Rectangle objectx=rect.x# rectangle bottom-left x coordinatey=rect.y# rectangle bottom-left y coordinatew=rect.widthh=rect.height

looping over all of them

forabininpacker:
print(abin.bid) # Bin id if it has oneforrectinabin:
print(rect)

or using rect_list()

# Full rectangle listall_rects=packer.rect_list()
forrectinall_rects:
b, x, y, w, h, rid=rect# b - Bin index# x - Rectangle bottom-left corner x coordinate# y - Rectangle bottom-left corner y coordinate# w - Rectangle width# h - Rectangle height# rid - User asigned rectangle id or None

Lastly all the dimmension (bins and rectangles) must be integers or decimals to avoid collisions caused by floating point rounding. If your data is floating point use float2dec to convert float values to decimals (see float below)

API

A more detailed description of API calls:

  • class newPacker([, mode][, bin_algo][, pack_algo][, sort_algo][, rotation])
    Return a new packer object

    • mode: Mode of operations
      • PackingMode.Offline: The set of rectangles is known beforehand, packing won't start until pack() is called.
      • PackingMode.Online: The rectangles are unknown at the beginning of the job, and will be packed as soon as they are added.
    • bin_algo: Bin selection heuristic
      • PackingBin.BNF: (Bin Next Fit) If a rectangle doesn't fit into the current bin, close it and try next one.
      • PackingBin.BFF: (Bin First Fit) Pack rectangle into the first bin it fits (without closing)
      • PackingBin.BBF: (Bin Best Fit) Pack rectangle into the bin that gives best fitness.
      • PackingBin.Global: For each bin pack the rectangle with the best fitness until it is full, then continue with next bin.
    • pack_algo: One of the supported packing algorithms (see list below)
    • sort_algo: Rectangle sort order before packing (only for offline mode)
      • SORT_NONE: Rectangles left unsorted.
      • SORT_AREA: Sort by descending area.
      • SORT_PERI: Sort by descending perimeter.
      • SORT_DIFF: Sort by difference of rectangle sides.
      • SORT_SSIDE: Sort by shortest side.
      • SORT_LSIDE: Sort by longest side.
      • SORT_RATIO: Sort by ration between sides.
    • rotation: Enable or disable rectangle rotation.
  • packer.add_bin(width, height[, count][, bid])
    Add empty bin or bins to a packer

    • width: Bin width
    • height: Bin height
    • count: Number of bins to add, 1 by default. It's possible to add infinie bins with count=float("inf")
    • bid: Optional bin identifier
  • packer.add_rect(width, height[, rid])
    Add rectangle to packing queue

    • width: Rectangle width
    • height: Rectangle height
    • rid: User assigned rectangle id
  • packer.pack():
    Starts packing process (only for offline mode).

  • packer.rect_list():
    Returns the list of packed rectangles, each one represented by the tuple (b, x, y, w, h, rid) where:

    • b: Index for the bin the rectangle was packed into
    • x: X coordinate for the rectangle bottom-left corner
    • y: Y coordinate for the rectangle bottom-left corner
    • w: Rectangle width
    • h: Rectangle height
    • rid: User provided id or None

Supported Algorithms

This library implements three of the algorithms described in [1] Skyline, Maxrects, and Guillotine, with the following variants:

  • MaxRects

    • MaxRectsBl
    • MaxRectsBssf
    • MaxRectsBaf
    • MaxRectsBlsf
  • Skyline

    • SkylineBl
    • SkylineBlWm
    • SkylineMwf
    • SkylineMwfl
    • SkylineMwfWm
    • SkylineMwflWm
  • Guillotine

    • GuillotineBssfSas
    • GuillotineBssfLas
    • GuillotineBssfSlas
    • GuillotineBssfLlas
    • GuillotineBssfMaxas
    • GuillotineBssfMinas
    • GuillotineBlsfSas
    • GuillotineBlsfLas
    • GuillotineBlsfSlas
    • GuillotineBlsfLlas
    • GuillotineBlsfMaxas
    • GuillotineBlsfMinas
    • GuillotineBafSas
    • GuillotineBafLas
    • GuillotineBafSlas
    • GuillotineBafLlas
    • GuillotineBafMaxas
    • GuillotineBafMinas

I recommend to use the default algorithm unless the packing is too slow, in that case switch to one of the Guillotine variants for example GuillotineBssfSas. You can learn more about the algorithms in [1].

Testing

Rectpack is thoroughly tested, run the tests with:

python setup.py test

or

python -m unittest discover

Float

If you need to use floats just convert them to fixed-point using a Decimal type, be carefull rounding up so the actual rectangle size is always smaller than the conversion. Rectpack provides helper funcion float2dec for this task, it accepts a number and the number of decimals to round to, and returns the rounded Decimal.

fromrectpackimportfloat2dec, newPackerfloat_rects= [...]
dec_rects= [(float2dec(r[0], 3), float2dec(r[1], 3)) forrinfloat_rects]
p=newPacker()
...

References

[1] Jukka Jylang - A Thousand Ways to Pack the Bin - A Practical Approach to Two-Dimensional Rectangle Bin Packing (2010)

[2] Huang, E. Korf - Optimal Rectangle Packing: An Absolute Placement Approach (2013)

About

Python 2D rectangle packing library, with supporting the weight factor

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

rectpack Build Status

Rectpack is a collection of heuristic algorithms for solving the 2D knapsack problem, also known as the bin packing problem. In essence packing a set of rectangles into the smallest number of bins.

alt tag

Installation

Download the package or clone the repository, and then install with:

python setup.py install

or use pypi:

pip install rectpack

Basic Usage

Packing rectangles into a number of bins is very simple:

fromrectpackimportnewPackerrectangles= [(100, 30), (40, 60), (30, 30),(70, 70), (100, 50), (30, 30)]
bins= [(300, 450), (80, 40), (200, 150)]
packer=newPacker()
# Add the rectangles to packing queueforrinrectangles:
packer.add_rect(*r)
# Add the bins where the rectangles will be placedforbinbins:
packer.add_bin(*b)
# Start packingpacker.pack()

Once the rectangles have been packed the results can be accessed individually

# Obtain number of bins used for packingnbins=len(packer)
# Index first binabin=packer[0]
# Bin dimmensions (bins can be reordered during packing)width, height=abin.width, abin.height# Number of rectangles packed into first binnrect=len(packer[0])
# Second bin first rectanglerect=packer[1][0]
# rect is a Rectangle objectx=rect.x# rectangle bottom-left x coordinatey=rect.y# rectangle bottom-left y coordinatew=rect.widthh=rect.height

looping over all of them

forabininpacker:
print(abin.bid) # Bin id if it has oneforrectinabin:
print(rect)

or using rect_list()

# Full rectangle listall_rects=packer.rect_list()
forrectinall_rects:
b, x, y, w, h, rid=rect# b - Bin index# x - Rectangle bottom-left corner x coordinate# y - Rectangle bottom-left corner y coordinate# w - Rectangle width# h - Rectangle height# rid - User asigned rectangle id or None

Lastly all the dimmension (bins and rectangles) must be integers or decimals to avoid collisions caused by floating point rounding. If your data is floating point use float2dec to convert float values to decimals (see float below)

API

A more detailed description of API calls:

  • class newPacker([, mode][, bin_algo][, pack_algo][, sort_algo][, rotation])
    Return a new packer object

    • mode: Mode of operations
      • PackingMode.Offline: The set of rectangles is known beforehand, packing won't start until pack() is called.
      • PackingMode.Online: The rectangles are unknown at the beginning of the job, and will be packed as soon as they are added.
    • bin_algo: Bin selection heuristic
      • PackingBin.BNF: (Bin Next Fit) If a rectangle doesn't fit into the current bin, close it and try next one.
      • PackingBin.BFF: (Bin First Fit) Pack rectangle into the first bin it fits (without closing)
      • PackingBin.BBF: (Bin Best Fit) Pack rectangle into the bin that gives best fitness.
      • PackingBin.Global: For each bin pack the rectangle with the best fitness until it is full, then continue with next bin.
    • pack_algo: One of the supported packing algorithms (see list below)
    • sort_algo: Rectangle sort order before packing (only for offline mode)
      • SORT_NONE: Rectangles left unsorted.
      • SORT_AREA: Sort by descending area.
      • SORT_PERI: Sort by descending perimeter.
      • SORT_DIFF: Sort by difference of rectangle sides.
      • SORT_SSIDE: Sort by shortest side.
      • SORT_LSIDE: Sort by longest side.
      • SORT_RATIO: Sort by ration between sides.
    • rotation: Enable or disable rectangle rotation.
  • packer.add_bin(width, height[, count][, bid])
    Add empty bin or bins to a packer

    • width: Bin width
    • height: Bin height
    • count: Number of bins to add, 1 by default. It's possible to add infinie bins with count=float("inf")
    • bid: Optional bin identifier
  • packer.add_rect(width, height[, rid])
    Add rectangle to packing queue

    • width: Rectangle width
    • height: Rectangle height
    • rid: User assigned rectangle id
  • packer.pack():
    Starts packing process (only for offline mode).

  • packer.rect_list():
    Returns the list of packed rectangles, each one represented by the tuple (b, x, y, w, h, rid) where:

    • b: Index for the bin the rectangle was packed into
    • x: X coordinate for the rectangle bottom-left corner
    • y: Y coordinate for the rectangle bottom-left corner
    • w: Rectangle width
    • h: Rectangle height
    • rid: User provided id or None

Supported Algorithms

This library implements three of the algorithms described in [1] Skyline, Maxrects, and Guillotine, with the following variants:

  • MaxRects

    • MaxRectsBl
    • MaxRectsBssf
    • MaxRectsBaf
    • MaxRectsBlsf
  • Skyline

    • SkylineBl
    • SkylineBlWm
    • SkylineMwf
    • SkylineMwfl
    • SkylineMwfWm
    • SkylineMwflWm
  • Guillotine

    • GuillotineBssfSas
    • GuillotineBssfLas
    • GuillotineBssfSlas
    • GuillotineBssfLlas
    • GuillotineBssfMaxas
    • GuillotineBssfMinas
    • GuillotineBlsfSas
    • GuillotineBlsfLas
    • GuillotineBlsfSlas
    • GuillotineBlsfLlas
    • GuillotineBlsfMaxas
    • GuillotineBlsfMinas
    • GuillotineBafSas
    • GuillotineBafLas
    • GuillotineBafSlas
    • GuillotineBafLlas
    • GuillotineBafMaxas
    • GuillotineBafMinas

I recommend to use the default algorithm unless the packing is too slow, in that case switch to one of the Guillotine variants for example GuillotineBssfSas. You can learn more about the algorithms in [1].

Testing

Rectpack is thoroughly tested, run the tests with:

python setup.py test

or

python -m unittest discover

Float

If you need to use floats just convert them to fixed-point using a Decimal type, be carefull rounding up so the actual rectangle size is always smaller than the conversion. Rectpack provides helper funcion float2dec for this task, it accepts a number and the number of decimals to round to, and returns the rounded Decimal.

fromrectpackimportfloat2dec, newPackerfloat_rects= [...]
dec_rects= [(float2dec(r[0], 3), float2dec(r[1], 3)) forrinfloat_rects]
p=newPacker()
...

References

[1] Jukka Jylang - A Thousand Ways to Pack the Bin - A Practical Approach to Two-Dimensional Rectangle Bin Packing (2010)

[2] Huang, E. Korf - Optimal Rectangle Packing: An Absolute Placement Approach (2013)

About

Python 2D rectangle packing library, with supporting the weight factor

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

rectpack Build Status

Rectpack is a collection of heuristic algorithms for solving the 2D knapsack problem, also known as the bin packing problem. In essence packing a set of rectangles into the smallest number of bins.

alt tag

Installation

Download the package or clone the repository, and then install with:

python setup.py install

or use pypi:

pip install rectpack

Basic Usage

Packing rectangles into a number of bins is very simple:

fromrectpackimportnewPackerrectangles= [(100, 30), (40, 60), (30, 30),(70, 70), (100, 50), (30, 30)]
bins= [(300, 450), (80, 40), (200, 150)]
packer=newPacker()
# Add the rectangles to packing queueforrinrectangles:
packer.add_rect(*r)
# Add the bins where the rectangles will be placedforbinbins:
packer.add_bin(*b)
# Start packingpacker.pack()

Once the rectangles have been packed the results can be accessed individually

# Obtain number of bins used for packingnbins=len(packer)
# Index first binabin=packer[0]
# Bin dimmensions (bins can be reordered during packing)width, height=abin.width, abin.height# Number of rectangles packed into first binnrect=len(packer[0])
# Second bin first rectanglerect=packer[1][0]
# rect is a Rectangle objectx=rect.x# rectangle bottom-left x coordinatey=rect.y# rectangle bottom-left y coordinatew=rect.widthh=rect.height

looping over all of them

forabininpacker:
print(abin.bid) # Bin id if it has oneforrectinabin:
print(rect)

or using rect_list()

# Full rectangle listall_rects=packer.rect_list()
forrectinall_rects:
b, x, y, w, h, rid=rect# b - Bin index# x - Rectangle bottom-left corner x coordinate# y - Rectangle bottom-left corner y coordinate# w - Rectangle width# h - Rectangle height# rid - User asigned rectangle id or None

Lastly all the dimmension (bins and rectangles) must be integers or decimals to avoid collisions caused by floating point rounding. If your data is floating point use float2dec to convert float values to decimals (see float below)

API

A more detailed description of API calls:

  • class newPacker([, mode][, bin_algo][, pack_algo][, sort_algo][, rotation])
    Return a new packer object

    • mode: Mode of operations
      • PackingMode.Offline: The set of rectangles is known beforehand, packing won't start until pack() is called.
      • PackingMode.Online: The rectangles are unknown at the beginning of the job, and will be packed as soon as they are added.
    • bin_algo: Bin selection heuristic
      • PackingBin.BNF: (Bin Next Fit) If a rectangle doesn't fit into the current bin, close it and try next one.
      • PackingBin.BFF: (Bin First Fit) Pack rectangle into the first bin it fits (without closing)
      • PackingBin.BBF: (Bin Best Fit) Pack rectangle into the bin that gives best fitness.
      • PackingBin.Global: For each bin pack the rectangle with the best fitness until it is full, then continue with next bin.
    • pack_algo: One of the supported packing algorithms (see list below)
    • sort_algo: Rectangle sort order before packing (only for offline mode)
      • SORT_NONE: Rectangles left unsorted.
      • SORT_AREA: Sort by descending area.
      • SORT_PERI: Sort by descending perimeter.
      • SORT_DIFF: Sort by difference of rectangle sides.
      • SORT_SSIDE: Sort by shortest side.
      • SORT_LSIDE: Sort by longest side.
      • SORT_RATIO: Sort by ration between sides.
    • rotation: Enable or disable rectangle rotation.
  • packer.add_bin(width, height[, count][, bid])
    Add empty bin or bins to a packer

    • width: Bin width
    • height: Bin height
    • count: Number of bins to add, 1 by default. It's possible to add infinie bins with count=float("inf")
    • bid: Optional bin identifier
  • packer.add_rect(width, height[, rid])
    Add rectangle to packing queue

    • width: Rectangle width
    • height: Rectangle height
    • rid: User assigned rectangle id
  • packer.pack():
    Starts packing process (only for offline mode).

  • packer.rect_list():
    Returns the list of packed rectangles, each one represented by the tuple (b, x, y, w, h, rid) where:

    • b: Index for the bin the rectangle was packed into
    • x: X coordinate for the rectangle bottom-left corner
    • y: Y coordinate for the rectangle bottom-left corner
    • w: Rectangle width
    • h: Rectangle height
    • rid: User provided id or None

Supported Algorithms

This library implements three of the algorithms described in [1] Skyline, Maxrects, and Guillotine, with the following variants:

  • MaxRects

    • MaxRectsBl
    • MaxRectsBssf
    • MaxRectsBaf
    • MaxRectsBlsf
  • Skyline

    • SkylineBl
    • SkylineBlWm
    • SkylineMwf
    • SkylineMwfl
    • SkylineMwfWm
    • SkylineMwflWm
  • Guillotine

    • GuillotineBssfSas
    • GuillotineBssfLas
    • GuillotineBssfSlas
    • GuillotineBssfLlas
    • GuillotineBssfMaxas
    • GuillotineBssfMinas
    • GuillotineBlsfSas
    • GuillotineBlsfLas
    • GuillotineBlsfSlas
    • GuillotineBlsfLlas
    • GuillotineBlsfMaxas
    • GuillotineBlsfMinas
    • GuillotineBafSas
    • GuillotineBafLas
    • GuillotineBafSlas
    • GuillotineBafLlas
    • GuillotineBafMaxas
    • GuillotineBafMinas

I recommend to use the default algorithm unless the packing is too slow, in that case switch to one of the Guillotine variants for example GuillotineBssfSas. You can learn more about the algorithms in [1].

Testing

Rectpack is thoroughly tested, run the tests with:

python setup.py test

or

python -m unittest discover

Float

If you need to use floats just convert them to fixed-point using a Decimal type, be carefull rounding up so the actual rectangle size is always smaller than the conversion. Rectpack provides helper funcion float2dec for this task, it accepts a number and the number of decimals to round to, and returns the rounded Decimal.

fromrectpackimportfloat2dec, newPackerfloat_rects= [...]
dec_rects= [(float2dec(r[0], 3), float2dec(r[1], 3)) forrinfloat_rects]
p=newPacker()
...

References

[1] Jukka Jylang - A Thousand Ways to Pack the Bin - A Practical Approach to Two-Dimensional Rectangle Bin Packing (2010)

[2] Huang, E. Korf - Optimal Rectangle Packing: An Absolute Placement Approach (2013)

About

Python 2D rectangle packing library, with supporting the weight factor

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

rectpack Build Status

Rectpack is a collection of heuristic algorithms for solving the 2D knapsack problem, also known as the bin packing problem. In essence packing a set of rectangles into the smallest number of bins.

alt tag

Installation

Download the package or clone the repository, and then install with:

python setup.py install

or use pypi:

pip install rectpack

Basic Usage

Packing rectangles into a number of bins is very simple:

fromrectpackimportnewPackerrectangles= [(100, 30), (40, 60), (30, 30),(70, 70), (100, 50), (30, 30)]
bins= [(300, 450), (80, 40), (200, 150)]
packer=newPacker()
# Add the rectangles to packing queueforrinrectangles:
packer.add_rect(*r)
# Add the bins where the rectangles will be placedforbinbins:
packer.add_bin(*b)
# Start packingpacker.pack()

Once the rectangles have been packed the results can be accessed individually

# Obtain number of bins used for packingnbins=len(packer)
# Index first binabin=packer[0]
# Bin dimmensions (bins can be reordered during packing)width, height=abin.width, abin.height# Number of rectangles packed into first binnrect=len(packer[0])
# Second bin first rectanglerect=packer[1][0]
# rect is a Rectangle objectx=rect.x# rectangle bottom-left x coordinatey=rect.y# rectangle bottom-left y coordinatew=rect.widthh=rect.height

looping over all of them

forabininpacker:
print(abin.bid) # Bin id if it has oneforrectinabin:
print(rect)

or using rect_list()

# Full rectangle listall_rects=packer.rect_list()
forrectinall_rects:
b, x, y, w, h, rid=rect# b - Bin index# x - Rectangle bottom-left corner x coordinate# y - Rectangle bottom-left corner y coordinate# w - Rectangle width# h - Rectangle height# rid - User asigned rectangle id or None

Lastly all the dimmension (bins and rectangles) must be integers or decimals to avoid collisions caused by floating point rounding. If your data is floating point use float2dec to convert float values to decimals (see float below)

API

A more detailed description of API calls:

  • class newPacker([, mode][, bin_algo][, pack_algo][, sort_algo][, rotation])
    Return a new packer object

    • mode: Mode of operations
      • PackingMode.Offline: The set of rectangles is known beforehand, packing won't start until pack() is called.
      • PackingMode.Online: The rectangles are unknown at the beginning of the job, and will be packed as soon as they are added.
    • bin_algo: Bin selection heuristic
      • PackingBin.BNF: (Bin Next Fit) If a rectangle doesn't fit into the current bin, close it and try next one.
      • PackingBin.BFF: (Bin First Fit) Pack rectangle into the first bin it fits (without closing)
      • PackingBin.BBF: (Bin Best Fit) Pack rectangle into the bin that gives best fitness.
      • PackingBin.Global: For each bin pack the rectangle with the best fitness until it is full, then continue with next bin.
    • pack_algo: One of the supported packing algorithms (see list below)
    • sort_algo: Rectangle sort order before packing (only for offline mode)
      • SORT_NONE: Rectangles left unsorted.
      • SORT_AREA: Sort by descending area.
      • SORT_PERI: Sort by descending perimeter.
      • SORT_DIFF: Sort by difference of rectangle sides.
      • SORT_SSIDE: Sort by shortest side.
      • SORT_LSIDE: Sort by longest side.
      • SORT_RATIO: Sort by ration between sides.
    • rotation: Enable or disable rectangle rotation.
  • packer.add_bin(width, height[, count][, bid])
    Add empty bin or bins to a packer

    • width: Bin width
    • height: Bin height
    • count: Number of bins to add, 1 by default. It's possible to add infinie bins with count=float("inf")
    • bid: Optional bin identifier
  • packer.add_rect(width, height[, rid])
    Add rectangle to packing queue

    • width: Rectangle width
    • height: Rectangle height
    • rid: User assigned rectangle id
  • packer.pack():
    Starts packing process (only for offline mode).

  • packer.rect_list():
    Returns the list of packed rectangles, each one represented by the tuple (b, x, y, w, h, rid) where:

    • b: Index for the bin the rectangle was packed into
    • x: X coordinate for the rectangle bottom-left corner
    • y: Y coordinate for the rectangle bottom-left corner
    • w: Rectangle width
    • h: Rectangle height
    • rid: User provided id or None

Supported Algorithms

This library implements three of the algorithms described in [1] Skyline, Maxrects, and Guillotine, with the following variants:

  • MaxRects

    • MaxRectsBl
    • MaxRectsBssf
    • MaxRectsBaf
    • MaxRectsBlsf
  • Skyline

    • SkylineBl
    • SkylineBlWm
    • SkylineMwf
    • SkylineMwfl
    • SkylineMwfWm
    • SkylineMwflWm
  • Guillotine

    • GuillotineBssfSas
    • GuillotineBssfLas
    • GuillotineBssfSlas
    • GuillotineBssfLlas
    • GuillotineBssfMaxas
    • GuillotineBssfMinas
    • GuillotineBlsfSas
    • GuillotineBlsfLas
    • GuillotineBlsfSlas
    • GuillotineBlsfLlas
    • GuillotineBlsfMaxas
    • GuillotineBlsfMinas
    • GuillotineBafSas
    • GuillotineBafLas
    • GuillotineBafSlas
    • GuillotineBafLlas
    • GuillotineBafMaxas
    • GuillotineBafMinas

I recommend to use the default algorithm unless the packing is too slow, in that case switch to one of the Guillotine variants for example GuillotineBssfSas. You can learn more about the algorithms in [1].

Testing

Rectpack is thoroughly tested, run the tests with:

python setup.py test

or

python -m unittest discover

Float

If you need to use floats just convert them to fixed-point using a Decimal type, be carefull rounding up so the actual rectangle size is always smaller than the conversion. Rectpack provides helper funcion float2dec for this task, it accepts a number and the number of decimals to round to, and returns the rounded Decimal.

fromrectpackimportfloat2dec, newPackerfloat_rects= [...]
dec_rects= [(float2dec(r[0], 3), float2dec(r[1], 3)) forrinfloat_rects]
p=newPacker()
...

References

[1] Jukka Jylang - A Thousand Ways to Pack the Bin - A Practical Approach to Two-Dimensional Rectangle Bin Packing (2010)

[2] Huang, E. Korf - Optimal Rectangle Packing: An Absolute Placement Approach (2013)

About

Python 2D rectangle packing library, with supporting the weight factor

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

rectpack Build Status

Rectpack is a collection of heuristic algorithms for solving the 2D knapsack problem, also known as the bin packing problem. In essence packing a set of rectangles into the smallest number of bins.

alt tag

Installation

Download the package or clone the repository, and then install with:

python setup.py install

or use pypi:

pip install rectpack

Basic Usage

Packing rectangles into a number of bins is very simple:

fromrectpackimportnewPackerrectangles= [(100, 30), (40, 60), (30, 30),(70, 70), (100, 50), (30, 30)]
bins= [(300, 450), (80, 40), (200, 150)]
packer=newPacker()
# Add the rectangles to packing queueforrinrectangles:
packer.add_rect(*r)
# Add the bins where the rectangles will be placedforbinbins:
packer.add_bin(*b)
# Start packingpacker.pack()

Once the rectangles have been packed the results can be accessed individually

# Obtain number of bins used for packingnbins=len(packer)
# Index first binabin=packer[0]
# Bin dimmensions (bins can be reordered during packing)width, height=abin.width, abin.height# Number of rectangles packed into first binnrect=len(packer[0])
# Second bin first rectanglerect=packer[1][0]
# rect is a Rectangle objectx=rect.x# rectangle bottom-left x coordinatey=rect.y# rectangle bottom-left y coordinatew=rect.widthh=rect.height

looping over all of them

forabininpacker:
print(abin.bid) # Bin id if it has oneforrectinabin:
print(rect)

or using rect_list()

# Full rectangle listall_rects=packer.rect_list()
forrectinall_rects:
b, x, y, w, h, rid=rect# b - Bin index# x - Rectangle bottom-left corner x coordinate# y - Rectangle bottom-left corner y coordinate# w - Rectangle width# h - Rectangle height# rid - User asigned rectangle id or None

Lastly all the dimmension (bins and rectangles) must be integers or decimals to avoid collisions caused by floating point rounding. If your data is floating point use float2dec to convert float values to decimals (see float below)

API

A more detailed description of API calls:

  • class newPacker([, mode][, bin_algo][, pack_algo][, sort_algo][, rotation])
    Return a new packer object

    • mode: Mode of operations
      • PackingMode.Offline: The set of rectangles is known beforehand, packing won't start until pack() is called.
      • PackingMode.Online: The rectangles are unknown at the beginning of the job, and will be packed as soon as they are added.
    • bin_algo: Bin selection heuristic
      • PackingBin.BNF: (Bin Next Fit) If a rectangle doesn't fit into the current bin, close it and try next one.
      • PackingBin.BFF: (Bin First Fit) Pack rectangle into the first bin it fits (without closing)
      • PackingBin.BBF: (Bin Best Fit) Pack rectangle into the bin that gives best fitness.
      • PackingBin.Global: For each bin pack the rectangle with the best fitness until it is full, then continue with next bin.
    • pack_algo: One of the supported packing algorithms (see list below)
    • sort_algo: Rectangle sort order before packing (only for offline mode)
      • SORT_NONE: Rectangles left unsorted.
      • SORT_AREA: Sort by descending area.
      • SORT_PERI: Sort by descending perimeter.
      • SORT_DIFF: Sort by difference of rectangle sides.
      • SORT_SSIDE: Sort by shortest side.
      • SORT_LSIDE: Sort by longest side.
      • SORT_RATIO: Sort by ration between sides.
    • rotation: Enable or disable rectangle rotation.
  • packer.add_bin(width, height[, count][, bid])
    Add empty bin or bins to a packer

    • width: Bin width
    • height: Bin height
    • count: Number of bins to add, 1 by default. It's possible to add infinie bins with count=float("inf")
    • bid: Optional bin identifier
  • packer.add_rect(width, height[, rid])
    Add rectangle to packing queue

    • width: Rectangle width
    • height: Rectangle height
    • rid: User assigned rectangle id
  • packer.pack():
    Starts packing process (only for offline mode).

  • packer.rect_list():
    Returns the list of packed rectangles, each one represented by the tuple (b, x, y, w, h, rid) where:

    • b: Index for the bin the rectangle was packed into
    • x: X coordinate for the rectangle bottom-left corner
    • y: Y coordinate for the rectangle bottom-left corner
    • w: Rectangle width
    • h: Rectangle height
    • rid: User provided id or None

Supported Algorithms

This library implements three of the algorithms described in [1] Skyline, Maxrects, and Guillotine, with the following variants:

  • MaxRects

    • MaxRectsBl
    • MaxRectsBssf
    • MaxRectsBaf
    • MaxRectsBlsf
  • Skyline

    • SkylineBl
    • SkylineBlWm
    • SkylineMwf
    • SkylineMwfl
    • SkylineMwfWm
    • SkylineMwflWm
  • Guillotine

    • GuillotineBssfSas
    • GuillotineBssfLas
    • GuillotineBssfSlas
    • GuillotineBssfLlas
    • GuillotineBssfMaxas
    • GuillotineBssfMinas
    • GuillotineBlsfSas
    • GuillotineBlsfLas
    • GuillotineBlsfSlas
    • GuillotineBlsfLlas
    • GuillotineBlsfMaxas
    • GuillotineBlsfMinas
    • GuillotineBafSas
    • GuillotineBafLas
    • GuillotineBafSlas
    • GuillotineBafLlas
    • GuillotineBafMaxas
    • GuillotineBafMinas

I recommend to use the default algorithm unless the packing is too slow, in that case switch to one of the Guillotine variants for example GuillotineBssfSas. You can learn more about the algorithms in [1].

Testing

Rectpack is thoroughly tested, run the tests with:

python setup.py test

or

python -m unittest discover

Float

If you need to use floats just convert them to fixed-point using a Decimal type, be carefull rounding up so the actual rectangle size is always smaller than the conversion. Rectpack provides helper funcion float2dec for this task, it accepts a number and the number of decimals to round to, and returns the rounded Decimal.

fromrectpackimportfloat2dec, newPackerfloat_rects= [...]
dec_rects= [(float2dec(r[0], 3), float2dec(r[1], 3)) forrinfloat_rects]
p=newPacker()
...

References

[1] Jukka Jylang - A Thousand Ways to Pack the Bin - A Practical Approach to Two-Dimensional Rectangle Bin Packing (2010)

[2] Huang, E. Korf - Optimal Rectangle Packing: An Absolute Placement Approach (2013)

About

Python 2D rectangle packing library, with supporting the weight factor

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages