[cairo] Extracting The Scaling Component Of A Matrix

Behdad Esfahbod behdad.esfahbod at gmail.com
Mon Dec 14 03:20:58 PST 2015


On 15-12-13 11:15 PM, Lawrence D'Oliveiro wrote:
> On Sat, 12 Dec 2015 12:15:17 +0100, Behdad Esfahbod wrote:
> 
>> On 15-12-11 01:51 AM, Lawrence D'Oliveiro wrote:
>>
>>> I construct a matrix that implements just the scaling component of
>>> the CTM in the Cairo context “ctx”:
>>>
>>>     scaling = Matrix.scale(ctx.user_to_device_distance(Vector(1,
>>> 1)))  
>>
>> This wouldn't do what you think it does for general matrices.  Or
>> maybe I don't understand what you are trying to do.  Are you only
>> interested in non-skewed matrices?
> 
>     import sys
>     from qahirah import \
>         Matrix, \
>         Vector
> 
>     for \
>         mat \
>     in \
>         (
>             Matrix.scale(3),
>             Matrix.skew((0, 1)) * Matrix.scale(3),
>             Matrix.scale(3) * Matrix.skew((1, 0)),
>             Matrix.skew((1, 1)),
>             Matrix.skew((1, -1)) * Matrix.scale(3),
>             Matrix.scale(3) * Matrix.skew((-1, 1)),
>         ) \
>     :
>         sys.stdout.write \
>           (
>             "scaling part of {} = {}\n"
>             .format
>               (
>                 mat,
>                 mat.mapdelta(Vector(1, 1))
>               )
>           )
>     #end for
> 
>     ...
> 
>     scaling part of Matrix(3, 0, 0, 3, 0, 0) = Vector(3, 3)
>     scaling part of Matrix(3, 3, 0, 3, 0, 0) = Vector(3, 6)
>     scaling part of Matrix(3, 0, 3, 3, 0, 0) = Vector(6, 3)
>     scaling part of Matrix(1, 1, 1, 1, 0, 0) = Vector(2, 2)
>     scaling part of Matrix(3, -3, 3, 3, 0, 0) = Vector(6, 0)
>     scaling part of Matrix(3, 3, -3, 3, 0, 0) = Vector(0, 6)
> 
> Hmmm ...

Yeah... You have to define what exactly you want.  A 2D matrix like the ones
cairo uses can always be decomposed into a concatenation of the following
matrices:

  - transform
  - rotate
  - skew
  - scale

This has many useful properties, and you can derive those four transformations
from an arbitrary matrix easily.  Here's my derivation:

https://readable-email.org/list/www-style/topic/better-matrix-decomposition-for-animation

This also describes the benefits of such decompositions:

http://research.cs.wisc.edu/graphics/Courses/838-s2002/Papers/polar-decomp.pdf

If you transform a circle with a matrix, you get an ellipse.  If you are
interested in the major and minor axes of that ellipse, that's a Singular
Value Decomposition of the 2D matrix.  I've put code here for doing that:

https://github.com/behdad/cairo/blob/color-emoji/doc/tutorial/src/singular.c

Cheers,

behdad


More information about the cairo mailing list