예제 #1
0
        public List <PackedLayer> Stabilise(IEnumerable <PackedLayer> packedLayers)
        {
            // first re-order according to footprint
            var stabilizedLayers = new List <PackedLayer>();

            packedLayers.OrderBy(l => l);

            var currentZ = 0;

            foreach (var oldZLayer in packedLayers)
            {
                var oldZStart = oldZLayer.GetStartDepth();
                var newZLayer = new PackedLayer();

                foreach (var oldZItem in oldZLayer.Items)
                {
                    var newZ     = oldZItem.Z - oldZStart + currentZ;
                    var newZItem = new PackedItem()
                    {
                        Item   = oldZItem.Item,
                        Width  = oldZItem.Width,
                        Length = oldZItem.Length,
                        Depth  = oldZItem.Depth,
                        X      = oldZItem.X,
                        Y      = oldZItem.Y,
                        Z      = newZ,
                    };
                    newZLayer.Items.Add(newZItem);
                }
                stabilizedLayers.Add(newZLayer);
                currentZ += newZLayer.GetDepth();
            }

            return(stabilizedLayers);
        }
예제 #2
0
        private void TryAndStackItemsIntoSpace(PackedLayer layer,
                                               PackedItem prevItem,
                                               ItemList nextItems,
                                               int maxWidth,
                                               int maxLength,
                                               int maxDepth,
                                               int x,
                                               int y,
                                               int z,
                                               int rowLength
                                               )
        {
            while (items.Count() > 0 && CheckNonDimensionalConstraints(items.Top()))
            {
                var stackedItem = GetOrientationForItem(
                    items.Top(),
                    prevItem,
                    nextItems,
                    items.Count == 1,
                    maxWidth,
                    maxLength,
                    maxDepth,
                    rowLength,
                    x,
                    y,
                    z
                    );

                if (stackedItem != null)
                {
                    remainingWeight -= items.Top().Weight;

                    layer.Insert(PackedItem.FromOrientatedItem(stackedItem, x, y, z));
                    items.Extract();

                    maxDepth -= stackedItem.Depth;
                    z        += stackedItem.Depth;
                }
                else
                {
                    break;
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Pack items into an individual vertical layer.
        /// </summary>
        /// <param name="startDepth"></param>
        /// <param name="widthLeft"></param>
        /// <param name="lengthLeft"></param>
        /// <param name="depthLeft"></param>
        protected void PackLayer(int startDepth, int widthLeft, int lengthLeft, int depthLeft)
        {
            var newLayer = new PackedLayer();

            layers.Add(newLayer);

            int x, y, rowWidth, rowLength, layerDepth;

            x = y = rowWidth = rowLength = layerDepth = 0;

            PackedItem prevItem = null;

            while (items.Count > 0)
            {
                var itemToPack = items.Extract();

                //skip items that are simply too heavy or too large
                if (!CheckNonDimensionalConstraints(itemToPack))
                {
                    RebuildItemList();
                    continue;
                }

                var orientedItem = GetOrientationForItem(itemToPack,
                                                         prevItem,
                                                         items,
                                                         !HasItemsLeftToPack(),
                                                         widthLeft,
                                                         lengthLeft,
                                                         depthLeft,
                                                         rowLength,
                                                         x,
                                                         y,
                                                         startDepth
                                                         );

                if (orientedItem != null)
                {
                    var packedItem = PackedItem.FromOrientatedItem(orientedItem, x, y, startDepth);
                    newLayer.Insert(packedItem);
                    remainingWeight -= orientedItem.Item.Weight;
                    widthLeft       -= orientedItem.Width;

                    rowWidth  += orientedItem.Width;
                    rowLength  = Math.Max(rowLength, orientedItem.Length);
                    layerDepth = Math.Max(layerDepth, orientedItem.Depth);

                    //allow items to be stacked in place within the same footprint up to current layer depth
                    var stackableDepth = layerDepth - orientedItem.Depth;
                    TryAndStackItemsIntoSpace(newLayer,
                                              prevItem,
                                              items,
                                              orientedItem.Width,
                                              orientedItem.Length,
                                              stackableDepth,
                                              x,
                                              y,
                                              startDepth + orientedItem.Depth,
                                              rowLength
                                              );
                    x += orientedItem.Width;

                    prevItem = packedItem;
                    if (items.Count == 0)
                    {
                        RebuildItemList();
                    }
                }
                else if (newLayer.Items.Count == 0)
                {
                    // zero items on layer
                    // doesn't fit on layer even when empty, skipping for good
                    continue;
                }
                else if (widthLeft > 0 && items.Count > 0)
                {
                    // skip for now, move on to the next item
                    skippedItems.Add(itemToPack);

                    // abandon here if next item is the same, no point trying to keep going. Last time is not skipped, need that to trigger appropriate reset logic
                    while (items.Count > 2 && orientatedItemFactory.IsSameDimensions(itemToPack, items.Top()))
                    {
                        this.skippedItems.Add(items.Extract());
                    }
                }
                else if (x > 0 && lengthLeft >= Math.Min(Math.Min(itemToPack.Width, itemToPack.Length), itemToPack.Depth))
                {
                    // No more fit in width wise, resetting for new row
                    widthLeft  += rowWidth;
                    lengthLeft -= rowLength;
                    y          += rowLength;
                    x           = rowWidth = rowLength = 0;
                    skippedItems.Add(itemToPack);
                    RebuildItemList();
                    prevItem = null;
                    continue;
                }
                else
                {
                    // no items fit, so starting next vertical layer
                    skippedItems.Add(itemToPack);
                    RebuildItemList();
                    return;
                }
            }
        }