public override void ArcTo(Point point, Size size, double rotationAngle, bool isLargeArc, SweepDirection sweepDirection, bool isStroked, bool isSmoothJoin) { if (size.Width != size.Height) { throw new NotImplementedException("The arc must be based on a circle, not an ellipse."); } var startPoint = _points.Last(); var endPoint = point; var radius = size.Width; var sign = isLargeArc != (sweepDirection == SweepDirection.Clockwise); var center = CenterFromPointsAndRadius(startPoint, endPoint, radius, sign); var startAngle = Atan2(startPoint.Y - center.Y, startPoint.X - center.X); var endAngle = Atan2(endPoint.Y - center.Y, endPoint.X - center.X); var circle = new Rect(center.X - radius, center.Y - radius, radius * 2, radius * 2); #if __IOS__ bezierPath.AddArc( center, (nfloat)radius, (nfloat)startAngle, (nfloat)endAngle, sweepDirection == SweepDirection.Clockwise ); #elif __MACOS__ bezierPath.AppendPathWithArc(center, (nfloat)radius, (nfloat)startAngle, (nfloat)endAngle, sweepDirection == SweepDirection.Clockwise); #elif __ANDROID__ var sweepAngle = endAngle - startAngle; // Convert to degrees startAngle = startAngle * (180 / PI); sweepAngle = sweepAngle * (180 / PI); // Invert y-axis startAngle = (startAngle + 360) % 360; sweepAngle = (sweepAngle + 360) % 360; // Apply direction if (sweepDirection == SweepDirection.Counterclockwise) { sweepAngle -= 360; } bezierPath.ArcTo( circle.LogicalToPhysicalPixels().ToRectF(), (float)startAngle, (float)sweepAngle ); #endif _points.Add(point); }
public override void ArcTo(Point point, Size size, double rotationAngle, bool isLargeArc, SweepDirection sweepDirection, bool isStroked, bool isSmoothJoin) { if (size.Width != size.Height) { throw new NotImplementedException("The arc must be based on a circle, not an ellipse."); } var startPoint = _points.Last(); var endPoint = point; var radius = size.Width; var sign = isLargeArc != (sweepDirection == SweepDirection.Clockwise); var center = CenterFromPointsAndRadius(startPoint, endPoint, radius, sign); var startAngle = Atan2(startPoint.Y - center.Y, startPoint.X - center.X); var endAngle = Atan2(endPoint.Y - center.Y, endPoint.X - center.X); var circle = new Rect(center.X - radius, center.Y - radius, radius * 2, radius * 2); #if __IOS__ bezierPath.AddArc( center, (nfloat)radius, (nfloat)startAngle, (nfloat)endAngle, sweepDirection == SweepDirection.Clockwise ); #elif __MACOS__ //Ugly workaround. check if all vars are defined if (!double.IsNaN(radius) && !double.IsNaN(startAngle) && !double.IsNaN(endAngle)) { //Convert to degrees in a 0 =< x =< 360 deg range startAngle = MathEx.ToDegreeNormalized(startAngle); endAngle = MathEx.ToDegreeNormalized(endAngle); bezierPath.AppendPathWithArc(center, (nfloat)radius, (nfloat)startAngle, (nfloat)endAngle); //Move to startPoint. To prevent segment being drawn to the startPoint from the end of the arc bezierPath.MoveTo(startPoint); } #elif __ANDROID__ var sweepAngle = endAngle - startAngle; // Convert to degrees startAngle = startAngle * (180 / PI); sweepAngle = sweepAngle * (180 / PI); // Invert y-axis startAngle = (startAngle + 360) % 360; sweepAngle = (sweepAngle + 360) % 360; // Apply direction if (sweepDirection == SweepDirection.Counterclockwise) { sweepAngle -= 360; } bezierPath.ArcTo( circle.ToRectF(), (float)startAngle, (float)sweepAngle ); #elif __SKIA__ var sweepAngle = endAngle - startAngle; // Convert to degrees startAngle = startAngle * (180 / PI); sweepAngle = sweepAngle * (180 / PI); // Invert y-axis startAngle = (startAngle + 360) % 360; sweepAngle = (sweepAngle + 360) % 360; // Apply direction if (sweepDirection == SweepDirection.Counterclockwise) { sweepAngle -= 360; } bezierPath.Geometry.ArcTo( new SkiaSharp.SKRect((float)circle.Left, (float)circle.Top, (float)circle.Right, (float)circle.Bottom), (float)startAngle, (float)sweepAngle, false ); #endif _points.Add(point); }