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); } } } }