public PackingSolutions CreateSolutions(PackModelsRequest packModelsRequest) { PackingSolutions packingSolutions = new PackingSolutions(); Stopwatch stopwatch = Stopwatch.StartNew(); int theoreticalMaxCloneCount = packModelsRequest.DetermineMaximumCloneCountBasedOnSurfaceArea(); int maxCloneCount = theoreticalMaxCloneCount; if (packModelsRequest.RequestedCloneCount.HasValue && packModelsRequest.RequestedCloneCount.Value > 0) { maxCloneCount = Math.Min(packModelsRequest.RequestedCloneCount.Value, theoreticalMaxCloneCount); } for (int cloneCount = maxCloneCount; cloneCount > 0; cloneCount--) { PackingSolution solution = CreateSolution(packModelsRequest, cloneCount); packingSolutions.Solutions.Add(solution); if (solution.CloneCount == maxCloneCount || solution.CloneCount >= cloneCount || !solution.FootprintCloneCount.Any(f => f != solution.CloneCount)) { break; } } stopwatch.Stop(); packingSolutions.TotalDurationMs = stopwatch.ElapsedMilliseconds; return(packingSolutions); }
public static PackModelsRequest CreatePackModelsRequest(int?requestedCloneCount) { PackModelsRequest packModelsRequest = new PackModelsRequest(); foreach (var object3D in ObjectView.Objects3D) { if (object3D is STLModel3D && !(object3D is GroundPane)) { var stlModel = object3D as STLModel3D; var modelFootprint = ModelFootprint.FromModel(stlModel); packModelsRequest.ModelFootprints.Add(modelFootprint); } } var selectedPrinter = PrintJobManager.SelectedPrinter; var printerGroundPaneDimensionX = (selectedPrinter.ProjectorResolutionX / 10) * selectedPrinter.TrapeziumCorrectionFactorX; var printerGroundPaneDimensionY = (selectedPrinter.ProjectorResolutionY / 10) * selectedPrinter.TrapeziumCorrectionFactorY; packModelsRequest.BuildPlatform = new Core.Engines.PackingEngine.Rectangle() { SizeX = printerGroundPaneDimensionX, SizeY = printerGroundPaneDimensionY }; packModelsRequest.Clearance = UserProfileManager.UserProfile.Settings_Models_ClearanceBetweenClones; packModelsRequest.RequestedCloneCount = requestedCloneCount; return(packModelsRequest); }
/// <summary> /// Run all packingstrategies to get their solutions /// </summary> /// <param name="packModelsRequest"></param> /// <param name="allPackingSolutions"></param> /// <param name="stopwatch"></param> private void getSolutions(PackModelsRequest packModelsRequest, PackingSolutions allPackingSolutions, Stopwatch stopwatch) { foreach (IPackingStrategy packingStrategy in PackingStrategies) { getSolutions(packModelsRequest, allPackingSolutions, packingStrategy); } LoggingManager.WriteToLog("PackingEngine", "Get solutions for strategies", stopwatch.ElapsedMilliseconds + "ms"); }
public PackingSolution CreateSolution(PackModelsRequest packModelsRequest, int maxCloneCount) { PackingSolution packingSolution = new PackingSolution(); Stopwatch stopwatch = Stopwatch.StartNew(); // Get model footprints based on area size packingSolution.Footprints = packModelsRequest.ModelFootprints.OrderByDescending(footprint => footprint.Area).Select(f => f.Clone()).ToList(); packingSolution.Footprints.ForEach(f => f.CloneCount = 0); packingSolution.FootprintCloneCount = new int[packingSolution.Footprints.Count]; bool buildPlatformFull = false; Container buildPlatformContainer = Container.Create(packModelsRequest.BuildPlatform); Container remainingBuildPlatformArea = buildPlatformContainer; while (!buildPlatformFull) { var firstModelFootprintToPack = GetBestFitModelFootprint(packModelsRequest, maxCloneCount, packingSolution.Footprints, packingSolution.FootprintCloneCount, remainingBuildPlatformArea); if (firstModelFootprintToPack != null) { // Create shelf Container shelf = new Container() { PositionX = remainingBuildPlatformArea.PositionX, PositionY = remainingBuildPlatformArea.PositionY, SizeX = firstModelFootprintToPack.SizeX, SizeY = packModelsRequest.BuildPlatform.SizeY }; buildPlatformContainer.AddChild(shelf); FillContainer(shelf, packModelsRequest, maxCloneCount, packingSolution.Footprints, packingSolution.FootprintCloneCount); float newPositionX = shelf.PositionX + shelf.SizeX + packModelsRequest.Clearance; remainingBuildPlatformArea = new Container() { PositionX = newPositionX, SizeX = packModelsRequest.BuildPlatform.SizeX - newPositionX, PositionY = 0, SizeY = packModelsRequest.BuildPlatform.SizeY }; } ModelFootprint modelFootprint = GetBestFitModelFootprint(packModelsRequest, maxCloneCount, packingSolution.Footprints, packingSolution.FootprintCloneCount, remainingBuildPlatformArea); buildPlatformFull = modelFootprint == null; } var allContainers = buildPlatformContainer.GetAll(); var allItems = allContainers.SelectMany(c => c.Items); packingSolution.PackedItems.AddRange(allItems); packingSolution.UnusedSpaces.AddRange(allContainers.Where(s => !s.Items.Any())); packingSolution.UnusedSpaces.Add(remainingBuildPlatformArea); packingSolution.CloneCount = packingSolution.FootprintCloneCount.Min(); stopwatch.Stop(); packingSolution.DurationMs = stopwatch.ElapsedMilliseconds; return(packingSolution); }
public static PackingSolutions CalculatePackingSolutions(PackModelsRequest packModelsRequest) { PackingEngine packingEngine = new PackingEngine(); packingEngine.PackingStrategies.Add(new ShelfPackLargestFirstPackingStrategy()); var solutions = packingEngine.AnalyzeSolutions(packModelsRequest); return(solutions); }
private static void getSolutions(PackModelsRequest packModelsRequest, PackingSolutions allPackingSolutions, IPackingStrategy packingStrategy) { try { PackingSolutions packingSolutions = packingStrategy.CreateSolutions(packModelsRequest); allPackingSolutions.Solutions.AddRange(packingSolutions.Solutions); } catch (Exception ex) { LoggingManager.WriteToLog("PackingEngine", "Get solutions for strategy - " + packingStrategy.GetType().Name, ex); } }
private void determineBestSolution(PackModelsRequest packModelsRequest, PackingSolutions allPackingSolutions, Stopwatch stopwatch) { // TODO: implement determine best solution based on number of clones and biggest unused area left var packingSolutionsWithRequestedAmountOfClones = new List <PackingSolution>(); if (packModelsRequest.PackingType == TypeOfPacking.DefinedNumbersOfClones) { foreach (var packageSolution in allPackingSolutions.Solutions) { var allModelRequestsAreValid = true; foreach (var modelRequest in packModelsRequest.ModelFootprints) { if (modelRequest.RequestedCloneCount < 5000) { var amountOfPackedModels = packageSolution.PackedItems.Count(s => s.ModelFootprint.Model == modelRequest.Model); if (modelRequest.RequestedCloneCount >= amountOfPackedModels && amountOfPackedModels >= modelRequest.RequestedCloneCount - 1) { } else { allModelRequestsAreValid = false; break; } } } if (allModelRequestsAreValid) { packingSolutionsWithRequestedAmountOfClones.Add(packageSolution); } } if (packingSolutionsWithRequestedAmountOfClones.Count > 0) { //best solution is where there are as much as possible models allPackingSolutions.BestSolution = packingSolutionsWithRequestedAmountOfClones.OrderByDescending(s => s.CloneCount).FirstOrDefault(); } else { allPackingSolutions.BestSolution = null; } } else { allPackingSolutions.BestSolution = allPackingSolutions.Solutions.OrderByDescending(s => s.CloneCount).FirstOrDefault(); } LoggingManager.WriteToLog("PackingEngine", "Determine best solution", stopwatch.ElapsedMilliseconds + "ms"); }
private static ModelFootprint GetBestFitModelFootprint(PackModelsRequest packModelsRequest, int maxCloneCount, List <ModelFootprint> orderedModelFootprints, int[] modelsCloneCount, Container containerArea) { // Check best orientation for model footprints for this container orderedModelFootprints.DetermineOptimalModelsOrientation(containerArea, packModelsRequest.Clearance); // Get the first biggest model footprint which still needs to be packed var modelFootprintToPack = orderedModelFootprints.FirstOrDefault(footprint => modelsCloneCount[orderedModelFootprints.IndexOf(footprint)] < maxCloneCount && modelsCloneCount[orderedModelFootprints.IndexOf(footprint)] < footprint.RequestedCloneCount && containerArea.Fits(footprint)); // If all models are packed with the max clone count to get an equal amount of models, get the next model that fits to fill up the space if (modelFootprintToPack == null) { modelFootprintToPack = orderedModelFootprints.FirstOrDefault(footprint => modelsCloneCount[orderedModelFootprints.IndexOf(footprint)] < footprint.RequestedCloneCount && containerArea.Fits(footprint)); } return(modelFootprintToPack); }
public PackingSolutions AnalyzeSolutions(PackModelsRequest packModelsRequest) { PackingSolutions allPackingSolutions = new PackingSolutions(); Stopwatch stopwatch = Stopwatch.StartNew(); getSolutions(packModelsRequest, allPackingSolutions, stopwatch); determineBestSolution(packModelsRequest, allPackingSolutions, stopwatch); stopwatch.Stop(); allPackingSolutions.TotalDurationMs = stopwatch.ElapsedMilliseconds; LoggingManager.WriteToLog("PackingEngine", "Completed in", stopwatch.ElapsedMilliseconds + "ms"); return(allPackingSolutions); }
private static void FillContainer(Container container, PackModelsRequest packModelsRequest, int maxCloneCount, List <ModelFootprint> orderedModelFootprints, int[] modelsCloneCount) { ModelFootprint modelFootprint = GetBestFitModelFootprint(packModelsRequest, maxCloneCount, orderedModelFootprints, modelsCloneCount, container); if (modelFootprint != null) { int modelIndex = orderedModelFootprints.IndexOf(modelFootprint); modelsCloneCount[modelIndex]++; modelFootprint.CloneCount++; PackedItem item = PackedItem.Create(modelFootprint); item.CloneNumber = modelsCloneCount[modelIndex]; item.ClearanceY = packModelsRequest.Clearance; item.ClearanceX = packModelsRequest.Clearance; item.PositionX = container.PositionX; item.PositionY = container.PositionY; container.Items.Add(item); Container spaceNextToModel = new Container() { SizeX = container.SizeX - item.TotalSizeX, SizeY = item.ModelFootprint.SizeY, PositionX = item.PositionX + item.TotalSizeX, PositionY = item.PositionY }; if (spaceNextToModel.SizeX > packModelsRequest.Clearance) { container.AddChild(spaceNextToModel); FillContainer(spaceNextToModel, packModelsRequest, maxCloneCount, orderedModelFootprints, modelsCloneCount); } Container remainingSpaceAboveModel = new Container() { SizeX = container.SizeX, SizeY = container.SizeY - item.TotalSizeY, PositionX = container.PositionX, PositionY = container.PositionY + item.TotalSizeY }; if (remainingSpaceAboveModel.SizeY > packModelsRequest.Clearance) { container.AddChild(remainingSpaceAboveModel); FillContainer(remainingSpaceAboveModel, packModelsRequest, maxCloneCount, orderedModelFootprints, modelsCloneCount); } } }