A heuristic first-fit 3D bin packing algorithm with optional weight and bin limits.
Install gem:
gem install 'box_packer'
Or add to gemfile:
gem 'box_packer'
require 'box_packer'
BoxPacker.container [3, 6, 7] do
add_item [1,3,5]
add_item [4,3,5]
add_item [3,5,5]
pack! # 2
puts packed_successfully # true
puts packings.count # 2
puts packings[0].include? items[1] # false
puts packings[0][1].position # (5,0,0)
puts self # |Container| 7x6x3
# | Packing| Remaining Volume:36
# | Item| 5x5x3 (0,0,0) Volume:75
# | Item| 1x5x3 (5,0,0) Volume:15
# | Packing| Remaining Volume:66
# | Item| 5x4x3 (0,0,0) Volume:60
end
With optional labels, weights, quantity and packings limit:
BoxPacker.container [15, 20, 13], label: 'Parcel', weight_limit: 50, packings_limit: 3 do
add_item [2, 3, 5], label: 'Shoes', weight: 47, quantity: 2
add_item [3, 3, 1], label: 'Watch', weight: 24
add_item [1, 1, 4], label: 'Bag', weight: 7
pack! # 3
puts self # |Container| Parcel 20x15x13 Weight Limit:50 Packings Limit:3
# | Packing| Remaining Volume:3870 Remaining Weight:3
# | Item| Shoes 5x3x2 (0,0,0) Volume:30 Weight:47
# | Packing| Remaining Volume:3870 Remaining Weight:3
# | Item| Shoes 5x3x2 (0,0,0) Volume:30 Weight:47
# | Packing| Remaining Volume:3887 Remaining Weight:19
# | Item| Watch 3x3x1 (0,0,0) Volume:9 Weight:24
# | Item| Bag 4x1x1 (3,0,0) Volume:4 Weight:7
end
Alternative builder API:
BoxPacker.builder do |b|
c1 = b.container [10,5,11]
c2 = b.container [17,23,14]
c1.items = [b.item([1,1,4]), b.item([4,6,7]), b.item([5,8,10])]
c2.items = c1.items
c1.pack! # 2
c2.pack! # 1
puts c1 # |Container| 11x10x5
# | Packing| Remaining Volume:146
# | Item| 10x8x5 (0,0,0) Volume:400
# | Item| 4x1x1 (0,8,0) Volume:4
# | Packing| Remaining Volume:382
# | Item| 7x6x4 (10,0,0) Volume:168
puts c2 # |Container| 23x17x14
# | Packing| Remaining Volume:4902
# | Item| 10x8x5 (0,0,0) Volume:400
# | Item| 7x6x4 (10,0,0) Volume:168
# | Item| 4x1x1 (17,0,0) Volume:4
end
BoxPacker.container [3, 4, 2] do
add_item [1,3,2], label: 'Bag', colour: 'red'
add_item [3,3,1], label: 'Hat', colour: 'blue'
add_item [1,2,2], label: 'Shoes', colour: 'green'
add_item [3,1,1], label: 'Slipper', colour: 'purple'
add_item [2,1,1], label: 'Dragon', colour: 'orange'
pack!
draw!('examples/example', scale_longest_side_to: 500, margin: 15)
end
Output: