public static IEnumerable <IPolyLine2D> BuildOffset(IEnumerable <IPolyLine2D> polylines, double delta, JoinType joinType, EndType endType, double mitterLimit, bool sort = false, double maxDiscretizationAngle = 5)
        {
            PolyLine2DDiscretizator discretizator = new PolyLine2DDiscretizator
            {
                NumberOfTiles = 1,
                LengthOfTile  = double.MaxValue,
                Angle         = maxDiscretizationAngle
            };
            bool containsCircArc = joinType == JoinType.jtRound || endType == EndType.etOpenRound;
            var  polygons        = new List <List <IntPoint> >(polylines.Count());

            foreach (var polyline in polylines)
            {
                if (!containsCircArc)
                {
                    containsCircArc |= polyline.Segments.FirstOrDefault(s => s is CircularArcSegment2D) != null;
                }

                var polygon = CreatePolygon(polyline, discretizator, true);
                polygons.Add(polygon);
            }

            var co = new ClipperOffset(mitterLimit);

            co.AddPaths(polygons, joinType, endType);
            var solution = new List <List <IntPoint> >();

            co.Execute(ref solution, delta * ClipperScale);
            foreach (var polygon in solution)
            {
                yield return(CreatePolyline(polygon, containsCircArc, maxDiscretizationAngle + 1));
            }
        }
        protected static List <IntPoint> CreatePolygon(IPolyLine2D polyline, PolyLine2DDiscretizator discretizator, bool counterClockwise)
        {
            IPolygon2D polygon = new Polygon2D();

            discretizator.Discretize(polyline, ref polygon, null);
            return(CreatePolygon(polygon, counterClockwise));
        }
        public static IEnumerable <IPolyLine2D> BuildOffset(IPolyLine2D polyline, double delta, JoinType joinType, EndType endType, double mitterLimit, bool sort = false, double maxDiscretizationAngle = 5)
        {
            PolyLine2DDiscretizator discretizator = new PolyLine2DDiscretizator
            {
                NumberOfTiles = 1,
                LengthOfTile  = double.MaxValue,
                Angle         = maxDiscretizationAngle
            };
            var p = CreatePolygon(polyline, discretizator, true);

            bool containsCircArc = joinType == JoinType.jtRound || endType == EndType.etOpenRound;

            if (!containsCircArc)
            {
                containsCircArc = polyline.Segments.FirstOrDefault(s => s is CircularArcSegment2D) != null;
            }

            var co = new ClipperOffset(mitterLimit);

            co.AddPath(p, joinType, endType);
            var solution = new List <List <IntPoint> >();

            co.Execute(ref solution, delta * ClipperScale);
            if (sort && polyline.IsClosed && !containsCircArc && joinType == JoinType.jtMiter && (endType == EndType.etClosedLine || endType == EndType.etClosedPolygon) && solution.Count == 1)
            {
                // try to sort offset path according to source path
                var newPolyline = CreatePolyline(solution[0], containsCircArc, maxDiscretizationAngle + 1);
                TrySortSegments(polyline, newPolyline, delta);
                yield return(newPolyline);
            }
            else
            {
                foreach (var polygon in solution)
                {
                    yield return(CreatePolyline(polygon, containsCircArc, maxDiscretizationAngle + 1));
                }
            }
        }
        public static IRegion2D Simplify(IRegion2D region, double maxDiscretizationAngle = 5)
        {
            PolyLine2DDiscretizator discretizator = new PolyLine2DDiscretizator
            {
                NumberOfTiles = 1,
                LengthOfTile  = double.MaxValue,
                Angle         = maxDiscretizationAngle
            };
            var polyline        = region.Outline;
            var containsCircArc = polyline.Segments.FirstOrDefault(s => s is CircularArcSegment2D) != null;
            var polygon         = CreatePolygon(polyline, discretizator, true);
            var solution        = Clipper.SimplifyPolygon(polygon);

            if (solution.Count == 1)
            {
                var newRegion = new Region2D(CreatePolyline(solution[0], containsCircArc, maxDiscretizationAngle + 1));

                foreach (var opening in region.Openings)
                {
                    containsCircArc = opening.Segments.FirstOrDefault(s => s is CircularArcSegment2D) != null;
                    polygon         = CreatePolygon(opening, discretizator, true);
                    solution        = Clipper.SimplifyPolygon(polygon);
                    if (solution.Count == 1)
                    {
                        newRegion.Openings.Add(CreatePolyline(solution[0], containsCircArc, maxDiscretizationAngle + 1));
                    }
                    else
                    {
                        throw new System.NotImplementedException();
                    }
                }

                return(newRegion);
            }

            throw new System.NotImplementedException();
        }