# How do I compose these two matrices in SkiaSharp?

GBMember ✭✭✭

I am being driven nuts by what should be a dead simple bit of matrix maths.

I am drawing a simple graph using SkiaSharp. I have a SKPath, which describes the plot of the graph. I have simulated this in the code below by a silly bit of code that just produces 50 drawable points. To draw the graph, I wish to scale it horizontally according to a value that is updated when the user pinches the screen and I want to offset the graph by a fixed amount to line it up with the x=0 point on the screen.

In the code below, the first version of the code that does two separate transforms works fine. So I thought, for efficiency, I would combine the two matrices and do one single transform. I have tried all four combinations of pre- and post- concatenation and none of them stays overlaid on the first correct line. In other words, no matter how I compose the matrices, I cannot get the same result I get by applying the matrices separately.

What am I doing wrong?

``````SKCanvas canvas = null; // This is passed into the drawing function.

SKPaint pen = new SKPaint()
{
Style = SKPaintStyle.Stroke,
StrokeWidth = 1.0f,
Color = SKColor.Parse( "#B0FFDD00" )
};

float horizontalScale = 1.0f;
float x = 0.0f;
float y = 0.0f;

SKPath path = new SKPath();
path.MoveTo( x, y );
for( int i = 0; i < 50; ++i )
{
x = (float)( i * 10 );
y += ( i % 10 == 0 ) ? -5.0f : (float)i * 0.8f;
path.LineTo( x, y );
}

// This one works fine.
SKMatrix scaleMatrix1 = SKMatrix.MakeScale( horizontalScale, 1.0f );
path.Transform( scaleMatrix1 );
SKMatrix translationMatrix1 = SKMatrix.MakeTranslation( 50.0f, 0.0f );
path.Transform( translationMatrix1 );
canvas.DrawPath( path, pen );

// This does not work as expected.
SKMatrix scaleMatrix2 = SKMatrix.MakeScale( horizontalScale, 1.0f );
SKMatrix translationMatrix2 = SKMatrix.MakeTranslation( 50.0f, 0.0f );
SKMatrix.PreConcat( ref translationMatrix2, scaleMatrix2 );
path.Transform( translationMatrix2 );
canvas.DrawPath( path, pen );

// Neither does this.
SKMatrix scaleMatrix3 = SKMatrix.MakeScale( horizontalScale, 1.0f );
SKMatrix translationMatrix3 = SKMatrix.MakeTranslation( 50.0f, 0.0f );
SKMatrix.PostConcat( ref translationMatrix3, scaleMatrix3 );
path.Transform( translationMatrix3 );
canvas.DrawPath( path, pen );

// Neither does this.
SKMatrix scaleMatrix4 = SKMatrix.MakeScale( horizontalScale, 1.0f );
SKMatrix translationMatrix4 = SKMatrix.MakeTranslation( 50.0f, 0.0f );
SKMatrix.PreConcat( ref scaleMatrix4, translationMatrix4 );
path.Transform( scaleMatrix4 );
canvas.DrawPath( path, pen );

// And neither does this.
SKMatrix scaleMatrix5 = SKMatrix.MakeScale( horizontalScale, 1.0f );
SKMatrix translationMatrix5 = SKMatrix.MakeTranslation( 50.0f, 0.0f );
SKMatrix.PostConcat( ref scaleMatrix5, translationMatrix5 );
path.Transform( scaleMatrix5 );
canvas.DrawPath( path, pen );
``````
Tagged:

• GB ✭✭✭

I must have been doing something stupid. This now works as expected. The two code fragments shown below both perform exactly the same compound transformation as the code above where I perform the scale and translate in two separate steps.

So these code fragments both work fine (though personally I find the former to be more intuitive):

``````SKMatrix scaleMatrixA = SKMatrix.MakeScale( horizontalScale, 1.0f );
SKMatrix transformMatrixA = SKMatrix.MakeTranslation( 20.0f, 0.0f );
SKMatrix.PostConcat( ref scaleMatrixA, transformMatrixA );
plotA.Transform( scaleMatrixA );
canvas.DrawPath( plotA, penA );

SKMatrix scaleMatrixB = SKMatrix.MakeScale( horizontalScale, 1.0f );
SKMatrix transformMatrixB = SKMatrix.MakeTranslation( 20.0f, 0.0f );
SKMatrix.PreConcat( ref transformMatrixB, scaleMatrixB );
plotB.Transform( transformMatrixB );
canvas.DrawPath( plotB, penB );
``````

Thank you to anyone who has taken the time to look at this problem.

Kind wishes ~ Patrick

• GBMember ✭✭✭

I must have been doing something stupid. This now works as expected. The two code fragments shown below both perform exactly the same compound transformation as the code above where I perform the scale and translate in two separate steps.

So these code fragments both work fine (though personally I find the former to be more intuitive):

``````SKMatrix scaleMatrixA = SKMatrix.MakeScale( horizontalScale, 1.0f );
SKMatrix transformMatrixA = SKMatrix.MakeTranslation( 20.0f, 0.0f );
SKMatrix.PostConcat( ref scaleMatrixA, transformMatrixA );
plotA.Transform( scaleMatrixA );
canvas.DrawPath( plotA, penA );

SKMatrix scaleMatrixB = SKMatrix.MakeScale( horizontalScale, 1.0f );
SKMatrix transformMatrixB = SKMatrix.MakeTranslation( 20.0f, 0.0f );
SKMatrix.PreConcat( ref transformMatrixB, scaleMatrixB );
plotB.Transform( transformMatrixB );
canvas.DrawPath( plotB, penB );
``````

Thank you to anyone who has taken the time to look at this problem.

Kind wishes ~ Patrick

• GBMember ✭✭✭