/pliant/math/transform.pli
 
 1  submodule "point.pli" 
 2  submodule "vector.pli" 
 3  submodule "functions.pli" 
 4  module "matrix.pli" 
 5   
 6  doc 
 7    [If zero is a bottom left, then rotate is counterclockwise, just as in PostScript coordinate system.] ; eol 
 8    [If zero is a top left, than rotate is clockwise] 
 9   
 10  public 
 11    constant transform_identity 0 
 12    constant transform_translate 1 
 13    constant transform_scale 2 
 14    constant transform_rotate 3 
 15   
 16    type Transform2 
 17      field Float xx xy xt 
 18      field Float yx yy yt 
 19      field Int level 
 20   
 21   
 22  method t compute 
 23    arg_rw Transform2 t 
 24    if t:xy<>or t:yx<>0 
 25      level := transform_rotate 
 26    eif t:xx<>or t:yy<>1 
 27      level := transform_scale 
 28    eif t:xt<>or t:yt<>0 
 29      level := transform_translate 
 30    else 
 31      level := transform_identity 
 32   
 33   
 34  function transform -> t 
 35    arg Transform2 t 
 36    xx := 1 
 37    xy := 0 
 38    xt := 0 
 39    yx := 0 
 40    yy := 1 
 41    yt := 0 
 42    level := transform_identity 
 43   
 44  function transform tx ty sx sy rx ry -> t 
 45    arg Float tx ty sx sy rx ry ; arg Transform2 t 
 46    if (rx<>or ry<>0) 
 47      xx := sx*cos:rx 
 48      xy := -sy*sin:ry 
 49      xt := tx 
 50      yx := sx*sin:rx 
 51      yy := sy*cos:ry 
 52      yt := ty 
 53    else 
 54      xx := sx 
 55      xy := 0 
 56      xt := tx 
 57      yx := 0 
 58      yy := sy 
 59      yt := ty 
 60    compute 
 61   
 62   
 63  method t matrix -> m 
 64    arg Transform2 t ; arg Matrix m 
 65    resize 3 3 
 66    0 0 := xx 
 67    0 1 := xy 
 68    0 2 := xt 
 69    1 0 := yx 
 70    1 1 := yy 
 71    1 2 := yt 
 72    2 0 := 0 
 73    2 1 := 0 
 74    2 2 := 1 
 75   
 76  function transform m -> t 
 77    arg Matrix m ; arg Transform2 t 
 78    check m:nb_lines=and m:nb_columns=3 
 79    xx := 0 0 
 80    xy := 0 1 
 81    xt := 0 2 
 82    yx := 1 0 
 83    yy := 1 1 
 84    yt := 1 2 
 85    compute 
 86   
 87  function compose t1 t2 -> t 
 88    arg Transform2 t1 t2 t 
 89    if t1:level<=transform_translate and t2:level<=transform_translate 
 90      xx := 1 
 91      xy := 0 
 92      xt := t1:xt+t2:xt 
 93      yx := 0 
 94      yy := 1 
 95      yt := t1:yt+t2:yt 
 96      level := shunt t:xt<>or t:yt<>0 transform_translate transform_identity 
 97    else 
 98      := transform t2:matrix*t1:matrix 
 99   
 100  function compose t1 t2 t3 -> t 
 101    arg Transform2 t1 t2 t3 t 
 102    := transform t3:matrix*t2:matrix*t1:matrix 
 103   
 104  function reverse t -> inv 
 105    arg Transform2 inv 
 106    if t:level<=transform_translate 
 107      inv := t 
 108      inv xt := -(xt) 
 109      inv yt := -(yt) 
 110    else   
 111      inv := transform t:matrix^(-1) 
 112   
 113   
 114  method t '' p -> q 
 115    arg Transform2 t ; arg Point2 q 
 116    if t:level=transform_identity 
 117      := p 
 118    eif t:level=transform_translate 
 119      := point p:x+t:xt p:y+t:yt 
 120    eif t:level=transform_scale 
 121      := point p:x*t:xx+t:xt p:y*t:yy+t:yt 
 122    else 
 123      := point p:x*t:xx+p:y*t:xy+t:xt p:x*t:yx+p:y*t:yy+t:yt 
 124   
 125  method t '' v -> w 
 126    arg Transform2 t ; arg Vector2 w 
 127    if t:level<=transform_translate 
 128      := v 
 129    eif t:level=transform_scale 
 130      := vector v:x*t:xx v:y*t:yy 
 131    else 
 132      := vector v:x*t:xx+v:y*t:xy v:x*t:yx+v:y*t:yy 
 133   
 134   
 135  export Transform2 '. compute' transform '' '. matrix' compose reverse