private static ClassificationResult GetDirectedResult(INestingManager nestingManager, Part part, WorkingArea workingArea, List <Part> originalParts)
        {
            float areaX, areaY;

            if (!nestingManager.IsRectangle(workingArea, out areaX, out areaY))
            {
                throw new Exception("WorkingArea is not a rectangle!");
            }


            //Step 1: Calculate the tesselation polygon
            float boxX, boxY;

            nestingManager.GetRectangleBoxOfPart(part, out boxX, out boxY);
            int horizontalBoxes = (int)(areaX / boxX);
            int verticalBoxes   = (int)(areaY / boxY);

            ClassificationResult result = new ClassificationResult(ClassifierInformation);

            //Step 4: Calculate the remainder polygons
            List <WorkingArea> remainderPolygons = CalculateRemainderWorkingAreas(
                nestingManager,
                boxX,
                boxY,
                horizontalBoxes,
                verticalBoxes,
                areaX,
                areaY);

            //Step 5: Generate the reimainder polygons' problems
            foreach (WorkingArea remainderPolygon in remainderPolygons)
            {
                ClassificationResult subResult = GetMainResult(nestingManager, originalParts, remainderPolygon);

                if (!nestingManager.IsRectangle(remainderPolygon, out areaX, out areaY))
                {
                    throw new Exception("WorkingArea is not a rectangle!");
                }

                result.ExtraPolygons.Add(nestingManager.CalculateRectangle(areaX, areaY, remainderPolygon.Placement));

                result.AddSubResult(subResult, remainderPolygon.Placement);
            }

            for (int i = 0; i < horizontalBoxes; i++)
            {
                for (int j = 0; j < verticalBoxes; j++)
                {
                    Point placementPart = new Point(i * boxX, j * boxY);

                    PlaceGenericPart(nestingManager, placementPart, part, result);

                    result.ExtraPolygons.Add(nestingManager.CalculateRectangle(boxX, boxY, placementPart));
                }
            }

            return(result);
        }
        public static ClassificationResult GetMainResult(
            INestingManager nestingManager,
            List <Part> originalParts,
            WorkingArea workingArea)
        {
            float areaX, areaY;

            if (!nestingManager.IsRectangle(workingArea, out areaX, out areaY))
            {
                throw new Exception("WorkingArea is not a rectangle!");
            }

            //Step 1: Remove parts that do not fit the working area
            float       boxX;
            float       boxY;
            List <Part> parts = new List <Part>();

            foreach (Part part in originalParts)
            {
                nestingManager.GetRectangleBoxOfPart(part, out boxX, out boxY);

                if (areaX >= boxX && areaY >= boxY)
                {
                    //Part does not fit the working area
                    parts.Add(part);
                }
            }

            //Step 2: Break if no parts fit the working area
            if (!parts.Any())
            {
                //Empty result
                return(new ClassificationResult(ClassifierInformation)
                {
                    WorkingArea = workingArea
                });
            }

            //Step 2.5: Sort parts by Area size in descending order, so we favor the placement of bigger pieces
            //in case there are not enough polygons to place all the parts, because the smaller parts could be fit in the remainders
            parts = parts.OrderByDescending(x => x.GetTotalArea()).ToList();

            //Step 3: Calculate the tesselation polygon
            nestingManager.GetRectangleBoxOfParts(parts, out boxX, out boxY);
            int horizontalBoxes = (int)(areaX / boxX);
            int verticalBoxes   = (int)(areaY / boxY);

            WorkingArea tesselationPolygon = new WorkingArea()
            {
                Vertexes = new List <Point>()
                {
                    new Point(0, 0),
                    new Point(boxX, 0),
                    new Point(boxX, boxY),
                    new Point(0, boxY)
                }
            };

            ClassificationResult result = new ClassificationResult(ClassifierInformation);

            //Step 4: Calculate the remainder polygons
            List <WorkingArea> remainderPolygons = CalculateRemainderWorkingAreas(
                nestingManager,
                boxX,
                boxY,
                horizontalBoxes,
                verticalBoxes,
                areaX,
                areaY);

            //Step 5: Generate the reimainder polygons' problems
            foreach (WorkingArea remainderPolygon in remainderPolygons)
            {
                ClassificationResult subResult = GetMainResult(nestingManager, parts, remainderPolygon);

                if (!nestingManager.IsRectangle(remainderPolygon, out areaX, out areaY))
                {
                    throw new Exception("WorkingArea is not a rectangle!");
                }

                result.ExtraPolygons.Add(nestingManager.CalculateRectangle(areaX, areaY, remainderPolygon.Placement));

                result.AddSubResult(subResult, remainderPolygon.Placement);
            }

            //Step6: Generate tesselation poligons' subproblem
            List <ClassificationResult> subresults = new List <ClassificationResult>();

            foreach (Part part in parts)
            {
                ClassificationResult res = GetDirectedResult(nestingManager, part, tesselationPolygon, parts);
                if (res != null)
                {
                    subresults.Add(res);
                }
            }

            result.WorkingArea = workingArea.Clone();

            int numberOfParts = parts.Count;
            int partIndex     = 0;

            //Place parts until we run out of space
            for (int i = 0; i < horizontalBoxes; i++)
            {
                for (int j = 0; j < verticalBoxes; j++)
                {
                    ClassificationResult subResult = subresults[partIndex % numberOfParts];
                    Point subResultOrigin          = new Point(i * boxX, j * boxY);

                    result.AddSubResult(subResult, subResultOrigin);

                    partIndex++;
                }
            }

            return(result);
        }