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); }
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 ModelFootprint Clone() { ModelFootprint clonedFootprint = new ModelFootprint(this.SizeX, this.SizeY, this.Color); clonedFootprint.Model = this.Model; clonedFootprint.PositionX = this.PositionX; clonedFootprint.PositionY = this.PositionY; clonedFootprint.RequestedCloneCount = this.RequestedCloneCount; clonedFootprint.RotateModel = this.RotateModel; clonedFootprint.CloneCount = this.CloneCount; return(clonedFootprint); }
public static PackedItem Create(ModelFootprint modelFootprint) { PackedItem packedItem = new PackedItem() { ModelFootprint = modelFootprint, SizeX = modelFootprint.SizeX, SizeY = modelFootprint.SizeY, RotateModel = modelFootprint.RotateModel, }; return(packedItem); }
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); } } }
/// <summary> /// Create a model footprint for a STL model /// </summary> /// <param name="model"></param> /// <returns></returns> public static ModelFootprint FromModel(STLModel3D model) { ModelFootprint modelFootprint = new ModelFootprint(); modelFootprint.Model = model; if (model.SupportBasement) { if (model.SupportBasementStructure != null) { model.SupportBasementStructure.UpdateBoundries(); } } modelFootprint.SizeX = Math.Abs(model.FootprintRightPoint - model.FootprintLeftPoint); modelFootprint.SizeY = Math.Abs(model.FootprintBackPoint - model.FootprintFrontPoint); modelFootprint.Color = model.Color; return(modelFootprint); }
public static void DetermineOptimalModelOrientation(this ModelFootprint modelFootprint, Rectangle container, float clearance) { // Optimal orientation is the orientation that allows the most amount of clones of the model in total on the buildplate, with clearance // TODO: there may be a better way to calculate with clearance since the clearance is not needed on the edges of the buildplatform // Normal orientation int normalOrientationRows = DetermineMaxRepetitions(container.SizeY, modelFootprint.SizeY + 0.0f * clearance); int normalOrientationColumns = DetermineMaxRepetitions(container.SizeX, modelFootprint.SizeX + 0.0f * clearance); int normalOrientationCloneCount = normalOrientationRows * normalOrientationColumns; // Rotated 90 degrees int rotatedOrientationRows = DetermineMaxRepetitions(container.SizeY, modelFootprint.SizeX + 0.0f * clearance); int rotatedOrientationColumns = DetermineMaxRepetitions(container.SizeX, modelFootprint.SizeY + 0.0f * clearance); int rotatedOrientationCloneCount = rotatedOrientationRows * rotatedOrientationColumns; bool rotateModel = rotatedOrientationCloneCount > normalOrientationCloneCount; //The model may already be rotated and SizeX and SizeY may already return the rotated value, so only apply rotation by inverting current value if needed if (rotateModel) { modelFootprint.RotateModel = !modelFootprint.RotateModel; } }