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)); }
public EllipticalArcEquation(Point startPoint, EllipticalArcSegment segment) { var phi = ToRadians(segment.XAxisRotation); _cos = Cos(phi); _sin = Sin(phi); var mid = (startPoint - segment.EndPoint) / 2; var x1 = _cos * mid.X + _sin * mid.Y; var y1 = -_sin * mid.X + _cos * mid.Y; _rx = segment.Radii.X; _ry = segment.Radii.Y; var lambda = Square(x1 / _rx) + Square(y1 / _ry); if (lambda > 1) { lambda = Sqrt(lambda); _rx *= lambda; _ry *= lambda; } var sqrt = Sqrt(Square(_rx * _ry) / (Square(_rx * y1) + Square(x1 * _ry)) - 1); var sign = segment.IsLargeArc != segment.IsSweep ? 1 : -1; var cx1 = sign * sqrt * _rx * y1 / _ry; var cy1 = -sign * sqrt * _ry * x1 / _rx; var avg = (startPoint + segment.EndPoint) / 2; _cx = _cos * cx1 - _sin * cy1 + avg.X; _cy = _sin * cx1 + _cos * cy1 + avg.Y; _theta1 = ToDegrees(Atan2((y1 - cy1) / _ry, (x1 - cx1) / _rx)); var theta2 = ToDegrees(Atan2((-y1 - cy1) / _ry, (-x1 - cx1) / _rx)); _deltaTheta = (theta2 - _theta1) % 360; _isSweep = segment.IsSweep; if (_isSweep) { if (_deltaTheta < 0) { _deltaTheta += 360; } } else { if (_deltaTheta > 0) { _deltaTheta -= 360; } } _theta1 = ToRadians(_theta1); _deltaTheta = ToRadians(_deltaTheta); }
public static List<Point> Approximate(Point startPoint, EllipticalArcSegment segment) { return Approximate(new EllipticalArcEquation(startPoint, segment).GetPoint, startPoint, segment.EndPoint); }