Как вы переводите координаты диаграммы в пиксели устройства в SkiaSharp? - PullRequest
0 голосов
/ 29 января 2020

Я пытаюсь написать матричное преобразование для преобразования точек диаграммы в пиксели устройства в SkiaSharp. У меня это работает, пока я использую 0,0 как минимальные координаты графика, но если мне нужно подняться с отрицательного числа, это заставит рисунок сместиться влево и вниз. То есть ось X смещена влево за пределы окна, а ось Y смещена за пределы окна.

Это предназначено для типичного линейного графика (минимальная точка на графике внизу слева) в то время как минимальная точка устройства в левом верхнем углу). Я учел это уже в преобразовании.

Проходя по коду, я вижу, что координаты, возвращаемые из матрицы, не те, которые я ожидал, поэтому я считаю, что проблема связана с моим преобразованием, но Я не смог точно определить это.

ОБНОВЛЕНИЕ: После дальнейшего изучения, я считаю, что я ошибся, он не сдвинут, он просто не масштабируется должным образом до максимального конца экран. В верхней и правой части графика больше поля, чем должно быть, но с нижней и левой стороны все в порядке. Мне не удалось определить, почему масштабирование не заполняет холст.

Ниже приведены мои матричные методы:

private SKMatrix ChartToDeviceMatrix, DeviceToChartMatrix;
private void ConfigureTransforms(SKPoint ChartMin, 
    SKPoint ChartMax, SKPoint DeviceMin, SKPoint DeviceMax)
{
    this.ChartToDeviceMatrix = SKMatrix.MakeIdentity();
    float xScale = (DeviceMax.X - DeviceMin.X) / (ChartMax.X - ChartMin.X);
    float yScale = (DeviceMin.Y - DeviceMax.Y) / (ChartMax.Y - ChartMin.Y);

    this.ChartToDeviceMatrix.SetScaleTranslate(xScale, yScale, DeviceMin.X, DeviceMax.Y);
    this.ChartToDeviceMatrix.TryInvert(out this.DeviceToChartMatrix);
}

// Transform a point from chart to device coordinates.
private SKPoint ChartToDevice(SKPoint point)
{
    return this.ChartToDeviceMatrix.MapPoint(point);
}

Код, вызывающий это:

void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
    SKImageInfo info = args.Info;
    SKSurface surface = args.Surface;
    SKCanvas canvas = surface.Canvas;

    float strokeWidth = 1;
    float margin = 10;

    // SKPaint definitions omitted for brevity.

    var ChartMin = new SKPoint(-10, -1); // Works fine if I change this to 0,0
    var ChartMax = new SKPoint(110, 11);
    var DeviceMin = new SKPoint(margin, margin);
    var DeviceMax = new SKPoint(info.Width - margin, info.Height - margin);
    const float stepX = 10;
    const float stepY = 1;
    const float tickX = 0.5;
    const float tickY = 0.075F;

    // Prepare the transformation matrices.
    this.ConfigureTransforms(ChartMin, ChartMax, DeviceMin, DeviceMax);

    // Draw the X axis.
    var lineStart = new SKPoint(ChartMin.X, 0);
    var lineEnd = new SKPoint(ChartMax.X, 0);
    canvas.DrawLine(this.ChartToDevice(lineStart), this.ChartToDevice(lineEnd), axisPaint);

    // X Axis Tick Marks
    for (float x = stepX; x <= ChartMax.X - stepX; x += stepX)
    {
        var tickMin = new SKPoint(x, -tickY);
        var tickMax = new SKPoint(x, tickY);
        canvas.DrawLine(this.ChartToDevice(tickMin), this.ChartToDevice(tickMax), axisPaint);
    }

    // Draw the Y axis.
    // The inversion of above, basically the same.

1 Ответ

0 голосов
/ 30 января 2020

Я смог обнаружить свою проблему за достаточно времени. Я не правильно рассчитал смещение. this.ChartToDeviceMatrix.SetScaleTranslate(xScale, yScale, DeviceMin.X, DeviceMax.X);

Должно было быть:

this.ChartToDeviceMatrix.SetScaleTranslate(xScale, yScale, -ChartMin.X * xScale + DeviceMin.Y, -ChartMin.Y * yScale + DeviceMax.Y);

Метод окончательной матрицы был:

private SKMatrix ChartToDeviceMatrix, DeviceToChartMatrix;
private void ConfigureTransforms(SKPoint ChartMin, SKPoint ChartMax, SKPoint DeviceMin, SKPoint DeviceMax)
{
    this.ChartToDeviceMatrix = SKMatrix.MakeIdentity();
    float xScale = (DeviceMax.X - DeviceMin.X) / (ChartMax.X - ChartMin.X);
    float yScale = (DeviceMin.Y - DeviceMax.Y) / (ChartMax.Y - ChartMin.Y);
    float xOffset = -ChartMin.X * xScale + DeviceMin.X;
    float yOffset = -ChartMin.Y * yScale + DeviceMax.Y;

    this.ChartToDeviceMatrix.SetScaleTranslate(xScale, yScale, xOffset, yOffset);
    this.ChartToDeviceMatrix.TryInvert(out this.DeviceToChartMatrix);
}
...