Как нарисовать плавный линейный график в SkiaSharp? - PullRequest
0 голосов
/ 30 апреля 2020

Скажем, у меня есть массив точек с плавающей точкой (функция xy). Первое изображение пытается с SkiaSharp, второе с System.Drawing. NET Framework.

Я понимаю, что я должен использовать метод, подобный CubicTo, но я не вижу, как его объединить с достичь ожидаемого результата.

Пример был создан в WindowsForms (использует только 2 PictureBox) и SkiaSharp nuget. Это похоже на Xamarin, вопрос тот же.

enter image description here

using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;

using System.Drawing;
using System.Drawing.Drawing2D;
using SkiaSharp;

namespace SKLab
{
    public partial class BasicTestForm : Form
    {
        float startX = -4, stopX = 4;
        float yi = -4, ye = 4;
        float w = 200, h = 150;
        float stepX = 1;
        float x, px;
        float y, py;
        // pixel to cartesian    
        float pixelFromX(float cartX) => w * (cartX - startX) / (stopX - startX);
        // cartesian to pixel
        float pixelFromY(float cartY) => h * (cartY - yi) / (ye - yi);

        public BasicTestForm()
        {
            InitializeComponent();
            SkiaPlot(pictureBox1);
            DrawingPlot(pictureBox2);
        }

        private void SkiaPlot(PictureBox p)
        {
            p.Size = new Size((int)w, (int)h);

            using (var surface = SKSurface.Create(new SKImageInfo(p.Width, p.Height))) {
                SKCanvas g = surface.Canvas;

                g.Clear(SKColors.White);

                using (var paint = new SKPaint()) {
                    paint.Style = SKPaintStyle.Stroke;
                    paint.IsAntialias = true;
                    paint.Color = SKColors.CornflowerBlue;
                    paint.StrokeWidth = 2;

                    var path = new SKPath();

                    for (x = startX; x <= stopX; x += stepX) {
                        px = pixelFromX(x);
                        py = pixelFromY((float)Math.Sin(x));
                        if (x == startX) {
                            path.MoveTo(px, py);
                        } else {
                            path.LineTo(px, py);
                        }
                    }
                    g.DrawPath(path, paint);
                }

                using (SKImage image = surface.Snapshot())
                using (SKData data = image.Encode(SKEncodedImageFormat.Png, 100))
                using (MemoryStream mStream = new MemoryStream(data.ToArray())) {
                    p.Image = new Bitmap(mStream, false);
                }
            }
        }

        void DrawingPlot(PictureBox p)
        {
            p.Size = new Size((int)w, (int)h); ;

            // Make the Bitmap.
            var canvas = new Bitmap(p.ClientSize.Width, p.ClientSize.Height);
            using (var g = Graphics.FromImage(canvas)) {
                // Clear.
                g.Clear(Color.White);
                // curve
                var points = new List<PointF>();
                for (x = startX; x <= stopX; x += stepX) {
                    points.Add(new PointF
                    {
                        X = pixelFromX(x),
                        Y = pixelFromY((float)Math.Sin(x))
                    });
                }
                g.SmoothingMode = SmoothingMode.AntiAlias;
                using (var pen = new Pen(Color.CornflowerBlue, 2)) {
                    g.DrawCurve(pen, points.ToArray());
                }
            }
            // Display the result.
            p.Image = canvas;
        }
    }
}
...