public static Path EliminateIntersections([NotNull] Path path)
 {
     IntersectionsCalculator.Calculate(path);
     if (path.Subpaths.SelectMany(x => x.ClosedSegments).All(x => x.Intersections.Count == 0))
     {
         // nothing to do
         return path;
     }
     var subpaths = path.Subpaths.SelectMany(SubpathSplitter.SplitByIntersections).ToList();
     // path creation could be avoided here – do it only for debugging
     path = new Path(subpaths);
     RemoveDuplicatePairs(subpaths);
     path = new Path(subpaths);
     path = new Path(SubpathUnifier.Unify(subpaths));
     return path;
 }
        public static void Calculate(Path path)
        {
            foreach (var subpath in path.Subpaths)
            {
                subpath.BuildPolylineApproximations();
                foreach (var segment in subpath.ClosedSegments)
                {
                    segment.Intersections.Clear();
                }
            }

            for (var i = 0; i < path.Subpaths.Count; i++)
            {
                var subpath1 = path.Subpaths[i];
                var segments1 = subpath1.ClosedSegments.ToArray();
                for (var j = 0; j < segments1.Length; j++)
                {
                    var segment1 = segments1[j];
                    CalculateSelfIntersections(segment1);
                    for (var k = j + 1; k < segments1.Length; k++)
                    {
                        CalculateIntersections(segment1, segments1[k], k == j + 1, j == 0 && k == segments1.Length - 1);
                    }
                    foreach (var subpath2 in path.Subpaths.Skip(i + 1))
                    {
                        if (!segment1.PolylineApproximation.BoundingBox.IntersectsWith(subpath2.PolygonApproximation.BoundingBox))
                        {
                            continue;
                        }
                        foreach (var segment2 in subpath2.ClosedSegments)
                        {
                            CalculateIntersections(segment1, segment2, false, false);
                        }
                    }
                }
            }
        }