図形言語解析

なんだか難しくてよくわからない図形言語を解析してゆくページ

オブジェクト

Frameオブジェクト
並行でない二つのベクトルで構成されており、そのベクトルを湧くとした座標平面を作る。
Painterオブジェクト
frameオブジェクトを受け取りそのframeオブジェクトで指定されている領域内で指定されている絵を描写する。
Segmentオブジェクト
描かれる線分情報を保持するオブジェクト。

関数名と動作

関数名
below (below wave wave)
beside (beside wave wave)
flip-vert (flip-vert wave)
right-split (right-split wave 1),(right-split wave 2),(right-split wave 3)
corner-split (corner-split wave 1),(corner-split wave 2),(corner-split wave 3)
square-limit (square-limit wave 1).(square-limit wave 2),(square-limit wave 3)
squash-inwards (squash-inwards wave)
shrink-to-upper-right (shrink-to-upper-right wave)
frame-coord-map before->after
flipped-pairs
transform-painter

実際やってみる

nagaさん(naga:gnuplotを使った図形言語)の方法を用いて体感しながらやってみる。
とりあえず、draw-lineを用いて実際に線を引いてみるnagaさんのページからコピーしてこのようなファイル(ファイル名draw.scmとでもしておく)を用意する
#!/usr/bin/env gosh

(define (make-vect x y)
  (cons x y))

(define (xcor-vect v)
  (car v))

(define (ycor-vect v)
  (cdr v))

(define (draw-line s-seg e-seg)
  (display "set arrow from ")
  (display (xcor-vect s-seg))
  (display ",")
  (display (ycor-vect s-seg))
  (display " to ")
  (display (xcor-vect e-seg))
  (display ",")
  (display (ycor-vect e-seg))      
  (display " nohead")
  (newline))

(draw-line (make-vect 0.3 0.5) (make-vect 0.1 0.5))
(draw-line (make-vect 0.9 0.6) (make-vect 0.6 0.4))

これを元に描写してみる
> ./draw.scm > segment.gp
> gnuplot plot.gp
すると、
このように実際に線が描写されることがわかる。

ここで重要なのは、
線を描くだけならSICPで書かれている関数はそれほどいらない。
ということである。まず、単純に絵を描くということと、図形言語として絵を描くということを分けて考えないと混乱する。

まず、draw-lineでいろいろ遊んでみよう。

より手軽に遊ぶ為上のプログラムを多少変更した以下のプログラムを用いる
#!/usr/bin/env gosh

(define (make-vect x y)
  (cons x y))

(define (xcor-vect v)
  (car v))

(define (ycor-vect v)
  (cdr v))

(define (make-frame origin edge1 edge2)
  (list origin edge1 edge2))

(define (put-x-y-coord seg)
  (let ((xcor (xcor-vect seg))
	(ycor (ycor-vect seg)))
    (for-each display (list xcor " " ycor "\n"))))

(define (draw-line s-seg e-seg)
  (put-x-y-coord s-seg)
  (put-x-y-coord e-seg)
  (newline))

(define (print str)
  (display str)
  (newline))

(define init-commands (list
			"set multiplot"		 ; 複数グラフを表示可能にする
			"set xrange [0:1]"	 ; 表示領域  0≦x,y≦1
			"set yrange [0:1]"
			"set size 0.721,1.0"	 ;  縦横を同じ長さに
			"unset border"		 ;  枠を表示しない
			"unset tics"		 ;  刻みを表示しない
			"unset key"		 ;  keyを表示しない
			"plot [0:1] 0 with dot"	 ;  y=0の線を0≦x≦1に目立たないように表示する
			"set style data line"
			"plot '-'"))

(for-each print init-commands) ;必要な設定
;;以下の部分に描写する手続きを記述。
(draw-line (make-vect 0.3 0.5) (make-vect 0.1 0.5))
(draw-line (make-vect 0.9 0.6) (make-vect 0.6 0.4))

使い方としてはファイル名をdrawline.scmとし、
> ./drawline.scm | gnuplot -persist
でOK

segment->painterを使ってみる

(define idframe (make-frame (make-vect 0.0 0.0) (make-vect 1.0 0.0) (make-vect 0.0 1.0)))
(define seglist (list (make-segment (make-vect 0.0 0.0) (make-vect 1.0 1.0))
                      (make-segment (make-vect 1.0 0.5) (make-vect 1.0 0.0))
                      (make-segment (make-vect 0.0 0.0) (make-vect 1.0 0.5))))

((segments->painter seglist) idframe)     
というようなものを実行してみる。(セグメントリストは適当なもの)
ここで用いたframeは正規ベクトルで構成されたありきたりなものであったので少し変更してみる。
(define idframe (make-frame (make-vect 0.0 0.0) (make-vect 1.0 0.0) (make-vect 0.0 1.0)))
     ↓
(define nextframe (make-frame (make-vect 0.0 0.0) (make-vect 0.8 0.1) (make-vect 0.5 0.3)))
結果


これはお世辞にもわかりやすいとはいえないので少しわかりやすくする。
なお、以下の説明においてnaoya_t氏のページにあるwaveおよびmake-pathを使う。(naoya_t氏に感謝)
http://sicp.naochan.com/memo.pl?p=wave
http://sicp.naochan.com/memo.pl?p=make-path

まずmake-pathを使ってフレームを表示させてみる。
(define idframe (make-frame (make-vect 0.0 0.0) (make-vect 1.0 0.0) (make-vect 0.0 1.0)))
(define exp-frame
  (make-path (make-vect 0.0 0.0)
             (make-vect 1.0 0.0)
             (make-vect 1.0 1.0)
             (make-vect 0.0 1.0) 
             (make-vect 0.0 0.0)))
として、
((segments->painter exp-frame) idframe)
を実行
これをフレームを変えることで変形させる。
(define transframe (make-frame (make-vect 0.0 0.0) (make-vect 0.8 0.2) (make-vect 0.2 0.8)))
((segments->painter exp-frame) transframe)
結果

さらにSICPに出てくるwaveの例を試してみる。
  • idframeの場合
実行コマンド
((segments->painter exp-idframe) idframe)    
(wave idframe) 
  • transframeの場合
実行コマンド
((segments->painter exp-idframe) transframe)    
(wave transframe) 

タグ:

+ タグ編集
  • タグ:
最終更新:2008年03月21日 00:35
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。