Exemple #1
0
        private void Pack_recursive(PartList parts, BoardList boards, PartList TemporarySolution, double tempSolutionArea)
        {
            // loop through remaining parts
            for (PartNode iPart = parts.Tail; iPart != null; iPart = iPart.Prev)
            {
                #region // check if the part is a viable candidate ...
                // if this part has bigger area than the largest board segment available, go to next part
                if (iPart.Area > boards.Tail.Area)
                {
                    continue;
                }
                // if the previous part was the same size, pass this one - we already completed this iteration
                if (iPart != parts.Tail && iPart.Length == iPart.Next.Length && iPart.Width == iPart.Next.Width)
                {
                    continue;
                }
                #endregion

                #region // Find first board that will fit the part ...
                // find first board that will accomodate the part
                BoardNode iBoard = boards.Head;

                // if even the last (bigest) board had a smaller area than the part, non of the rest will fit
                while (iPart.Area > iBoard.Area)
                {
                    iBoard = iBoard.Next;
                }
                while (iBoard != null && (iPart.Length > iBoard.Length || iPart.Width > iBoard.Width))
                {
                    iBoard = iBoard.Next;
                }
                if (iBoard == null)
                {
                    continue; // if this part cannot fit any board, continue to next part
                }
                #endregion

                #region // place the part ...
                double newPackedPartsArea = tempSolutionArea + iPart.Area;
                //append the part to the list of packed parts
                TemporarySolution.Append(new PartNode(iPart)
                {
                    Container = iBoard.ID,
                    dWidth    = iBoard.dWidth,
                    dLength   = iBoard.dLength
                });
                #endregion

                #region // store best solution ...
                //if this is a better solution than the current best one ... replace the current best one
                if (newPackedPartsArea > currentSolutionArea)
                {
                    currentSolutionArea = newPackedPartsArea;
                    currentSolution     = new PartList(TemporarySolution);
                }
                #endregion

                // if there are no more parts, break out of the loop
                if (parts.Count == 1)
                {
                    break;
                }

                #region // Break association and adjust associate if a board is used that is associated with another to prevent overlapping placements ...
                BoardNode iAssocBoard = iBoard.AssociatedBoard;
                double    oAssocLength = 0, oAssocWidth = 0;
                // if the board section used has a buddy from a previous placement, adjust the buddy and break the association
                if (iAssocBoard != null)
                {
                    oAssocLength = iAssocBoard.Length;
                    oAssocWidth  = iAssocBoard.Width;;

                    //we have to adjust the buddy, so as not to place another part on the overlapping area
                    if (iBoard.dWidth < iAssocBoard.dWidth)
                    {
                        //if this is Rem1
                        //if the part is wider than the left portion of Rem1
                        if (iBoard.dWidth + iPart.Width + sawkerf > iAssocBoard.dWidth)
                        {
                            iAssocBoard.Length -= (iBoard.Length + sawkerf);
                        }
                        else
                        {
                            iBoard.Width -= (iAssocBoard.Width + sawkerf);
                        }
                    }
                    else
                    {
                        //if this is Rem2
                        if (iBoard.dLength + iPart.Length + sawkerf > iAssocBoard.dLength)
                        {
                            iAssocBoard.Width -= (iBoard.Width + sawkerf);
                        }
                        else
                        {
                            iBoard.Length -= (iAssocBoard.Length + sawkerf);
                        }
                    }

                    //then break the pair
                    iAssocBoard.AssociatedBoard = null;
                    iBoard.AssociatedBoard      = null;
                }
                #endregion

                #region // remove the current part from the parts list ...
                parts.Remove(iPart);
                #endregion

                #region // replace the used board with 2 overlapping remainder pieces after subtracting the part ...
                // divide the board into two overlapping remainder sections
                boards.Remove(iBoard);
                BoardNode boardSection1 = null;
                double    l             = iBoard.Length - iPart.Length - sawkerf;
                if (l * iBoard.Width >= parts.Head.Area)
                {
                    boardSection1 = new BoardNode(iBoard.ID, l, iBoard.Width, iBoard.dLength + iPart.Length + sawkerf, iBoard.dWidth);
                    boards.InsertItemSortedbyAreaAsc(boardSection1);
                }
                BoardNode boardSection2 = null;
                double    w             = iBoard.Width - iPart.Width - sawkerf;
                if (w * iBoard.Length >= parts.Head.Area)
                {
                    boardSection2 = new BoardNode(iBoard.ID, iBoard.Length, w, iBoard.dLength, iBoard.dWidth + iPart.Width + sawkerf);
                    boards.InsertItemSortedbyAreaAsc(boardSection2);
                    boardSection2.AssociatedBoard = boardSection1;
                    if (boardSection1 != null)
                    {
                        boardSection1.AssociatedBoard = boardSection2;
                    }
                }
                #endregion

                if (boards.Count > 0)
                {
                    #region // pack the remaining parts on the remaining boards ...
                    // pack the remaining parts on the remaining boards
                    Pack_recursive(parts, boards, TemporarySolution, newPackedPartsArea);
                    #endregion
                }

                #region // undo the placement so we can iterate to the next part and test with it ...
                // place the current part back in its exact place ...
                parts.Return(iPart);

                // remove the remainder board sections we added...
                if (boardSection1 != null)
                {
                    boards.Remove(boardSection1);
                }
                if (boardSection2 != null)
                {
                    boards.Remove(boardSection2);
                }

                // restore associations, and the original associated board's size
                if (iAssocBoard != null)
                {
                    iBoard.AssociatedBoard      = iAssocBoard;
                    iAssocBoard.AssociatedBoard = iBoard;
                    iAssocBoard.Length          = oAssocLength;
                    iAssocBoard.Width           = oAssocWidth;
                }

                // place the board back
                if (iBoard.Prev == null)
                {
                    boards.Head = iBoard;
                }
                else
                {
                    iBoard.Prev.Next = iBoard;
                }
                if (iBoard.Next == null)
                {
                    boards.Tail = iBoard;
                }
                else
                {
                    iBoard.Next.Prev = iBoard;
                }
                boards.Count++;

                // remove the part from the temporary solution
                TemporarySolution.Tail = TemporarySolution.Tail.Prev;
                if (TemporarySolution.Tail != null)
                {
                    TemporarySolution.Tail.Next = null;
                }
                else
                {
                    TemporarySolution.Head = null;
                }
                TemporarySolution.Count--;

                #endregion
            }
        }