2

I am trying to draw an arc on a SkiaSharp canvas view using following code.

path3.ArcTo(new SKPoint(0, h/2), 1.57f, SKPathArcSize.Large,
            SKPathDirection.Clockwise, new SKPoint(w/2, h));

But instead of a curve, it is drawing a straight line. How to make it as a curve?

Complete Code

 private void OnPainting(object sender, SKPaintSurfaceEventArgs e)
 {

     var surface = e.Surface;
     var canvas = surface.Canvas;
     canvas.Clear(SKColors.White);

        var w = e.Info.Width;
        var h = e.Info.Height;

        var pathStroke3 = new SKPaint
        {
            IsAntialias = true,
            Style = SKPaintStyle.StrokeAndFill,
            Color = new SKColor(240, 0, 100, 250),
            StrokeWidth = 5
        };

        var path3 = new SKPath { FillType = SKPathFillType.EvenOdd };
        path3.MoveTo(0, h/2);
        path3.ArcTo(new SKPoint(0, h/2), 1.57f, SKPathArcSize.Large, SKPathDirection.Clockwise, new SKPoint(w/2, h));
        path3.LineTo(0, h);
        path3.Close();
        canvas.DrawPath(path3, pathStroke3);


 }

XAML

 <Grid x:Name="controlGrid" ColumnSpacing="0" RowSpacing="0" Padding="0" BackgroundColor="White" >
    <Grid.RowDefinitions>
        <RowDefinition Height="4*" />
        <RowDefinition Height="6*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <views:SKCanvasView PaintSurface="OnPainting" EnableTouchEvents="True" 
     Touch="OnTouch" HeightRequest="300" Grid.Row="0"/>
 </Grid>

enter image description here

LCJ
  • 22,196
  • 67
  • 260
  • 418

2 Answers2

4

Your x radius is zero, thus ArcTo adds a line to the path from the current point to the exit point.

arcTo appends Line to xy if either radii are zero, or if last Path Point equals (x, y). arcTo scales radii r to fit last Path Point and xy if both are greater than zero but too small.

You can do something like:

path3.ArcTo(new SKPoint(100, 100), 0, SKPathArcSize.Large, SKPathDirection.Clockwise, new SKPoint(w / 2, h));

enter image description here

But I do not know what your drawing intent is; concave, convex, bounded, unbounded, etc... but some other examples using ConicTo that might be closer to what I think your intent might be:

path3.ConicTo(w / 3, h / 2, w / 2, h, 0.50f);

enter image description here

path3.ConicTo(0, h - (h / 5), w / 2, h, 0.50f);

enter image description here

You might want to look at the official docs to understand how ArcTo resolves into arcs, conics and moves:

SushiHangover
  • 73,120
  • 10
  • 106
  • 165
1

I am using ConicTo for the following as per the reply from @SushiHangover

References:

  1. Three Types of Bézier Curves - developer.xamarin
  2. Three Ways to Draw an Arc - developer.xamarin
  3. Experimental SkPath - skia.org

enter image description here

Code

private void OnPainting(object sender, SKPaintSurfaceEventArgs e)
{

     var surface = e.Surface;
     var canvas = surface.Canvas;
     canvas.Clear(SKColors.White);

        var w = e.Info.Width;
        var h = e.Info.Height;
        var h12 = h - (h / 8);
        var h8 = h - (h / 6);
        var h4 = h - (h / 3);


        var pathStroke3 = new SKPaint
        {
            IsAntialias = true,
            Style = SKPaintStyle.StrokeAndFill,
            Color = new SKColor(240, 0, 100, 250),
            StrokeWidth = 5
        };

        var path3 = new SKPath { FillType = SKPathFillType.EvenOdd };
        path3.MoveTo(0, h4);
        path3.ConicTo(0, h8, w/2, h12, 0.50f);
        path3.LineTo(w/2, h);
        path3.LineTo(0, h);
        path3.Close();
        canvas.DrawPath(path3, pathStroke3);

        var pathStroke6 = new SKPaint
        {
            IsAntialias = true,
            Style = SKPaintStyle.StrokeAndFill,
            Color = new SKColor(100,0, 240,  250),
            StrokeWidth = 5
        };
        var path6 = new SKPath { FillType = SKPathFillType.EvenOdd };
        path6.MoveTo(w, h4);
        path6.ConicTo(w, h8, w / 2, h12, 0.50f);
        path6.LineTo(w / 2, h);
        path6.LineTo(w, h);
        path6.Close();
        canvas.DrawPath(path6, pathStroke6);


        var pathStroke4 = new SKPaint
        {
            IsAntialias = true,
            Style = SKPaintStyle.Stroke,
            Color = new SKColor(0, 0, 255),
            StrokeWidth = 5
        };

        var path4 = new SKPath { FillType = SKPathFillType.EvenOdd };
        path4.MoveTo(0, h4);
        path4.LineTo(w / 2, h4);
        canvas.DrawPath(path4, pathStroke4);


        var pathStroke5 = new SKPaint
        {
            IsAntialias = true,
            Style = SKPaintStyle.Stroke,
            Color = new SKColor(0, 255, 0),
            StrokeWidth = 5
        };
        var path5 = new SKPath { FillType = SKPathFillType.EvenOdd };
        path5.MoveTo(0, h8);
        path5.LineTo(w / 2, h8);
        canvas.DrawPath(path5, pathStroke5);

        var path7 = new SKPath { FillType = SKPathFillType.EvenOdd };
        path5.MoveTo(w/4, h8);
        path5.LineTo(w /4, h);
        canvas.DrawPath(path5, pathStroke5);

  }
LCJ
  • 22,196
  • 67
  • 260
  • 418