public static Point SplitByNextIntersection(Point startPoint, LineSegment segment, out SegmentBase segment1, out SegmentBase segment2) { return SplitByNextIntersection(startPoint, segment, out segment1, out segment2, new LineEquation(startPoint, segment), (t, p) => new LineSegment(p), t => new LineSegment(segment.EndPoint)); }
public static Point SplitByNextIntersection(Point startPoint, QuadraticBezierSegment segment, out SegmentBase segment1, out SegmentBase segment2) { return SplitByNextIntersection(startPoint, segment, out segment1, out segment2, new QuadraticBezierEquation(startPoint, segment), (t, p) => new QuadraticBezierSegment(Mid(startPoint, segment.ControlPoint, t), p), t => new QuadraticBezierSegment(Mid(segment.ControlPoint, segment.EndPoint, t), segment.EndPoint)); }
public static Point SplitByNextIntersection(Point startPoint, EllipticalArcSegment segment, out SegmentBase segment1, out SegmentBase segment2) { Func<Point, EllipticalArcSegment> create = p => new EllipticalArcSegment(segment.Radii, segment.XAxisRotation, segment.IsLargeArc, segment.IsSweep, p); return SplitByNextIntersection(startPoint, segment, out segment1, out segment2, new EllipticalArcEquation(startPoint, segment), (t, p) => create(p), t => create(segment.EndPoint)); }
private static bool IsDegenerate(Point startPoint, SegmentBase segment) { if (segment is LineSegment || segment is EllipticalArcSegment) { return segment.EndPoint == startPoint; } return false; }
public static Subpath ReverseDirection(Subpath subpath) { var segments = new SegmentBase[subpath.Segments.Count]; var startPoint = subpath.StartPoint; for (var i = 0; i < segments.Length; i++) { var segment = subpath.Segments[i]; segments[i] = segment.Reverse(startPoint); startPoint = segment.EndPoint; } Array.Reverse(segments); return new Subpath(startPoint, segments, subpath.IsClosed); }
public static Point SplitByNextIntersection(Point startPoint, CubicBezierSegment segment, out SegmentBase segment1, out SegmentBase segment2) { return SplitByNextIntersection(startPoint, segment, out segment1, out segment2, new CubicBezierEquation(startPoint, segment), (t, p) => { var a = Mid(startPoint, segment.ControlPoint1, t); var b = Mid(segment.ControlPoint1, segment.ControlPoint2, t); return new CubicBezierSegment(a, Mid(a, b, t), p); }, t => { var b = Mid(segment.ControlPoint1, segment.ControlPoint2, t); var c = Mid(segment.ControlPoint2, segment.EndPoint, t); return new CubicBezierSegment(Mid(b, c, t), c, segment.EndPoint); }); }
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 Point SplitByNextIntersection(Point startPoint, SegmentBase segment, out SegmentBase segment1, out SegmentBase segment2, CurveEquation equation, Func<double, Point, SegmentBase> factory1, Func<double, SegmentBase> factory2) { var intersection = segment.Intersections.Select(x => new { Point = x, T = equation.GetT(x) }).MinBy(x => x.T); var t = Math.Min(Math.Max(intersection.T, 0), 1); var point = equation.GetPoint(t); segment1 = point == startPoint ? null : factory1(t, intersection.Point); if (point == segment.EndPoint) { segment2 = null; Debugger.BreakWhen(segment.Intersections.Count > 1); } else { segment2 = factory2(t); segment2.Intersections.AddRange(segment.Intersections.Where(x => x != intersection.Point)); } return intersection.Point; }
private static SegmentBase Simplify(Point startPoint, SegmentBase segment) { var endPoint = segment.EndPoint; var simplifyToLine = false; if (segment is EllipticalArcSegment) { var x = (EllipticalArcSegment)segment; simplifyToLine = x.Radii.X.IsZero() || x.Radii.Y.IsZero(); } if (segment is QuadraticBezierSegment) { var x = (QuadraticBezierSegment)segment; simplifyToLine = x.ControlPoint == startPoint || x.ControlPoint == endPoint; } if (segment is CubicBezierSegment) { var x = (CubicBezierSegment)segment; simplifyToLine = (x.ControlPoint1 == startPoint || x.ControlPoint1 == endPoint) && (x.ControlPoint2 == startPoint || x.ControlPoint2 == endPoint); } return simplifyToLine ? new LineSegment(endPoint) : segment; }
public override Point SplitByNextIntersection(Point startPoint, out SegmentBase segment1, out SegmentBase segment2) { return SegmentSplitter.SplitByNextIntersection(startPoint, this, out segment1, out segment2); }
public override Point SplitByNextIntersection(Point startPoint, out SegmentBase segment1, out SegmentBase segment2) { return(SegmentSplitter.SplitByNextIntersection(startPoint, this, out segment1, out segment2)); }
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); } } } }
public abstract Point SplitByNextIntersection(Point startPoint, out SegmentBase segment1, out SegmentBase segment2);