Drawing Graphics from Path in UWP C#

Viewed 534

I'm trying to convert an android method to draw any types of shape. Following are android code and my tried C# code. My C# code doesn't work at all, it gives ambiguous drawing as output. I searched a lot about path drawing in C# UWP similar of android.graphics.Path but couldn't find anything for UWP.

Android Code

public static Bitmap getPathBitmap(int width, int height, GraphicsSegment[] segments) {

    RectF rect = null;
    Path path = new Path();
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    Paint paint = new Paint();
    paint.setStyle(Paint.Style.FILL);
    paint.setColor(Color.TRANSPARENT);
    canvas.drawPaint(paint);

    for (GraphicsSegment segment : segments) {

        switch (segment.drawingType) {
            case GraphicsSegment.T_MOVETO:
                path.moveTo(segment.x, segment.y);
                break;
            case GraphicsSegment.T_LINETO:
                path.lineTo(segment.x, segment.y);
                break;
            case GraphicsSegment.T_QUADTO:
                path.quadTo(segment.x, segment.y, segment.x2, segment.y2);
                break;
            case GraphicsSegment.T_CUBICTO:
                path.cubicTo(segment.x, segment.y, segment.x1, segment.y1, segment.x2, segment.y2);
                break;
            case GraphicsSegment.T_ARCTO:
                rect = new RectF();
                rect.set(segment.x, segment.y, segment.x1, segment.y1);
                path.arcTo(rect, segment.x2, segment.y2, true);
                break;
            case GraphicsSegment.T_ADDOVAL:
                rect = new RectF();
                rect.set(segment.x, segment.y, segment.x1, segment.y1);
                path.addOval(rect, Path.Direction.CW);
                break;
            case GraphicsSegment.T_CLOSE:
                path.close();
                break;
        }
    }

    paint.setStrokeWidth(2);
    paint.setStyle(Paint.Style.STROKE);
    canvas.drawPath(path, paint);
    return bitmap;
}

My tried C# Code

 public WriteableBitmap getPathBitmap(int width, int height, GraphicsSegment[] segments)
 {
        List<int> points = new List<int>();

        foreach (GraphicsSegment segment in segments)
        {
            if (segment.drawingType == GraphicsSegment.T_CLOSE)
                continue;

            points.Add((int)segment.X);
            points.Add((int)segment.Y);
        }

        WriteableBitmap writeableBmp = BitmapFactory.New(width, height);
        using (writeableBmp.GetBitmapContext())
        {
           writeableBmp.DrawPolyline(points.ToArray(), Colors.Blue);
        }

        return writeableBmp;
 }

GraphicsSegment is a class with properties x,y,x1,y1,x2,y2 corresponding X,Y coordinate position of first, second and third target point

2 Answers

You can do by using Microsoft.Graphics.Canvas namespace. Just follow following steps

  1. Build Path like android using CanvasPathBuilder (Microsoft.Graphics.Canvas.Geometry)
  2. Create CanvasGeometry (Microsoft.Graphics.Canvas.Geometry) using your path
  3. Create CanvasDrawingSession instance
  4. Draw your image using DrawGeometry using CanvasDrawingSession instance
  5. Convert CanvasRenderTarget image to your Required format

Here is sample Code you can try:

public getPathBitmap(int width, int height, GraphicsSegment[] segments) {

    CanvasRenderTarget _RenderImage = null;

    CanvasDevice device = CanvasDevice.GetSharedDevice();
    var logicalDpi = 96.0f;

    //Step 01
    var path = new CanvasPathBuilder(device);  

    foreach(GraphicsSegment segment in segments) {
        switch (segment.drawingType) {
        case GraphicsSegment.T_MOVETO:
            path.BeginFigure(X-Cordinate Start Position, Y-Cordinate Start Position);
            break;
        case GraphicsSegment.T_LINETO:
            path.AddLine(X-Cordinate Next Position, Y-Cordinate Next Position);
            break;
        case GraphicsSegment.T_QUADTO:
            {
                Vector2 point = new Vector2(X-Cordinate Control Position1, Y-Cordinate Control Position1);
                Vector2 point2 = new Vector2(X-Cordinate Control Position2, Y-Cordinate Control Position2);
                path.AddQuadraticBezier(point, point2);
            }
            break;
        case GraphicsSegment.T_CUBICTO:
            {
                Vector2 point = new Vector2(X-Cordinate Control Position1, Y-Cordinate Control Position1);
                Vector2 point2 = new Vector2(X-Cordinate Control Position2, Y-Cordinate Control Position2);
                Vector2 point3 = new Vector2(X-Cordinate End Position, Y-Cordinate End Position);
                path.AddCubicBezier(point, point2, point3);
            }
            break;
        case GraphicsSegment.T_ARCTO:
            {
                //TODO:: Set centerPoint, radiusX, radiusY, startAngle, sweepAngle by your self based on your requirement
                Vector2 centerPoint = Calculate();
                path.AddArc(centerPoint, radiusX, radiusY, startAngle, sweepAngle);
            }
            break;
        case GraphicsSegment.T_CLOSE:
            path.EndFigure(CanvasFigureLoop.Closed);
            break;
        case GraphicsSegment.T_ADDOVAL:
            {
                //TODO:: Set endpoint,radiusX,radiusY,rotationAngle by your self based on your requirement
                Vector2 endpoint = Calculate();
                path.AddArc(endpoint, radiusX, radiusY, rotationAngle, CanvasSweepDirection.Clockwise, CanvasArcSize.Small);
            }

            break;
        }
    }

    //Step 02
    var g = CanvasGeometry.CreatePath(path);

    _RenderImage = new CanvasRenderTarget(device, width, height, logicalDpi);

    //Step 03
    using(var ds = _RenderImage.CreateDrawingSession()) {
        ds.Clear(Colors.Transparent);

        //Step 05
        ds.DrawGeometry(g, Colors.Blue, 3.0f);
    }

    //Step 05
    //Here you have to convert CanvasRenderTarget object  _RenderImage to your required format like bitmapimage,stream,stroageFile etc
    return yourTypeFile;
}

You should look at using Win2D for Graphic drawing like this on UWP. Here is an example of how to use it for offscreen drawing.

Related