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 108 109 110 111 112 113 114 115 116
use crate::block::{Block, Dimension}; use crate::error::Result; use crate::item::Item; /// Represents an bin that a user can insert items into. /// ```rust /// use bin_packer_3d::bin::Bin; /// let bin = Bin::new([1.0, 2.0, 3.0]); /// ``` #[derive(Clone, Debug)] pub struct Bin<'a> { /// Represents the cuboid of this bin. blocks: Vec<Block>, /// Represents the items that are currently packed inside this bin. pub items: Vec<Item<'a>>, } impl<'a> Bin<'a> { /// Creates a new Bin from it's dimensions. pub fn new<F: Into<Dimension> + Copy>(dims: [F; 3]) -> Self { Self { blocks: vec![Block::new(dims[0], dims[1], dims[2])], items: vec![], } } /** Returns whether or not the Bin's dimensions can emcompass or match the item. An item that fits into a bin: ```rust use bin_packer_3d::bin::Bin; use bin_packer_3d::item::Item; let item = Item::new("item1", [1.0, 2.0, 3.0]); let bin = Bin::new([1.0, 2.0, 3.0]); assert!(bin.fits(&item)); ``` An item that does not fit into a bin: ```rust use bin_packer_3d::bin::Bin; use bin_packer_3d::item::Item; let item = Item::new("item2", [4.0, 12.0, 14.0]); let bin = Bin::new([3.0, 12.0, 14.0]); assert!(!bin.fits(&item)); ``` **/ pub fn fits(&self, item: &Item<'_>) -> bool { self.blocks .iter() .any(|block| block.does_it_fit(&item.block)) } /** Add the item to the bin Returns None if the item cannot be packed into the bin. ```rust use bin_packer_3d::bin::Bin; use bin_packer_3d::item::{Item, ItemId}; let item_1 = Item::new("item1", [24.0, 10.0, 2.0]); let item_2 = Item::new("item2", [24.0, 10.0, 2.0]); let item_3 = Item::new("item3", [24.0, 10.0, 2.0]); let mut bin = Bin::new([24.0, 10.0, 4.0]); assert!(bin.try_packing(item_1).is_some()); assert!(bin.try_packing(item_2).is_some()); assert_eq!(bin.try_packing(item_3), None); assert_eq!( bin.items .into_iter() .map(|item| item.id) .collect::<Vec<&ItemId>>(), vec!["item1", "item2"] ); ``` **/ pub fn try_packing(&mut self, item: Item<'a>) -> Option<()> { let block_to_pack_index = self.blocks .iter() .enumerate() .find_map(|(block_index, block)| { if block.does_it_fit(&item.block) { Some(block_index) } else { None } })?; let block_to_pack = self.blocks.remove(block_to_pack_index); self.blocks.append( &mut block_to_pack .best_fit(&item.block) .expect("Invalid state - the block doesn't fit the item."), ); self.items.push(item); Some(()) } /** Returns a new bin that is the same dimensions as the original bin, but without any items. ```rust use bin_packer_3d::bin::Bin; use bin_packer_3d::item::{Item, ItemId}; let bin = Bin::new([24.0, 10.0, 4.0]); let new_bin = bin.clone_as_empty_bin(); ``` **/ pub fn clone_as_empty_bin(&self) -> Self { Self { blocks: self.blocks.clone(), items: vec![], } } }