/// <summary> /// Find best freerectangle and place next rectangle /// </summary> /// <param name="item"></param> /// <param name="placementMethod"></param> /// <param name="idx"></param> private static void PlaceItem( Rectangle item, PlacementMethods placementMethod, int idx) { FreeRectangle f = BestFreeRect(item, placementMethod); if (f != null) { if (f.rotate) { item = Rotate(item); } CoordinateSystem newCS = CoordinateSystem.ByOrigin(f.xPos, f.yPos); CoordinateSystem originCS = CoordinateSystem.ByOrigin(item.StartPoint.X - item.Width, item.StartPoint.Y); Rectangle placedRect = (Rectangle)item.Transform(originCS, newCS); packedRectangles.Add(placedRect); SplitFreeRectangle(f, placedRect); packedIndices.Add(idx); freeRectangles.Remove(f); List <double> itemBounds = RectBounds(placedRect); RemoveOverlaps(itemBounds); // Dispose Dynamo geometry newCS.Dispose(); originCS.Dispose(); } else { remainRectangles.Add(item); } }
public static Dictionary <string, object> Pack2D( List <Rectangle> rects, Rectangle bin, PlacementMethods placementMethod) { freeRectangles = new List <FreeRectangle>(); packedRectangles = new List <Rectangle>(); remainRectangles = new List <Rectangle>(); packedIndices = new List <int>(); // Initialize freeRectangles freeRectangles.Add(new FreeRectangle { width = bin.Width, height = bin.Height, xPos = bin.StartPoint.X - bin.Width, yPos = bin.StartPoint.Y }); int idx = 0; foreach (var rect in rects) { PlaceItem(rect, placementMethod, idx); idx++; } Dictionary <string, object> newOutput; newOutput = new Dictionary <string, object> { { packedItemsOutputPort2D, packedRectangles }, { indicesOutputPort2D, packedIndices }, { remainingItemsOutputPort2D, remainRectangles } }; return(newOutput); }
/// <summary> /// Chooses the best free rectangle based on the placement method /// </summary> /// <param name="item"></param> /// <param name="placementMethod"></param> /// <returns>free rectangle with best score</returns> private static FreeRectangle BestFreeRect( Rectangle item, PlacementMethods placementMethod) { List <FreeRectangle> fRects = new List <FreeRectangle>(); foreach (var fRect in freeRectangles) { FreeRectangle chosenFreeRect; List <FreeRectangle> fitsItem = new List <FreeRectangle>(); if (ItemFits(fRect, item, false)) { FreeRectangle newFree = new FreeRectangle { xPos = fRect.xPos, yPos = fRect.yPos, height = fRect.height, width = fRect.width, rotate = false, }; if (placementMethod == PlacementMethods.BestShortSideFits) { newFree.score = BSSF_Score(newFree, item); } else if (placementMethod == PlacementMethods.BestLongSideFits) { newFree.score = BLSF_Score(newFree, item); } else if (placementMethod == PlacementMethods.BestAreaFits) { newFree.score = BAF_Score(newFree, item); } fitsItem.Add(newFree); } if (ItemFits(fRect, item, true)) { FreeRectangle newFree = new FreeRectangle { xPos = fRect.xPos, yPos = fRect.yPos, height = fRect.height, width = fRect.width, rotate = true, }; if (placementMethod == PlacementMethods.BestShortSideFits) { newFree.score = BSSF_Score(newFree, item); } else if (placementMethod == PlacementMethods.BestLongSideFits) { newFree.score = BLSF_Score(newFree, item); } else if (placementMethod == PlacementMethods.BestAreaFits) { newFree.score = BAF_Score(newFree, item); } fitsItem.Add(newFree); } if (fitsItem.Count == 1) { chosenFreeRect = fitsItem[0]; fRect.score = chosenFreeRect.score; fRect.rotate = chosenFreeRect.rotate; fRects.Add(fRect); } else if (fitsItem.Count == 2) { // Choose free rect with smallest score chosenFreeRect = fitsItem.Aggregate((f1, f2) => f1.score < f2.score ? f1 : f2); fRect.score = chosenFreeRect.score; fRect.rotate = chosenFreeRect.rotate; fRects.Add(fRect); } else { continue; } } if (fRects.Any()) { // Choose free rect with smallest score return(fRects.Aggregate((f1, f2) => f1.score < f2.score ? f1 : f2)); } else { return(null); } }