public static Point GetInsidePoint(IReadOnlyList<Point> points, Box boundingBox)
 {
     var y = (boundingBox.MinY + boundingBox.MaxY) / 2;
     var xIntersections = new List<double>();
     var point1 = points.Last();
     foreach (var point2 in points)
     {
         if ((y > point1.Y) != (y > point2.Y))
         {
             xIntersections.Add((y - point2.Y) * (point1.X - point2.X) / (point1.Y - point2.Y) + point2.X);
         }
         point1 = point2;
     }
     xIntersections.Sort();
     Debugger.BreakWhen(xIntersections.Count == 0 || xIntersections.Count % 2 != 0);
     var x = (boundingBox.MinX + boundingBox.MaxX) / 2;
     var maxDelta = double.NegativeInfinity;
     for (var i = 0; i < xIntersections.Count - 1; i += 2)
     {
         var delta = Math.Abs(xIntersections[i] - xIntersections[i + 1]);
         if (delta > maxDelta)
         {
             x = (xIntersections[i] + xIntersections[i + 1]) / 2;
             maxDelta = delta;
         }
     }
     var point = new Point(x, y);
     #if DEBUG
     Debugger.BreakWhen(!PointInPolygonTest.Contains(points, point));
     #endif
     return point;
 }
 public bool IntersectsWith(Box box)
 {
     return
         box.MinX <= MaxX &&
         box.MaxX >= MinX &&
         box.MinY <= MaxY &&
         box.MaxY >= MinY;
 }
 public Polyline([NotNull] IEnumerable<Point> points)
 {
     Points = points.ToReadOnlyList();
     BoundingBox = new Box(
         Points.Select(x => x.X).Min(),
         Points.Select(x => x.X).Max(),
         Points.Select(x => x.Y).Min(),
         Points.Select(x => x.Y).Max());
 }
 private static void CalculateIntersections(SegmentBase segment1, SegmentBase segment2, bool skipInner, bool skipOuter)
 {
     var boundingBox1 = segment1.PolylineApproximation.BoundingBox;
     var boundingBox2 = segment2.PolylineApproximation.BoundingBox;
     if (!boundingBox1.IntersectsWith(boundingBox2))
     {
         return;
     }
     var points1 = segment1.PolylineApproximation.Points;
     var points2 = segment2.PolylineApproximation.Points;
     for (var i = 1; i < points1.Count; i++)
     {
         var p11 = points1[i - 1];
         var p12 = points1[i];
         var box1 = new Box(p11, p12);
         if (!box1.IntersectsWith(boundingBox2))
         {
             continue;
         }
         for (var j = 1; j < points2.Count; j++)
         {
             var p21 = points2[j - 1];
             var p22 = points2[j];
             var box2 = new Box(p21, p22);
             if (!box1.IntersectsWith(box2))
             {
                 continue;
             }
             if ((skipInner && i == points1.Count - 1 && j == 1) ||
                 (skipOuter && i == 1 && j == points2.Count - 1))
             {
                 continue;
             }
             var intersection = CalculateIntersection(p11, p12, p21, p22);
             if (intersection.HasValue)
             {
                 segment1.Intersections.Add(intersection.Value);
                 segment2.Intersections.Add(intersection.Value);
             }
         }
     }
 }
 private static void CalculateSelfIntersections(SegmentBase segment)
 {
     if (!(segment is CubicBezierSegment))
     {
         // only cubic bezier segment can self-intersect
         return;
     }
     var points = segment.PolylineApproximation.Points;
     for (var i = 1; i < points.Count - 2; i++)
     {
         var p11 = points[i - 1];
         var p12 = points[i];
         var box1 = new Box(p11, p12);
         for (var j = i + 2; j < points.Count; j++)
         {
             var p21 = points[j - 1];
             var p22 = points[j];
             var box2 = new Box(p21, p22);
             if (!box1.IntersectsWith(box2))
             {
                 continue;
             }
             var intersection = CalculateIntersection(p11, p12, p21, p22);
             if (intersection.HasValue)
             {
                 segment.Intersections.Add(intersection.Value);
             }
         }
     }
 }