Example #1
0
        static public PartList Pack(PartList parts, BoardList boards, double sawkerf = 4, double boardMarginLength = 0, double boardMarginWidth = 0, double partPaddingLength = 0, double partPaddingWidth = 0)
        {
            // order the parts by Area, Ascending
            var orderredParts = parts.OrderredByArea();
            var oderredBoards = boards.OrderredByArea();

            // add padding to parts
            orderredParts.InflateAll(partPaddingWidth, partPaddingLength);

            // init the bag for the solution
            PartList completeSolution = new PartList();

            // repeat until all parts are placed, or boards used up
            int iteration = 0;

            while (orderredParts.Count > 0 && oderredBoards.Count > 0)
            {
                // for this iteration, prepare to hold the best board's packing solution
                PartList bestsolution         = null;
                double   bestsolutioncoverage = 0;

                // we will pack each board in its own thread, so we need to track the threads
                List <Task> threads = new List <Task>();

                // loop through the available board sections
                for (BoardNode iBoard = oderredBoards.Head; iBoard != null; iBoard = iBoard.Next)
                {
                    threads.Add(
                        Task.Factory.StartNew((o) =>
                    {
                        Thread.CurrentThread.Priority = ThreadPriority.Highest;
                        // for every board
                        BoardNode tiBoard = new BoardNode((BoardNode)o);
                        // subtract the margin from the board
                        tiBoard.Inflate(-boardMarginWidth, -boardMarginLength);

                        // init a packer object
                        Packer iPacker = new Packer()
                        {
                            boardArea = tiBoard.Area,
                            sawkerf   = sawkerf
                        };

                        // pack the board recursively, starting at the first part and an empty solution
                        iPacker.Pack_recursive(new PartList(orderredParts), new BoardList(tiBoard), new PartList(), 0);

                        //Trace.WriteLine($"......in iteration {iteration+1}: Board {iPacker.currentSolution.Head.Container} packed to {iPacker.currentSolutionArea/iPacker.boardArea:0 %} :\r\n{iPacker.currentSolution.ToString()}");

                        // replace the best solution if this one is better
                        lock (lck)
                            if (iPacker.currentSolutionArea / iPacker.boardArea > bestsolutioncoverage)
                            {
                                bestsolutioncoverage = iPacker.currentSolutionArea / iPacker.boardArea;
                                bestsolution         = iPacker.currentSolution;
                            }
                    }, iBoard));
                }
                Task.WaitAll(threads.ToArray());

                // if no board could be packed, stop
                if (bestsolutioncoverage == 0)
                {
                    Trace.WriteLine("STOPPING: Non of the parts left to place would fit any of the available boards...");
                    break;
                }

                boards[bestsolution.Head.Container].Solution = new PartList(bestsolution);
                // report the best packking for this iteration
                Trace.WriteLine($"Best solution for iteration {++iteration}: Board {bestsolution.Head.Container} packed to {bestsolutioncoverage:0 %} :\r\n{bestsolution.ToString()}");

                // remove best packed board from the list of available boards
                oderredBoards.Remove(bestsolution.Head.Container);

                // remove the parts packed from the list of required parts
                for (PartNode iPart = bestsolution.Head; iPart != null; iPart = iPart.Next)
                {
                    orderredParts.Remove(iPart.ID);
                }

                // add this partial solution to the complete solution...
                completeSolution.Append(bestsolution);
            }

            // return the solution
            return(completeSolution);
        }