private void Insert( Cuboid cuboid, FreeCuboidChoiceHeuristic cuboidChoice, GuillotineSplitHeuristic splitMethod) { // Check is overweight if (cuboid.Weight + _usedCuboids.Sum(x => x.Weight) > _parameter.BinWeight) { return; } // Find where to put the new cuboid var freeNodeIndex = 0; FindPositionForNewNode(cuboid, cuboidChoice, out freeNodeIndex); // Abort if we didn't have enough space in the bin if (!cuboid.IsPlaced) { return; } // Remove the space that was just consumed by the new cuboid if (freeNodeIndex < 0) { throw new ArithmeticException("freeNodeIndex < 0"); } SplitFreeCuboidByHeuristic(_freeCuboids[freeNodeIndex], cuboid, splitMethod); _freeCuboids.RemoveAt(freeNodeIndex); // Remember the new used cuboid _usedCuboids.Add(cuboid); }
public BinPackGuillotineAlgorithm( BinPackParameter parameter, FreeCuboidChoiceHeuristic cuboidChoice, GuillotineSplitHeuristic splitMethod) { _parameter = parameter; _cuboidChoice = cuboidChoice; _splitMethod = splitMethod; _usedCuboids = new List <Cuboid>(); _freeCuboids = new List <Cuboid>(); AddFreeCuboid(new Cuboid(parameter.BinWidth, parameter.BinHeight, parameter.BinDepth)); }
private static decimal ScoreByHeuristic( Cuboid cuboid, Cuboid freeCuboid, FreeCuboidChoiceHeuristic cuboidChoice) { switch (cuboidChoice) { case FreeCuboidChoiceHeuristic.CuboidMinHeight: return(freeCuboid.Y + cuboid.Height); default: throw new NotSupportedException($"cuboid choice is unsupported: {cuboidChoice}"); } }
public BinPackGuillotineAlgorithm( decimal binWidth, decimal binHeight, decimal binDepth, FreeCuboidChoiceHeuristic cuboidChoice, GuillotineSplitHeuristic splitMethod) { _binWidth = binWidth; _binHeight = binHeight; _binDepth = binDepth; _cuboidChoice = cuboidChoice; _splitMethod = splitMethod; _usedCuboids = new List <Cuboid>(); _freeCuboids = new List <Cuboid>(); AddFreeCuboid(new Cuboid(_binWidth, _binHeight, _binDepth)); }
private void FindPositionForNewNode( Cuboid cuboid, FreeCuboidChoiceHeuristic cuboidChoice, out int freeCuboidIndex) { var width = cuboid.Width; var height = cuboid.Height; var depth = cuboid.Depth; var bestScore = decimal.MaxValue; freeCuboidIndex = -1; // Try each free cuboid to find the best one for placement a given cuboid. // Rotate a cuboid in every possible way and find which choice is the best. for (int index = 0; index < _freeCuboids.Count; ++index) { var freeCuboid = _freeCuboids[index]; // Width x Height x Depth (no rotate) if (width <= freeCuboid.Width && height <= freeCuboid.Height && depth <= freeCuboid.Depth) { var score = ScoreByHeuristic(cuboid, freeCuboid, cuboidChoice); if (score < bestScore && cuboid.AllowOrientZ) { cuboid.IsPlaced = true; cuboid.X = freeCuboid.X; cuboid.Y = freeCuboid.Y; cuboid.Z = freeCuboid.Z; cuboid.Width = width; cuboid.Height = height; cuboid.Depth = depth; bestScore = score; freeCuboidIndex = index; } } // Width x Depth x Height (rotate vertically) if (width <= freeCuboid.Width && depth <= freeCuboid.Height && height <= freeCuboid.Depth && _parameter.AllowRotateVertically) { var score = ScoreByHeuristic(cuboid, freeCuboid, cuboidChoice); if (score < bestScore && cuboid.AllowOrientY) { cuboid.IsPlaced = true; cuboid.X = freeCuboid.X; cuboid.Y = freeCuboid.Y; cuboid.Z = freeCuboid.Z; cuboid.Width = width; cuboid.Height = depth; cuboid.Depth = height; bestScore = score; freeCuboidIndex = index; } } // Depth x Height x Width (rotate horizontally) if (depth <= freeCuboid.Width && height <= freeCuboid.Height && width <= freeCuboid.Depth) { var score = ScoreByHeuristic(cuboid, freeCuboid, cuboidChoice); if (score < bestScore && cuboid.AllowOrientX) { cuboid.IsPlaced = true; cuboid.X = freeCuboid.X; cuboid.Y = freeCuboid.Y; cuboid.Z = freeCuboid.Z; cuboid.Width = depth; cuboid.Height = height; cuboid.Depth = width; bestScore = score; freeCuboidIndex = index; } } // Depth x Width x Height (rotate horizontally and vertically) if (depth <= freeCuboid.Width && width <= freeCuboid.Height && height <= freeCuboid.Depth && _parameter.AllowRotateVertically) { var score = ScoreByHeuristic(cuboid, freeCuboid, cuboidChoice); if (score < bestScore && cuboid.AllowOrientY) { cuboid.IsPlaced = true; cuboid.X = freeCuboid.X; cuboid.Y = freeCuboid.Y; cuboid.Z = freeCuboid.Z; cuboid.Width = depth; cuboid.Height = width; cuboid.Depth = height; bestScore = score; freeCuboidIndex = index; } } // Height x Width x Depth (rotate vertically) if (height <= freeCuboid.Width && width <= freeCuboid.Height && depth <= freeCuboid.Depth && _parameter.AllowRotateVertically) { var score = ScoreByHeuristic(cuboid, freeCuboid, cuboidChoice); if (score < bestScore && cuboid.AllowOrientZ) { cuboid.IsPlaced = true; cuboid.X = freeCuboid.X; cuboid.Y = freeCuboid.Y; cuboid.Z = freeCuboid.Z; cuboid.Width = height; cuboid.Height = width; cuboid.Depth = depth; bestScore = score; freeCuboidIndex = index; } } // Height x Depth x Width (rotate horizontally and vertically) if (height <= freeCuboid.Width && depth <= freeCuboid.Height && width <= freeCuboid.Depth && _parameter.AllowRotateVertically) { var score = ScoreByHeuristic(cuboid, freeCuboid, cuboidChoice); if (score < bestScore && cuboid.AllowOrientX) { cuboid.IsPlaced = true; cuboid.X = freeCuboid.X; cuboid.Y = freeCuboid.Y; cuboid.Z = freeCuboid.Z; cuboid.Width = height; cuboid.Height = depth; cuboid.Depth = width; bestScore = score; freeCuboidIndex = index; } } } }