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 void SetNestingManager(INestingManager nestingManager)
        {
            if (nestingManager == null)
            {
                throw new ArgumentNullException(nameof(nestingManager));
            }

            _nestingManager = nestingManager;
        }
Esempio n. 3
0
        private static ClassificationResult ClassifyGeneric(
            INestingManager manager,
            List <Part> parts,
            WorkingArea workingArea)
        {
            float areaX, areaY;

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

            float boxX, boxY;

            manager.GetRectangleBoxOfParts(parts, out boxX, out boxY);

            if (boxX > areaX || boxY > areaY)
            {
                throw new Exception("Part does not fit inside Working area!");
            }

            //Calculate how many boxes could be fit in the area
            int horizontalBoxes = (int)(areaX / boxX);
            int verticalBoxes   = (int)(areaY / boxY);

            //We build the final result using the partial results and the calculated positions of the boxes
            ClassificationResult result = new ClassificationResult(ClassifierInformation)
            {
                WorkingArea = workingArea.Clone()
            };

            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++)
                {
                    Point subResultOrigin = new Point(i * boxX, j * boxY);
                    result.ExtraPolygons.Add(manager.CalculateRectangle(boxX, boxY, subResultOrigin));

                    Part placedPart = parts[partIndex % parts.Count].Clone();

                    placedPart.Place(subResultOrigin);

                    result.Parts.Add(placedPart);

                    partIndex++;
                }
            }

            return(result);
        }
        private static void PlaceGenericPart(INestingManager nestingManager, Point originOfTesselationPolygon, Part part, ClassificationResult result)
        {
            part.Place(Point.Origin);

            if (nestingManager.IsRightTriangle(part))
            {
                Part flippedTriangle = nestingManager.CalculateFlippedRightTriangle(part);
                flippedTriangle.Place(Point.Origin);

                PlacePart(originOfTesselationPolygon, flippedTriangle, result);
            }

            PlacePart(originOfTesselationPolygon, part, result);
        }
        private static List <WorkingArea> CalculateRemainderWorkingAreas(
            INestingManager nestingManager,
            float tesselationPolygonWidth,
            float tesselationPolygonHeight,
            int horizontalBoxes,
            int verticalBoxes,
            float workingAreaWidth,
            float workingAreaHeight)
        {
            List <WorkingArea> result = new List <WorkingArea>();

            float width1  = tesselationPolygonWidth * horizontalBoxes;
            float height1 = workingAreaHeight - tesselationPolygonHeight * verticalBoxes;

            float width2  = workingAreaWidth - tesselationPolygonWidth * horizontalBoxes;
            float height2 = height1;

            float width3  = width2;
            float height3 = tesselationPolygonHeight * verticalBoxes;

            if (height1 > 0)
            {
                WorkingArea area = nestingManager.CalculateWorkingArea(width1, height1);
                area.Placement = new Point(0, tesselationPolygonHeight * verticalBoxes);
                result.Add(area);
            }

            if (height2 > 0 && width2 > 0)
            {
                WorkingArea area = nestingManager.CalculateWorkingArea(width2, height2);
                area.Placement = new Point(tesselationPolygonWidth * horizontalBoxes, tesselationPolygonHeight * verticalBoxes);
                result.Add(area);
            }

            if (width3 > 0)
            {
                WorkingArea area = nestingManager.CalculateWorkingArea(width3, height3);
                area.Placement = new Point(tesselationPolygonWidth * horizontalBoxes, 0);
                result.Add(area);
            }

            return(result);
        }
        private static void ClassifySinglePart(INestingManager nestingManager, Part part, WorkingArea workingArea, List <ClassificationResult> results)
        {
            Point point = Point.Origin;

            part.Place(Point.Origin);


            float areaWidth, areaHeight;

            if (!nestingManager.IsRectangle(workingArea, out areaWidth, out areaHeight))
            {
                throw new InvalidOperationException("Area is not a rectangle");
            }

            foreach (KeyValuePair <Point, Point> edge in part.ConvexHullEdges())
            {
                Part mirror = part.CalculateMirror(edge.Key, edge.Value);
                Part clone  = part.Clone();

                mirror.Place(point);
                clone.Place(point);

                Part hull = new Part();

                foreach (var side in new Part[] { mirror, clone })
                {
                    if (side.InnerParts.Any())
                    {
                        hull.InnerParts.AddRange(side.InnerParts.Select(x => x.Clone()));
                    }
                    else
                    {
                        hull.InnerParts.Add(side);
                    }
                }

                hull.FitToOrigin();

                float hullWidth, hullHeight;

                nestingManager.GetRectangleBoxOfPart(hull, out hullWidth, out hullHeight);

                //Is the hull too big for the area?
                if (!(hullWidth <= areaWidth) || !(hullHeight <= areaHeight))
                {
                    continue;
                }

                ClassificationResult result = new ClassificationResult(ClassifierInformation)
                {
                    Parts       = hull.InnerParts,
                    WorkingArea = workingArea
                };

                //The result was already found?
                if (results.Contains(result))
                {
                    //Ignore result
                    continue;
                }

                //If it fits, we store the part and continue operating over it.
                results.Add(result);

                ClassifySinglePart(nestingManager, hull, workingArea, results);
            }
        }
Esempio n. 7
0
 public void SetNestingManager(INestingManager nestingManager)
 {
     //This classifier does not use Nesting Manager
 }
Esempio n. 8
0
 public void SetNestingManager(INestingManager nestingManager)
 {
     this.manager = nestingManager;
 }
        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);
        }