アフィン変換

sample ps

数回前にやったpostscriptでの回転に付いて、分かったようで分からなかったので、少し探ってみる事にした。その過程で見つけた、面白い資料を挙げておく。

Graph Paper in Postscript

これ、無料のグラフ用紙ですって。コクヨさん、御免なさい。

C言語から呼び出すポストスクリプト描画法

ghostscriptは、C語から呼び出すライブラリィーが提供されていないようなので、C語で書くなら、postscrit語を出力する事になる。だったら、機動性が良いrubyとかで書くのがよさそう。

技術評論社で出している WEB+DB PRESS の次号特集は ruby3についてだぞ。python嫌いのオイラーは、たまに買ってもいいかも。

回転するぞ

肝はCTM

いよいよ本丸に迫ります。

図形の回転と移動 -アフィン変換-

アフィン変換なんてのが出て来た。これがキーになりそうだな。

図形の表現と座標系について

段々とgostscriptに近づいてきた。

座標変換(回転)について

concatなんてのが出て来た。これが統一理論かな。

PostScript言語 / 座標系

そして、遂に本丸へ到達した。

maximaで行列の記号解

行列の演算なんて超苦手なオイラーは、maximaに救いを求めてみます。

ghostscriptの心臓部であるCTMが下記のようだったとします。

[a b c d h v]

これを正式な行列で表現。

(%i7) R : matrix([a,b,h],[c,d,v],[0,0,1]);
                                  [ a  b  h ]
                                  [         ]
(%o7)                             [ c  d  v ]
                                  [         ]
                                  [ 0  0  1 ]
(%i8) R . matrix([x,y,1]);
                               [ b y + a x + h ]
                               [               ]
(%o8)                          [ d y + c x + v ]
                               [               ]
                               [       1       ]

そして、点(x,y)をワープと言うか変換します。これがアフィン変換なのね。

これ、記号的な表現。maximaでも、数値に置き換えてあげれば、ちゃんと数値で答えてくれるが、もう一つの専門家に依頼して、数値解を出してもらいましょう。

行列の専門家octave

入力が取っても簡単なのでお勧め。AIにも通じてる。

octave:5> a = [3,0 ; 0,0.5]
a =

   3.00000   0.00000
   0.00000   0.50000

octave:7> a * [2;1]
ans =

   6.00000
   0.50000

rubyでも行列する

rubyにもMatrixなクラスが有ったので、(無理して)使ってみた。

ob$ ruby -v
ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-openbsd6.8]
ob$ irb
irb(main):001:0> require 'matrix'
=> true
irb(main):002:0> R = Matrix[[3, 0], [0, 2]]
=> Matrix[[3, 0], [0, 2]]
irb(main):003:0> p = Matrix[[1], [1]]
=> Matrix[[1], [1]]
irb(main):004:0> R * p
=> Matrix[[3], [2]]

一応は使えるな。でも、醜いな。

irb(main):027:0> r.each_slice(r.column_size) {|row| puts row.inspect}
[3, 0]
[0, 2]
=> nil
irb(main):032:0> q.each {|val| puts val}
1
1

そんな時には、さっと整形するんだそうです。

gaucheにも行列有った

rubyにもmatrixが有るなら、scheme界のrubyことgaucheにも有るに違いない。

gosh> (use gauche.array)
gosh> (array-mul (array (shape 0 2 0 2) 1 0 0 1)
                 (array (shape 0 2 0 1) 3 2))
#,(<array> (0 2 0 1) 3 2)

shapeなんて言う変なリストを添付してarrayを作る約束になってる。2個1組で、インデックスを表すとな。最初は、エレメントのスタート・インデックス。後の奴は終了インデックス+1を指定する。

上の例だと、最初の配列は 2x2、後の配列は 2x1 とみなされる。結果は行列界のお約束で、2x1になる。何だか、配列を脳内加工して、行列に見立てているんだな。こんな考え方はnumpyでも使ってたな。

ghostscriptで見える化

いよいよ実戦です。

GS>(grid.ps)run
GS>grid
GS>300 300 org
GS>0 0 100 200 rectstroke
GS>45 rotate
GS>0 0 100 200 rectfill

gridは、数回前にやった目盛り用のやつ。原点を300,300に移動。左下を原点にした箱を書きます。幅は100で高さが200のやつ。rectfillを使うと中が塗りつぶされます。

次にrotateを使って、反時計方向に45度傾くように設定。これで次回からの描画は傾くはず。 そして、同じ設定で黒塗りの箱を描きます。見事に45度傾いた箱が出てきました。

アフィン変換

図形の鑑賞