public List <ContainerPackingResult> Pack(Container container, List <Item> itemsToPack) { var result = new List <ContainerPackingResult>(); var containerPackingResult = new ContainerPackingResult(); containerPackingResult.ContainerID = container.ID; var algorithm = GetPackingAlgorithmFromTypeID(1); //magic # // only enum avail in this 3rd party tool // Until I rewrite the algorithm with no side effects, we need to clone the item list // so the parallel updates don't interfere with each other. var items = new List <Item>(); itemsToPack.ForEach(item => { items.Add(new Item(item.ID, item.Dim1, item.Dim2, item.Dim3, item.Quantity)); }); var algorithmResult = algorithm.Run(container, items); var containerVolume = container.Length * container.Width * container.Height; var itemVolumePacked = algorithmResult.PackedItems.Sum(i => i.Volume); var itemVolumeUnpacked = algorithmResult.UnpackedItems.Sum(i => i.Volume); algorithmResult.PercentContainerVolumePacked = Math.Round(itemVolumePacked / containerVolume * 100, 2); algorithmResult.PercentItemVolumePacked = Math.Round(itemVolumePacked / (itemVolumePacked + itemVolumeUnpacked) * 100, 2); lock (sync) { containerPackingResult.AlgorithmPackingResults.Add(algorithmResult); } return(result); }
/// <summary> /// Attempts to pack the specified containers with the specified items using the specified algorithms. /// </summary> /// <param name="containers">The list of containers to pack.</param> /// <param name="itemsToPack">The items to pack.</param> /// <param name="algorithmTypeIDs">The list of algorithm type IDs to use for packing.</param> /// <returns>A container packing result with lists of the packed and unpacked items.</returns> public static List <ContainerPackingResult> Pack(List <Container> containers, List <Item> itemsToPack, List <int> algorithmTypeIDs) { Object sync = new Object { }; List <ContainerPackingResult> result = new List <ContainerPackingResult>(); Parallel.ForEach(containers, container => { ContainerPackingResult containerPackingResult = new ContainerPackingResult(); containerPackingResult.ContainerID = container.ID; Parallel.ForEach(algorithmTypeIDs, algorithmTypeID => { IPackingAlgorithm algorithm = PackingService.GetPackingAlgorithmFromTypeID(algorithmTypeID); // Until I rewrite the algorithm with no side effects, we need to clone the item list // so the parallel updates don't interfere with each other. List <Item> items = new List <Item>(); itemsToPack.ForEach(item => { items.Add(new Item(item.ID, item.Length, item.Width, item.Height, item.Quantity)); }); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); AlgorithmPackingResult algorithmResult = algorithm.Run(container, items); stopwatch.Stop(); algorithmResult.PackTimeInMilliseconds = stopwatch.ElapsedMilliseconds; decimal containerVolume = container.Length * container.Width * container.Height; decimal volumePacked = 0; algorithmResult.PackedItems.ForEach(item => { volumePacked += item.Volume; }); algorithmResult.PercentContainerVolumePacked = (int)Math.Ceiling(volumePacked / containerVolume * 100); lock (sync) { containerPackingResult.AlgorithmPackingResults.Add(algorithmResult); } }); containerPackingResult.AlgorithmPackingResults = containerPackingResult.AlgorithmPackingResults.OrderBy(r => r.AlgorithmName).ToList(); lock (sync) { result.Add(containerPackingResult); } }); return(result); }
/// <summary> /// Attempts to pack the specified containers with the specified items using the specified algorithms. /// </summary> /// <param name="containers">The list of containers to pack.</param> /// <param name="itemsToPack">The items to pack.</param> /// <param name="algorithmTypeIDs">The list of algorithm type IDs to use for packing.</param> /// <returns>A container packing result with lists of the packed and unpacked items.</returns> public List <ContainerPackingResult> Pack(List <Container> containers, List <Item> itemsToPack, List <int> algorithmTypeIDs) { var sync = new object(); var result = new List <ContainerPackingResult>(); Parallel.ForEach(containers, container => { var containerPackingResult = new ContainerPackingResult(); containerPackingResult.ContainerID = container.ID; Parallel.ForEach(algorithmTypeIDs, algorithmTypeID => { var algorithm = GetPackingAlgorithmFromTypeID(algorithmTypeID); // Until I rewrite the algorithm with no side effects, we need to clone the item list // so the parallel updates don't interfere with each other. var items = new List <Item>(); itemsToPack.ForEach(item => { items.Add(new Item(item.ID, item.Dim1, item.Dim2, item.Dim3, item.Quantity)); }); var stopwatch = new Stopwatch(); stopwatch.Start(); var algorithmResult = algorithm.Run(container, items); stopwatch.Stop(); algorithmResult.PackTimeInMilliseconds = stopwatch.ElapsedMilliseconds; var containerVolume = container.Length * container.Width * container.Height; var itemVolumePacked = algorithmResult.PackedItems.Sum(i => i.Volume); var itemVolumeUnpacked = algorithmResult.UnpackedItems.Sum(i => i.Volume); algorithmResult.PercentContainerVolumePacked = Math.Round(itemVolumePacked / containerVolume * 100, 2); algorithmResult.PercentItemVolumePacked = Math.Round(itemVolumePacked / (itemVolumePacked + itemVolumeUnpacked) * 100, 2); lock (sync) { containerPackingResult.AlgorithmPackingResults.Add(algorithmResult); } }); containerPackingResult.AlgorithmPackingResults = containerPackingResult.AlgorithmPackingResults .OrderBy(r => r.AlgorithmName).ToList(); lock (sync) { result.Add(containerPackingResult); } }); return(result); }
/// <summary> /// Attempts to pack the specified containers with the specified items using the specified algorithms. /// </summary> /// <param name="containers">The list of containers to pack.</param> /// <param name="itemsToPack">The items to pack.</param> /// <param name="algorithmTypeIDs">The list of algorithm type IDs to use for packing.</param> /// <returns>A container packing result with lists of the packed and unpacked items.</returns> public static List <ContainerPackingResult> Pack(Container containers, List <Item> itemsToPack, List <int> algorithmTypeIDs) { Object sync = new Object { }; List <ContainerPackingResult> result = new List <ContainerPackingResult>(); //Parallel.ForEach(containers, container => //{ ContainerPackingResult containerPackingResult = new ContainerPackingResult(); containerPackingResult.ContainerID = containers.Id; containerPackingResult.ContainerName = containers.Name; containerPackingResult.Weight = containers.Weight; Parallel.ForEach(algorithmTypeIDs, algorithmTypeID => { IPackingAlgorithm algorithm = PackingService.GetPackingAlgorithmFromTypeID(algorithmTypeID); // Until I rewrite the algorithm with no side effects, we need to clone the item list // so the parallel updates don't interfere with each other. List <Item> items = new List <Item>(); itemsToPack.ForEach(item => { items.Add(new Item(item.Name, item.Dim1, item.Dim2, item.Dim3, item.Quantity)); }); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); AlgorithmPackingResult algorithmResult = algorithm.Run(containers, items); stopwatch.Stop(); algorithmResult.PackTimeInMilliseconds = stopwatch.ElapsedMilliseconds; decimal containerVolume = containers.Length * containers.Width * containers.Height; decimal itemVolumePacked = algorithmResult.PackedItems.Sum(i => i.Volume); decimal itemVolumeUnpacked = algorithmResult.UnpackedItems.Sum(i => i.Volume); algorithmResult.PercentContainerVolumePacked = Math.Round(itemVolumePacked / containerVolume * 100, 2); algorithmResult.PercentItemVolumePacked = Math.Round(itemVolumePacked / (itemVolumePacked + itemVolumeUnpacked) * 100, 2); lock (sync) { containerPackingResult.AlgorithmPackingResults.Add(algorithmResult); } }); containerPackingResult.AlgorithmPackingResults = containerPackingResult.AlgorithmPackingResults.OrderBy(r => r.AlgorithmName).ToList(); lock (sync) { result.Add(containerPackingResult); } //}); return(result); }
public static Dictionary <string, object> Pack3D( Cuboid bin, List <Cuboid> items) { decimal length = Convert.ToDecimal(bin.Length); decimal width = Convert.ToDecimal(bin.Width); decimal height = Convert.ToDecimal(bin.Height); List <Container> container = new List <Container> { new Container(1, length, width, height) }; List <Item> itemsToPack = ItemsFromCuboids(items); //Dictionary to map Item Id with Cuboid index Dictionary <int, int> idDict = IdFromItem(itemsToPack).Zip(Enumerable.Range(0, itemsToPack.Count), (k, v) => new { Key = k, Value = v }).ToDictionary(x => x.Key, x => x.Value); List <int> algorithm = new List <int> { 1 }; ContainerPackingResult packingResult = CromulentBisgetti.ContainerPacking.PackingService.Pack(container, itemsToPack, algorithm).FirstOrDefault(); AlgorithmPackingResult algorithmPackingResult = packingResult.AlgorithmPackingResults.FirstOrDefault(); List <Item> packedItems = algorithmPackingResult.PackedItems; List <Cuboid> packedCuboids = CuboidsFromItems(packedItems); List <Item> unpackedItems = algorithmPackingResult.UnpackedItems; List <Cuboid> unpackedCuboids = CuboidsFromItems(unpackedItems); List <int> packedIndices = IdFromItem(packedItems).Where(idDict.ContainsKey) .Select(x => idDict[x]) .ToList(); Dictionary <string, object> newOutput; newOutput = new Dictionary <string, object> { { packedItemsOutputPort3D, packedCuboids }, { indicesOutputPort3D, packedIndices }, { remainingItemsOutputPort3D, unpackedCuboids } }; return(newOutput); }
/// <summary> /// Initializes everything. /// </summary> private void Initialize(Container container, List <Item> items) { itemsToPack = new List <Item>(); itemsPackedInOrder = new List <Item>(); result = new ContainerPackingResult(); // The original code uses 1-based indexing everywhere. This fake entry is added to the beginning // of the list to make that possible. itemsToPack.Add(new Item(0, 0, 0, 0, 0)); layers = new List <Layer>(); itemsToPackCount = 0; foreach (Item item in items) { for (int i = 1; i <= item.Quantity; i++) { Item newItem = new Item(item.ID, item.Dim1, item.Dim2, item.Dim3, item.Quantity); itemsToPack.Add(newItem); } itemsToPackCount += item.Quantity; } itemsToPack.Add(new Item(0, 0, 0, 0, 0)); totalContainerVolume = container.Length * container.Height * container.Width; totalItemVolume = 0.0M; for (x = 1; x <= itemsToPackCount; x++) { totalItemVolume = totalItemVolume + itemsToPack[x].Volume; } scrapfirst = new ScrapPad(); scrapfirst.Pre = null; scrapfirst.Post = null; packingBest = false; hundredPercentPacked = false; quit = false; }
public static Dictionary <string, object> PackContainersWithGroupsContinuously(List <Miscellany.ContainerPacking.Entities.Container> containers, List <List <Miscellany.ContainerPacking.Entities.Item> > itemsToPack, int algorithm = 1, int minimumItems = 20) { //Select algorithm using integer List <int> algorithms = new List <int> { algorithm }; //Create CromulentBisgetti Items, retaining the nested structure List <List <Item> > items = new List <List <Item> >(); foreach (List <Miscellany.ContainerPacking.Entities.Item> l in itemsToPack) { List <Item> subList = new List <Item>(); foreach (Miscellany.ContainerPacking.Entities.Item i in l) { Item cbItem = ItemToCB(i); subList.Add(cbItem); } items.Add(subList); } //Reverse List to start from back so removals don't cause problems to indexing items.Reverse(); //Output lists List <List <Miscellany.ContainerPacking.Entities.Item> > itemsPacked = new List <List <Miscellany.ContainerPacking.Entities.Item> >(); bool IsCompletePack = false; List <int> PackTimeInMilliseconds = new List <int>(); int TotalPackTimeInMilliseconds = 0; List <double> PercentContainerVolumePacked = new List <double>(); List <double> PercentItemVolumePacked = new List <double>(); //Items Count int currentPackGroup = items.Count - 1; //Set to last index //Temporary group of Items to pack List <Item> tempItemsToPack = new List <Item>(); //Loop through the containers foreach (Miscellany.ContainerPacking.Entities.Container container in containers) { //No more pack groups to consider if (currentPackGroup < 0) { break; } //How many Items in temp list? int tempCount = tempItemsToPack.Count; //Ensure count matches the number of groups remaining currentPackGroup = items.Count - 1; if (tempCount >= minimumItems) { //There are more Items than the minimum or the same } else if (currentPackGroup < 0 || (currentPackGroup == 0 && items[currentPackGroup].Count == 0)) { //There are fewer Items than the minimum but there are no more Items to draw on if (tempCount == 0) { //No Items left so break the loop break; } } else { //There are fewer Items than the minimum but there are further Items to use int whileCount = 0; while (tempCount < minimumItems) { whileCount++; if (whileCount > 10) { continue; //temp } if (currentPackGroup < 0) { break; } if (items[currentPackGroup].Count == 0) { //No items left, move onto next group for next loop items.RemoveAt(currentPackGroup); currentPackGroup--; } else if (items[currentPackGroup].Count <= (minimumItems - tempCount)) { //Fewer Items are available than desired tempItemsToPack.AddRange(items[currentPackGroup]); //Add all Items items.RemoveAt(currentPackGroup); //Remove all items from the group currentPackGroup--; //Move to the next group index for the next loop tempCount = tempItemsToPack.Count; //Set the cou/* } else if (items[currentPackGroup].Count > (minimumItems - tempCount)) { //The desired number or greater are available int numberToTake = minimumItems - tempCount; if (numberToTake < 1) { continue; } for (int i = numberToTake - 1; i >= 0; i--) { //Take each required Item and remove from list tempItemsToPack.Add(items[currentPackGroup][i]); items[currentPackGroup].RemoveAt(i); } tempCount = tempItemsToPack.Count; //Report the current size of the temporary group } //tempCount++; } } //Create CromulentBisgetti Container Container con = ContainerToCB(container); List <Container> cons = new List <Container> { con }; //Get container packing result ContainerPackingResult containerPackingResult = CromulentBisgetti.ContainerPacking.PackingService.Pack(cons, tempItemsToPack, algorithms).FirstOrDefault(); //Get the single algorthim packing result from the container packing result AlgorithmPackingResult algorithmPackingResult = containerPackingResult.AlgorithmPackingResults.FirstOrDefault(); //Packed Items List <Miscellany.ContainerPacking.Entities.Item> itemsPackedPass = new List <Miscellany.ContainerPacking.Entities.Item>(); foreach (Item i in algorithmPackingResult.PackedItems) { Miscellany.ContainerPacking.Entities.Item mItem = ItemToMiscellany(i); itemsPackedPass.Add(mItem); } itemsPacked.Add(itemsPackedPass); IsCompletePack = algorithmPackingResult.IsCompletePack; if (IsCompletePack) //If all the items from that group are packed { tempItemsToPack.Clear(); //Clear all Items from temp list } else { tempItemsToPack = algorithmPackingResult.UnpackedItems; //items is set to unpacked items for next loop } PackTimeInMilliseconds.Add(Convert.ToInt32(algorithmPackingResult.PackTimeInMilliseconds)); TotalPackTimeInMilliseconds += Convert.ToInt32(algorithmPackingResult.PackTimeInMilliseconds); PercentContainerVolumePacked.Add(Miscellany.Math.Functions.ToDouble(algorithmPackingResult.PercentContainerVolumePacked)); PercentItemVolumePacked.Add(Miscellany.Math.Functions.ToDouble(algorithmPackingResult.PercentItemVolumePacked)); } //Convert CromulentBisgetti items to Miscellany Items for Unpacked Items List <Miscellany.ContainerPacking.Entities.Item> itemsUnpacked = new List <Miscellany.ContainerPacking.Entities.Item>(); foreach (List <Item> l in items) { foreach (Item i in l) { Miscellany.ContainerPacking.Entities.Item mItem = ItemToMiscellany(i); itemsUnpacked.Add(mItem); } } //Return values var d = new Dictionary <string, object>(); d.Add("packedItems", itemsPacked); d.Add("unpackedItems", itemsUnpacked); d.Add("isCompletePack", IsCompletePack); d.Add("packTimeInMilliseconds", PackTimeInMilliseconds); d.Add("totalPackTimeInMilliseconds", TotalPackTimeInMilliseconds); d.Add("percentContainerVolumePacked", PercentContainerVolumePacked); d.Add("percentItemVolumePacked", PercentItemVolumePacked); return(d); }
public static Dictionary <string, object> PackContainer(Miscellany.ContainerPacking.Entities.Container container, List <Miscellany.ContainerPacking.Entities.Item> itemsToPack, int algorithm = 1) { //Create CromulentBisgetti Container Container con = ContainerToCB(container); //Create CromulentBisgetti Items List <Item> items = new List <Item>(); foreach (Miscellany.ContainerPacking.Entities.Item i in itemsToPack) { Item cbItem = ItemToCB(i); items.Add(cbItem); } //Create list with single container List <Container> containers = new List <Container> { con }; //Select algorithm using integer List <int> algorithms = new List <int> { algorithm }; //Get container packing result ContainerPackingResult containerPackingResult = CromulentBisgetti.ContainerPacking.PackingService.Pack(containers, items, algorithms).FirstOrDefault(); //Get the single algorthim packing result from the container packing result AlgorithmPackingResult algorithmPackingResult = containerPackingResult.AlgorithmPackingResults.FirstOrDefault(); bool IsCompletePack = algorithmPackingResult.IsCompletePack; int PackTimeInMilliseconds = Convert.ToInt32(algorithmPackingResult.PackTimeInMilliseconds); //Max limit of int32 for milliseconds is596 hours double PercentContainerVolumePacked = Miscellany.Math.Functions.ToDouble(algorithmPackingResult.PercentContainerVolumePacked); double PercentItemVolumePacked = Miscellany.Math.Functions.ToDouble(algorithmPackingResult.PercentItemVolumePacked); //int BestFitOrientation = algorithmPackingResult.best //Convert CromulentBisgetti items to Miscellany Items //Packed Items List <Miscellany.ContainerPacking.Entities.Item> itemsPacked = new List <Miscellany.ContainerPacking.Entities.Item>(); foreach (Item i in algorithmPackingResult.PackedItems) { Miscellany.ContainerPacking.Entities.Item mItem = ItemToMiscellany(i); itemsPacked.Add(mItem); } //Unpacked Items List <Miscellany.ContainerPacking.Entities.Item> itemsUnpacked = new List <Miscellany.ContainerPacking.Entities.Item>(); foreach (Item i in algorithmPackingResult.UnpackedItems) { Miscellany.ContainerPacking.Entities.Item mItem = ItemToMiscellany(i); itemsUnpacked.Add(mItem); } //Return values var d = new Dictionary <string, object>(); d.Add("packedItems", itemsPacked); d.Add("unpackedItems", itemsUnpacked); d.Add("isCompletePack", IsCompletePack); d.Add("packTimeInMilliseconds", PackTimeInMilliseconds); d.Add("percentContainerVolumePacked", PercentContainerVolumePacked); d.Add("percentItemVolumePacked", PercentItemVolumePacked); d.Add("orientation", PercentItemVolumePacked); return(d); }
public static Dictionary <string, object> PackContainersWithGroups(List <Miscellany.ContainerPacking.Entities.Container> containers, List <List <Miscellany.ContainerPacking.Entities.Item> > itemsToPack, int algorithm = 1) { //Select algorithm using integer List <int> algorithms = new List <int> { algorithm }; //Create CromulentBisgetti Items List <List <Item> > items = new List <List <Item> >(); foreach (List <Miscellany.ContainerPacking.Entities.Item> l in itemsToPack) { List <Item> subList = new List <Item>(); foreach (Miscellany.ContainerPacking.Entities.Item i in l) { Item cbItem = ItemToCB(i); subList.Add(cbItem); } items.Add(subList); } //Reverse List to start from back so removals don't cause problems to indexing items.Reverse(); //Output lists List <List <Miscellany.ContainerPacking.Entities.Item> > itemsPacked = new List <List <Miscellany.ContainerPacking.Entities.Item> >(); bool IsCompletePack = false; List <int> PackTimeInMilliseconds = new List <int>(); int TotalPackTimeInMilliseconds = 0; List <double> PercentContainerVolumePacked = new List <double>(); List <double> PercentItemVolumePacked = new List <double>(); //Items Count int currentPackGroup = items.Count - 1; //Loop through the containers foreach (Miscellany.ContainerPacking.Entities.Container container in containers) { if (items.Count == 0) { break; } if (items[currentPackGroup].Count == 0) { items.RemoveAt(currentPackGroup); //Remove empty list currentPackGroup--; //move to next group } //Create list of items to pack List <Item> itemsToPackGroup = items[currentPackGroup]; //Create CromulentBisgetti Container Container con = ContainerToCB(container); List <Container> cons = new List <Container> { con }; //Get container packing result ContainerPackingResult containerPackingResult = CromulentBisgetti.ContainerPacking.PackingService.Pack(cons, itemsToPackGroup, algorithms).FirstOrDefault(); //Get the single algorthim packing result from the container packing result AlgorithmPackingResult algorithmPackingResult = containerPackingResult.AlgorithmPackingResults.FirstOrDefault(); //Packed Items List <Miscellany.ContainerPacking.Entities.Item> itemsPackedPass = new List <Miscellany.ContainerPacking.Entities.Item>(); foreach (Item i in algorithmPackingResult.PackedItems) { Miscellany.ContainerPacking.Entities.Item mItem = ItemToMiscellany(i); itemsPackedPass.Add(mItem); } itemsPacked.Add(itemsPackedPass); IsCompletePack = algorithmPackingResult.IsCompletePack; if (IsCompletePack) //If all the items from that group are packed { items.RemoveAt(currentPackGroup); //Remove group from list to pack currentPackGroup--; //Move on to the next group } else { items[currentPackGroup] = algorithmPackingResult.UnpackedItems; //items is set to unpacked items for next loop } PackTimeInMilliseconds.Add(Convert.ToInt32(algorithmPackingResult.PackTimeInMilliseconds)); TotalPackTimeInMilliseconds += Convert.ToInt32(algorithmPackingResult.PackTimeInMilliseconds); PercentContainerVolumePacked.Add(Miscellany.Math.Functions.ToDouble(algorithmPackingResult.PercentContainerVolumePacked)); PercentItemVolumePacked.Add(Miscellany.Math.Functions.ToDouble(algorithmPackingResult.PercentItemVolumePacked)); if (items.Count == 0) //No more groups to pack { break; } } //Convert CromulentBisgetti items to Miscellany Items for Unpacked Items List <Miscellany.ContainerPacking.Entities.Item> itemsUnpacked = new List <Miscellany.ContainerPacking.Entities.Item>(); foreach (List <Item> l in items) { foreach (Item i in l) { Miscellany.ContainerPacking.Entities.Item mItem = ItemToMiscellany(i); itemsUnpacked.Add(mItem); } } //Return values var d = new Dictionary <string, object>(); d.Add("packedItems", itemsPacked); d.Add("unpackedItems", itemsUnpacked); d.Add("isCompletePack", IsCompletePack); d.Add("packTimeInMilliseconds", PackTimeInMilliseconds); d.Add("totalPackTimeInMilliseconds", TotalPackTimeInMilliseconds); d.Add("percentContainerVolumePacked", PercentContainerVolumePacked); d.Add("percentItemVolumePacked", PercentItemVolumePacked); return(d); }
public static Dictionary <string, object> PackContainers(List <Miscellany.ContainerPacking.Entities.Container> containers, List <Miscellany.ContainerPacking.Entities.Item> itemsToPack, int algorithm = 1) { //Select algorithm using integer List <int> algorithms = new List <int> { algorithm }; //Create CromulentBisgetti Items List <Item> items = new List <Item>(); foreach (Miscellany.ContainerPacking.Entities.Item i in itemsToPack) { Item cbItem = ItemToCB(i); items.Add(cbItem); } //Output lists List <List <Miscellany.ContainerPacking.Entities.Item> > itemsPacked = new List <List <Miscellany.ContainerPacking.Entities.Item> >(); bool IsCompletePack = false; List <int> PackTimeInMilliseconds = new List <int>(); int TotalPackTimeInMilliseconds = 0; List <double> PercentContainerVolumePacked = new List <double>(); List <double> PercentItemVolumePacked = new List <double>(); //Loop through the containers foreach (Miscellany.ContainerPacking.Entities.Container container in containers) { //Create CromulentBisgetti Container Container con = ContainerToCB(container); List <Container> cons = new List <Container> { con }; //Get container packing result ContainerPackingResult containerPackingResult = CromulentBisgetti.ContainerPacking.PackingService.Pack(cons, items, algorithms).FirstOrDefault(); //Get the single algorthim packing result from the container packing result AlgorithmPackingResult algorithmPackingResult = containerPackingResult.AlgorithmPackingResults.FirstOrDefault(); //Packed Items List <Miscellany.ContainerPacking.Entities.Item> itemsPackedPass = new List <Miscellany.ContainerPacking.Entities.Item>(); foreach (Item i in algorithmPackingResult.PackedItems) { Miscellany.ContainerPacking.Entities.Item mItem = ItemToMiscellany(i); itemsPackedPass.Add(mItem); } itemsPacked.Add(itemsPackedPass); items = algorithmPackingResult.UnpackedItems; //items is set to unpacked items for next loop IsCompletePack = algorithmPackingResult.IsCompletePack; PackTimeInMilliseconds.Add(Convert.ToInt32(algorithmPackingResult.PackTimeInMilliseconds)); TotalPackTimeInMilliseconds += Convert.ToInt32(algorithmPackingResult.PackTimeInMilliseconds); PercentContainerVolumePacked.Add(Miscellany.Math.Functions.ToDouble(algorithmPackingResult.PercentContainerVolumePacked)); PercentItemVolumePacked.Add(Miscellany.Math.Functions.ToDouble(algorithmPackingResult.PercentItemVolumePacked)); if (algorithmPackingResult.IsCompletePack == true) { break; } } //Convert CromulentBisgetti items to Miscellany Items for Unpacked Items List <Miscellany.ContainerPacking.Entities.Item> itemsUnpacked = new List <Miscellany.ContainerPacking.Entities.Item>(); foreach (Item i in items) { Miscellany.ContainerPacking.Entities.Item mItem = ItemToMiscellany(i); itemsUnpacked.Add(mItem); } //Return values var d = new Dictionary <string, object>(); d.Add("packedItems", itemsPacked); d.Add("unpackedItems", itemsUnpacked); d.Add("isCompletePack", IsCompletePack); d.Add("packTimeInMilliseconds", PackTimeInMilliseconds); d.Add("totalPackTimeInMilliseconds", TotalPackTimeInMilliseconds); d.Add("percentContainerVolumePacked", PercentContainerVolumePacked); d.Add("percentItemVolumePacked", PercentItemVolumePacked); return(d); }
/// <summary> /// Attempts to pack the specified containers with the specified items using the specified algorithms. /// </summary> /// <param name="containers">The list of containers to pack.</param> /// <param name="itemsToPack">The items to pack.</param> /// <param name="algorithmTypeIDs">The list of algorithm type IDs to use for packing.</param> /// <returns>A container packing result with lists of the packed and unpacked items.</returns> public static List <ContainerPackingResult> Pack(List <Container> containers, List <Item> itemsToPack, List <int> algorithmTypeIDs) { Object sync = new Object { }; List <ContainerPackingResult> result = new List <ContainerPackingResult>(); Parallel.ForEach(containers, container => { ContainerPackingResult containerPackingResult = new ContainerPackingResult(); containerPackingResult.ContainerID = container.ID; Parallel.ForEach(algorithmTypeIDs, algorithmTypeID => { var jsonDefinition = new { Height = new Decimal(), Length = new Decimal(), Volume = new Decimal(), Width = new Decimal(), Items = new List <Item>() }; var onlineContainerJsonSource = "{\"Height\":9.0,\"Length\":15.0,\"Volume\":1755.0,\"Width\":13.0,\"Items\":[{\"ID\":0,\"PesoMaximo\":0,\"Peso\":0,\"EmpilhamentoDisponivel\":true,\"ItensEmpilhados\":[],\"TipoDeItemId\":1,\"IsPacked\":true,\"Dim1\":3.0,\"Dim2\":3.0,\"Dim3\":3.0,\"CoordX\":0.0,\"CoordY\":0.0,\"CoordZ\":0.0,\"PackDimX\":3.0,\"PackDimY\":3.0,\"PackDimZ\":3.0,\"Volume\":27.000},{\"ID\":0,\"PesoMaximo\":0,\"Peso\":0,\"EmpilhamentoDisponivel\":true,\"ItensEmpilhados\":[],\"TipoDeItemId\":1,\"IsPacked\":true,\"Dim1\":3.0,\"Dim2\":3.0,\"Dim3\":3.0,\"CoordX\":3.0,\"CoordY\":0.0,\"CoordZ\":0.0,\"PackDimX\":3.0,\"PackDimY\":3.0,\"PackDimZ\":3.0,\"Volume\":27.000},{\"ID\":0,\"PesoMaximo\":0,\"Peso\":0,\"EmpilhamentoDisponivel\":true,\"ItensEmpilhados\":[],\"TipoDeItemId\":1,\"IsPacked\":true,\"Dim1\":3.0,\"Dim2\":3.0,\"Dim3\":3.0,\"CoordX\":6.0,\"CoordY\":0.0,\"CoordZ\":0.0,\"PackDimX\":3.0,\"PackDimY\":3.0,\"PackDimZ\":3.0,\"Volume\":27.000},{\"ID\":0,\"PesoMaximo\":0,\"Peso\":0,\"EmpilhamentoDisponivel\":true,\"ItensEmpilhados\":[],\"TipoDeItemId\":2,\"IsPacked\":true,\"Dim1\":2.0,\"Dim2\":2.0,\"Dim3\":2.0,\"CoordX\":9.0,\"CoordY\":0.0,\"CoordZ\":0.0,\"PackDimX\":2.0,\"PackDimY\":2.0,\"PackDimZ\":2.0,\"Volume\":8.0},{\"ID\":0,\"PesoMaximo\":0,\"Peso\":0,\"EmpilhamentoDisponivel\":true,\"ItensEmpilhados\":[],\"TipoDeItemId\":2,\"IsPacked\":true,\"Dim1\":2.0,\"Dim2\":2.0,\"Dim3\":2.0,\"CoordX\":11.0,\"CoordY\":0.0,\"CoordZ\":0.0,\"PackDimX\":2.0,\"PackDimY\":2.0,\"PackDimZ\":2.0,\"Volume\":8.0},{\"ID\":0,\"PesoMaximo\":0,\"Peso\":0,\"EmpilhamentoDisponivel\":true,\"ItensEmpilhados\":[],\"TipoDeItemId\":2,\"IsPacked\":true,\"Dim1\":2.0,\"Dim2\":2.0,\"Dim3\":2.0,\"CoordX\":13.0,\"CoordY\":0.0,\"CoordZ\":0.0,\"PackDimX\":2.0,\"PackDimY\":2.0,\"PackDimZ\":2.0,\"Volume\":8.0},{\"ID\":0,\"PesoMaximo\":0,\"Peso\":0,\"EmpilhamentoDisponivel\":true,\"ItensEmpilhados\":[],\"TipoDeItemId\":2,\"IsPacked\":true,\"Dim1\":2.0,\"Dim2\":2.0,\"Dim3\":2.0,\"CoordX\":9.0,\"CoordY\":0.0,\"CoordZ\":2.0,\"PackDimX\":2.0,\"PackDimY\":2.0,\"PackDimZ\":2.0,\"Volume\":8.0},{\"ID\":0,\"PesoMaximo\":0,\"Peso\":0,\"EmpilhamentoDisponivel\":true,\"ItensEmpilhados\":[],\"TipoDeItemId\":2,\"IsPacked\":true,\"Dim1\":2.0,\"Dim2\":2.0,\"Dim3\":2.0,\"CoordX\":11.0,\"CoordY\":0.0,\"CoordZ\":2.0,\"PackDimX\":2.0,\"PackDimY\":2.0,\"PackDimZ\":2.0,\"Volume\":8.0},{\"ID\":0,\"PesoMaximo\":0,\"Peso\":0,\"EmpilhamentoDisponivel\":true,\"ItensEmpilhados\":[],\"TipoDeItemId\":2,\"IsPacked\":true,\"Dim1\":2.0,\"Dim2\":2.0,\"Dim3\":2.0,\"CoordX\":13.0,\"CoordY\":0.0,\"CoordZ\":2.0,\"PackDimX\":2.0,\"PackDimY\":2.0,\"PackDimZ\":2.0,\"Volume\":8.0},{\"ID\":0,\"PesoMaximo\":0,\"Peso\":0,\"EmpilhamentoDisponivel\":true,\"ItensEmpilhados\":[],\"TipoDeItemId\":2,\"IsPacked\":true,\"Dim1\":2.0,\"Dim2\":2.0,\"Dim3\":2.0,\"CoordX\":7.0,\"CoordY\":0.0,\"CoordZ\":3.0,\"PackDimX\":2.0,\"PackDimY\":2.0,\"PackDimZ\":2.0,\"Volume\":8.0},{\"ID\":0,\"PesoMaximo\":0,\"Peso\":0,\"EmpilhamentoDisponivel\":true,\"ItensEmpilhados\":[],\"TipoDeItemId\":2,\"IsPacked\":true,\"Dim1\":2.0,\"Dim2\":2.0,\"Dim3\":2.0,\"CoordX\":5.0,\"CoordY\":0.0,\"CoordZ\":3.0,\"PackDimX\":2.0,\"PackDimY\":2.0,\"PackDimZ\":2.0,\"Volume\":8.0}]}"; var onlineContainerSource = JsonConvert.DeserializeAnonymousType(onlineContainerJsonSource, jsonDefinition); // Until I rewrite the algorithm with no side effects, we need to clone the item list // so the parallel updates don't interfere with each other. List <Item> items = new List <Item>(); onlineContainerSource.Items.ForEach(item => { item.Quantity = 1; //item.IsPacked = false; items.Add(item); item.ItensEmpilhados.ForEach(itemEmpilhado => items.Add(itemEmpilhado)); }); itemsToPack.ForEach(item => { for (int i = 0; i < item.Quantity; i++) { items.Add(new Item(item.ID, item.Dim1, item.Dim2, item.Dim3, 1, item.TipoDeItemId)); } }); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); //AlgorithmPackingResult algorithmResult = algorithm.Run(container, items); AlgorithmPackingResult algorithmResult = new OnlineContainerPacking().OnlineRun(container, items); stopwatch.Stop(); algorithmResult.PackTimeInMilliseconds = stopwatch.ElapsedMilliseconds; decimal containerVolume = container.Length * container.Width * container.Height; decimal itemVolumePacked = algorithmResult.PackedItems.Sum(i => i.Volume); decimal itemVolumeUnpacked = algorithmResult.UnpackedItems.Sum(i => i.Volume); algorithmResult.PercentContainerVolumePacked = Math.Round(itemVolumePacked / containerVolume * 100, 2); algorithmResult.PercentItemVolumePacked = Math.Round(itemVolumePacked / (itemVolumePacked + itemVolumeUnpacked) * 100, 2); var onlineContainer = new { Height = container.Height, Length = container.Length, Volume = container.Volume, Width = container.Width, Items = algorithmResult.PackedItems }; var onlineContainerJson = JsonConvert.SerializeObject(onlineContainer); lock (sync) { containerPackingResult.AlgorithmPackingResults.Add(algorithmResult); } }); containerPackingResult.AlgorithmPackingResults = containerPackingResult.AlgorithmPackingResults.OrderBy(r => r.AlgorithmName).ToList(); lock (sync) { result.Add(containerPackingResult); } }); return(result); }