Hatena::ブログ(Diary)

分室の分室 このページをアンテナに追加

2016-11-01 Tue

グルーピング・ストローク(仮)

【589】


グルーピング・ストローク(仮)…という新概念の導入を検討中:

 今まで『自作 Script-Fu』という呼び名で適当に話を濁してきたが、そろそろ『script-fu-auto-drawer』『auto-drawer』という名前を出しても良い頃合いになってきた、…そんな気がする。

 今回は auto-drawer の描画コマンドの話。今までは stroke と pset を別コマンドとして 2つの手続に分けて記述していた。が、先日作った pieces-of を使うことで、pset コマンドと stroke コマンドを区別せずに実行できる。で、座標データ中の "p" はグループ化(1つの図形の区切り)の優先順位最上位分割点とする。

 pieces-of は、先日に紹介したライブラリ・ファイル r6rs-and-subspecies.scm に収録したちょっとした手続だったが、グルーピング・ストローク(仮)に最適化した形に作り直すことにしたので、そのソースを再掲。↓

;; 初版:2016.09.28 Wed 18:18
;; ******************************************************************
;; pieces-of            (フラットなリストを2重リストに分割(独自仕様))
;; ******************************************************************
;; 主な目的:リストをコンソール画面に合わせて分割表示する時などに使用
;;  元ネタ:http://d.hatena.ne.jp/foussin/20160928/1475060731
;; (Pieces of Eight / Styx  を聴きながらこれを書く… I'm O.K.)
;;
;; 書式:(pieces-of lis n)  →  (読み下すと)リストの断片たち…(?)
;;
;; 改版:2016.10.30 Sun 20:46(n に 0 を指定→引数を2重リストで返す)
;;       script-fu-auto-drawer の『グルーピング・ストローク(仮)』に
;;       対応するための改版。ループ中で 1ストロークごとの座標データ
;;       を car で取り出して描画する仕組み。戻り値は必ず2重リストの
;;       方が何かと都合がいい…というご都合主義的な理由での改版。
;
;実行例(Script-Fuコンソール):
;  > (pieces-of '(1 2 3 4 5 6 7) 2)
;  ((1 2) (3 4) (5 6) (7))
;  > (pieces-of '(1 2 3 4 5 6 7 8 9 10 11 12) 3)
;  ((1 2 3) (4 5 6) (7 8 9) (10 11 12))
;  > (pieces-of '(1 2 3 4 5 6 7 8 9 10 11 12) 4)
;  ((1 2 3 4) (5 6 7 8) (9 10 11 12))
;  > (pieces-of '(1 2 3 4 5 6 7 8 9 10 11 12) 5)
;  ((1 2 3 4 5) (6 7 8 9 10) (11 12))
;
;  > (pieces-of '(1 2 3 4 5 6 7) 1)
;  ((1) (2) (3) (4) (5) (6) (7))
;  > (pieces-of '(1 2 3 4 5 6 7) 2.0)   ;整数なら OK.
;  ((1 2) (3 4) (5 6) (7))
;
;  > (pieces-of '(1 2 3 4 5 6 7) 0)     ;改版後の挙動(以前はエラーだった)
;  ((1 2 3 4 5 6 7))
;
(define (pieces-of lis n)
  (if (zero? n)
    (cons lis '())
    (let loop ((i 0) (ls lis) (group '()) (new '()))
      (if (null? ls)
        (reverse (cons (reverse group) new))
        (if (and (zero? (modulo i n)) (> i 0))
          (loop (+ i 1) (cdr ls)
                (cons (car ls) '()) (cons (reverse group) new))
          (loop (+ i 1) (cdr ls)
                (cons (car ls) group) new))))))

dropboxhttps://www.dropbox.com/s/vew5ds5v5n2va7b/r6rs-and-subspecies.scm?dl=0


 さて、『グルーピング・ストローク』とは、描画ループの実行直前に座標データのグループ化を再編する機能である。まずはメニュー用のリスト(とレジスター部)を作る。今回、新たに追加するのは次の記述…

;; SF-OPTION 用 "コマンド(グルーピング・ストローク)" メニュー
(define my-and-our-grouping-stroke-menu
  '("0.stroke(一筆書)"  "1.pset(点描)"  "2.破線(2点)stroke"
    "3.破線(3点)stroke" "4.ユーザー定義'(many shift)を使う"))

(script-fu-register
  ;…中略…
  SF-OPTION "コマンド(グルーピング・ストローク)"    ;command-ID
            my-and-our-grouping-stroke-menu
  SF-VALUE  "ユーザー定義'(many shift)" "'(4 0)"    ;grpStroke-usrDef
  SF-STRING "備考:'(many shift) の意味→ "         ;noticeUsrDef-1
            "'(グループ化する座標点の数 右シフト数)"
  ;…中略…
  );end register

 実は、コマンドメニューの "0.stroke(一筆書)" 〜 "3.破線(3点)stroke" の先頭の番号は、さっき修正した pieces-of の引数 n とスマートに対応している。端折りすぎて意味が分かりにくいと思うが、詳しくは後ほど、実行例を交えて説明するつもり…。


 今回のソースは前回記事の最後に書いたとおり『座標で往復運動を表現する』ものなんだけど、その記述は『グルーピング・ストローク』とも非常に相性がいいので、なんかダブル・ミーニングな記事になって読者を混乱させるかもしれない…。

;; -*- encoding : utf-8 -*-
;; example-reciprocating-motion.scm 【最新:2016.10.31 Mon 23:06】
;; 壁で跳ね返る等速運動のボール(reciprocating-motion-like-iota 使用例)

;;【メニュー表示用リスト(トップレベル定義)】
;ブラシ名
(define my-and-our-usable-brushes-list
  (cons "現在の設定(GUI画面)を使う" (cadr (gimp-brushes-get-list ".*"))))
;ブラシサイズ(初期サイズ):
;初期サイズ(動的初期値)→ブラシ動的サイズの初期サイズを兼ねる
(define my-and-our-brush-size-list '(1 2 3 4 6 8 10 12 14 16 18 20 25 30))
(define my-and-our-brush-size-menu-list
  (cons "現在の設定(GUI画面)を使う"
    (map number->string my-and-our-brush-size-list) ))
;ブラシ動的サイズ(単位→ピクセル):
;   ランダムサイズ………………の範囲:1〜30
;   増減サイズ(グラディエント)の範囲:未規定(ユーザー定義)
;   増加グラディエントが上限値超過になると減衰に転じる
;   減衰グラディエントが下限値未満になると増加に転じる
(define my-and-our-brush-size-dynamics-menu-list
  '( "0.なし(サイズ固定)"
     "1.ランダムサイズ(小:01-10)"  "2.ランダムサイズ(中:11-20)"
     "3.ランダムサイズ(大:21-30)"  "4.ランダムサイズ(全:01-20)"
     "5.増減サイズを使う(次項ユーザー定義)" ))
;コマンド(グルーピング・ストローク)
(define my-and-our-grouping-stroke-menu
  '( "0.stroke(一筆書)"  "1.pset(点描)"  "2.破線(2点)stroke"
     "3.破線(3点)stroke" "4.ユーザー定義'(many shift)を使う" ))
(script-fu-register
  "example-reciprocating-motion"                      ;1 func name
  "<Image>/File/Create/壁で跳ね返る等速運動のボール"  ;2 menu label
  "壁で跳ね返るボール(Test Grouping Stroke)"          ;3 description
  "foussin(japanese)"                                 ;4 author?
  "d.hatena.ne.jp/foussin/archive?word=*[script-fu]"  ;5 copyright notice
  "2016.10.31 Mon 21:30(初版日時)"                    ;6 date created
  ""                                                  ;7 image type
  SF-OPTION "コマンド(グルーピング・ストローク)"        ;command-ID
            my-and-our-grouping-stroke-menu
  SF-VALUE  "ユーザー定義'(many shift)" "'(4 0)"        ;groupStrokeArgs
  SF-STRING "備考:'(many shift) の意味→ "             ;notice-1
            "'(グループ化する座標点の数 右シフト数)"
  SF-OPTION "ブラシ名" my-and-our-usable-brushes-list   ;brush-ID
  SF-OPTION "ブラシサイズ(初期サイズ)"                  ;size-ID
            my-and-our-brush-size-menu-list
  SF-OPTION "ブラシ動的サイズ"                          ;dynamics-ID
            my-and-our-brush-size-dynamics-menu-list
  SF-VALUE  "増減サイズ '(step lower upper)" "'(2 0 16)" ;gradientSizeArgs
  SF-STRING "備考:'(step lower upper) の意味→ "        ;notice-2
            "'(初期ステップ 下限値 上限値)"             );end register

(define (example-reciprocating-motion  command-ID  groupStrokeArgs
  notice-1 brush-ID size-ID dynamics-ID gradientSizeArgs notice-2)
  (let* (
      (image-width 555) (image-height 200)  ;イメージサイズ
      (Image                                ;新規イメージ作成
        (car (gimp-image-new image-width image-height RGB)))
      (Layer                    ;イメージと同サイズの前景レイヤを作成
        (car (gimp-layer-new    ;RGBA-IMAGE→アルファチャンネルも追加
            Image image-width image-height
            RGBA-IMAGE "layer foreground" 100 NORMAL)))
      ;↓イメージサイズ内で跳ね返る等速運動のボール(座標データ):
      ;  (reciprocating-motion-like-iota 使用例)
      (count 70) (start 0) (step-x 15) (step-y 10)
      (x (reciprocating-motion-like-iota count start step-x image-width))
      (y (reciprocating-motion-like-iota count start step-y image-height))
      (lis-reciprocating-motion (riffle-shuffle x y))
      (group-many (car groupStrokeArgs))
      (group-shift (cadr groupStrokeArgs))
      (lis-xy-complete-grouping-stroke  ;グルーピング・ストローク(本体)
        (cond
          ((< command-ID 4)
            (pieces-of lis-reciprocating-motion (* command-ID 2)) )
          ((zero? group-shift)
            (pieces-of lis-reciprocating-motion (* group-many 2)) )
          (else
            (cons (take lis-reciprocating-motion (* group-shift 2))
                  (pieces-of
                    (drop lis-reciprocating-motion (* group-shift 2))
                    (* group-many 2) )))))
      (brush-name
        (if (zero? brush-ID)
          (car (gimp-context-get-brush))
          (nth brush-ID my-and-our-usable-brushes-list) ))
      (brush-size                       ;動的サイズの初期サイズを兼用
        (if (zero? size-ID)
          (car (gimp-context-get-brush-size))
          (nth size-ID my-and-our-brush-size-list) ))
      (step  (car gradientSizeArgs))    ;増減サイズ 初期ステップ
      (lower (cadr gradientSizeArgs))   ;増減サイズ 下限値
      (upper (caddr gradientSizeArgs))  ;増減サイズ 上限値
      (dyna-size-flag #f)   ;ランダムサイズ・増減サイズ 共用フラグ
      (dyna-size            ;ブラシ動的サイズ(本体)
        (lambda (id)
          (cond
            ;ループ 1回目は初期値を使う:ランダムサイズ
            ((and (boolean? dyna-size-flag) (< id 5))
              (begin (set! dyna-size-flag 1) brush-size) )
            ;ループ 1回目は初期値を使う:増減サイズ
            ((and (boolean? dyna-size-flag) (= id 5))
              (begin (set! dyna-size-flag 1)
                (cadr (add-to-recipro-motion 0 brush-size step 1)) ))
            ;ループ 2回目以降:ランダムサイズ
            ((= id 1) (+ (random 10)  1))   ;(小:01-10)
            ((= id 2) (+ (random 10) 11))   ;(中:11-20)
            ((= id 3) (+ (random 10) 21))   ;(大:21-30)
            ((= id 4) (+ (random 20)  1))   ;(全:01-20)
            ;ループ 2回目以降:増減サイズ
            ((= id 5) (cadr (reciprocating-motion 0 lower upper)))
            ;サイズ固定(= id 0):
            (else brush-size) ))) );end bind
    ; --- Gimp プロシージャ実行(副作用) ---
    ; gimp-context-云々…実行時のカレント(アクティブ)設定
    (gimp-context-push)                           ;環境退避
    (gimp-context-set-antialias TRUE)             ;アンチエイリアス有効
    (gimp-context-set-brush brush-name)           ;アクティブ・ブラシ
    (gimp-context-set-foreground "black")         ;描画色
    (gimp-context-set-background '(220 220 220))  ;背景色(light-gray)
    ; 前景レイヤを画像に配置(0 が最前景となる)
    (gimp-image-add-layer Image Layer 0)
    ; 前景レイヤを背景色で塗り潰す:画像のゴミを一掃(VRAMクリア的な…)
    (gimp-drawable-fill Layer BACKGROUND-FILL)

    ; 描画本体(ループ)
    (let loop ((vec (list->vector (car lis-xy-complete-grouping-stroke)))
               (lis (cdr lis-xy-complete-grouping-stroke)))
      (gimp-context-set-brush-size (dyna-size dynamics-ID))
      (gimp-paintbrush-default Layer (vector-length vec) vec)
      (if (null? lis) #t (loop (list->vector (car lis)) (cdr lis))) )

    (gimp-context-pop)            ;環境復元
    (gimp-display-new Image)      ;画像表示
    (gimp-image-clean-all Image)  ;[Ctrl-W] で破棄(メッセージ表示しない)
    ;戻り値(画像、レイヤ、座標リスト)
    (list Image Layer lis-xy-complete-grouping-stroke) ))

dropbox:https://www.dropbox.com/s/drug24hmz2jp90c/example-reciprocating-motion.scm?dl=0

 さっそく実行してみる。

f:id:foussin:20161031235923p:image
01-ここから起動

f:id:foussin:20161031235924p:image
02-メニュー画面(デフォルト)

f:id:foussin:20161031235925p:image
03-とりあえずこれで実行(stroke)

f:id:foussin:20161031235926p:image
04-stroke実行結果。stroke というのは、座標点を線で繋いで一筆書きで描画する『描画コマンド』のこと。

f:id:foussin:20161031235927p:image
05-コマンドのボックスをクリック。すると stroke 以外にこんな描画コマンドを登録している。実行してみよう。↓

f:id:foussin:20161031235928p:image
06-『1.pset(点描)』。左上から発射されたボールがイメージサイズの壁で跳ね返る様子が見えてきたと思う。reciprocating-motion 手続があれば、こんな描画が簡単にできる。

f:id:foussin:20161031235929p:image
07-『2.破線(2点)stroke』

f:id:foussin:20161101000333p:image
08-『3.破線(3点)stroke』

f:id:foussin:20161101000334p:image
09-『4.ユーザー定義'(many shift)を使う』のメニュー

 最後の『4.ユーザー定義'(many shift)を使う』というのは、ちょっと説明が難しい。とりあえず上記の設定で実行してみる(ブラシ名、ブラシサイズを変更)。↓

f:id:foussin:20161101000335p:image
10-『4.ユーザー定義実行結果』はこうなる。'(4 0) の 4 は『4つの点を 1つのストロークとして繋げる』という意味で、
  '(0 0) にすると『0.stroke(一筆書)』と同じになる。
  '(1 0) にすると『1.pset(点描)』と同じになる。
  '(2 0) にすると『2.破線(2点)stroke』と同じになる…と、そういう仕組み。

 で、'(4 0) の 0 の方は… GIFアニメにすると分かり易い。次の画像の左上の変化に注目してほしい。↓

f:id:foussin:20161101000336g:image
11-『4.ユーザー定義のshiftの意味』.gif

 文章では上手く説明しなかったが、なんとなく shift の意味が理解できると思う。ついでに、前回にやった『ブラシ動的サイズ』も使ってみよう。↓

f:id:foussin:20161101000337p:image
12-ランダムサイズを適用してみる

f:id:foussin:20161101000338p:image
13-増減サイズも適用してみる

…まあ、こんなところで。…こんな感じで、自作 Script-Fu (script-fu-auto-drawer) のバージョンアップを進めていく。これからしばらくの間、ダイアリーの更新が滞りがちになると思う。。。

2016-10-28 Fri

増加・減衰を繰り返すグラディエント部品の例(ブラシ動的サイズ)

【588】


 先日の『往復運動表現プロシージャ』の使用例をここらで…。

;; -*- encoding : utf-8 -*-
;; ****************** test-dyna-size-for-brushes.scm *****************
;; ブツ切りノコギリ波 → ブラシ動的サイズ(random or gradient)で描画

;;【メニュー表示用リスト(トップレベル定義)】
;ブラシ名
(define my-and-our-usable-brushes-list
  (cons "現在の設定(GUI画面)を使う" (cadr (gimp-brushes-get-list ".*"))))
;ブラシサイズ(初期サイズ):
;初期サイズ(動的初期値)→ブラシ動的サイズの初期サイズ(start)を兼ねる
(define my-and-our-brush-size-list
  '(1 2 3 4 6 8 10 12 14 16 18 20 25 30 35 40))
(define my-and-our-brush-size-menu-list
  (cons "現在の設定(GUI画面)を使う"
    (map number->string my-and-our-brush-size-list) ))
;ブラシ動的サイズ(単位→ピクセル):
;   ランダムサイズの範囲            :0〜40
;   増減サイズ(グラディエント)の範囲:未規定(ユーザー定義)
;   増加グラディエントが上限値超過になると減衰に転じる
;   減衰グラディエントが下限値未満になると増加に転じる
(define my-and-our-brush-size-dynamics-menu-list
  '( "00.なし(サイズ固定)"
     "01.ランダムサイズ(小:01-20)"  "02.ランダムサイズ(中:11-30)"
     "03.ランダムサイズ(大:21-40)"  "04.ランダムサイズ(全:01-40)"
     "05.増減サイズを使う(次項ユーザー定義)" ))

(define (test-dyna-size-for-brushes
    brush-ID size-ID dynamics-ID gradientSizeArgs notice)
  (let* (
      (image-width 540)       ;イメージサイズ
      (image-height 200)
      ;↓座標データ:ブツ切り(?)ノコギリ波形図を作る
      (base-x '( 20 40  40))  ;x基本形(x > 520 まで +20 を繰り返す)
      (base-y '(180 20 180))  ;y基本形(x座標の加算が続く限りコピー)
      (lis-sawtooth-wave
        (let loop ((bx base-x) (a '()))
          (if (< (- image-width 20) (cadr bx))
            (reverse a)
            (loop (map (lambda (x) (+ 20 x)) bx)
                  (cons (riffle-shuffle bx base-y) a) ))))
      (brush-name
        (if (zero? brush-ID)
          (car (gimp-context-get-brush))
          (nth brush-ID my-and-our-usable-brushes-list) ))
      (brush-size
        (if (zero? size-ID)
          (car (gimp-context-get-brush-size))
          (nth size-ID my-and-our-brush-size-list) ))
      (start brush-size)                ;動的サイズ 初期サイズ
      (step  (car gradientSizeArgs))    ;増減サイズ 初期ステップ
      (lower (cadr gradientSizeArgs))   ;増減サイズ 下限値
      (upper (caddr gradientSizeArgs))  ;増減サイズ 上限値
      (dyna-size-flag #f)   ;ランダムサイズ・増減サイズ 共用フラグ
      (dyna-size            ;ブラシ動的サイズ(本体)
        (lambda (id)
          (cond
            ;ループ 1回目は初期値を使う:ランダムサイズ
            ((and (boolean? dyna-size-flag) (< id 5))
              (begin (set! dyna-size-flag 1) start))
            ;ループ 1回目は初期値を使う:増減サイズ
            ((and (boolean? dyna-size-flag) (= id 5))
              (begin
                (set! dyna-size-flag 1)
                (add-to-recipro-motion 0 start step 1) start))
            ;ループ 2回目以降:ランダムサイズ
            ((= id 1) (+ (random 20)  1))
            ((= id 2) (+ (random 20) 11))
            ((= id 3) (+ (random 20) 21))
            ((= id 4) (+ (random 40)  1))
            ;ループ 2回目以降:増減サイズ
            ((= id 5)
              (begin
                (reciprocating-motion 0 lower upper)
                (recipro-value 0)))
            ;サイズ固定(= id 0):
            (else brush-size) )))
      (Image                    ;新規イメージ作成
        (car (gimp-image-new image-width image-height RGB)))
      (Layer                    ;イメージと同サイズの前景レイヤを作成
        (car (gimp-layer-new    ;RGBA-IMAGE→アルファチャンネルも追加
            Image image-width image-height
            RGBA-IMAGE "layer foreground" 100 NORMAL))) );end bind

    ; --- Gimp プロシージャ実行(副作用) ---
    ; gimp-context-云々…実行時のカレント(アクティブ)設定
    (gimp-context-push)                           ;環境退避
    (gimp-context-set-brush brush-name)           ;アクティブ・ブラシ
    (gimp-context-set-antialias TRUE)             ;アンチエイリアス有効
    (gimp-context-set-foreground "black")         ;描画色
    (gimp-context-set-background '(220 220 220))  ;背景色(light-gray)
    ; 前景レイヤを画像に配置(0 が最前景となる)
    (gimp-image-add-layer Image Layer 0)
    ; 前景レイヤを背景色で塗り潰す:画像のゴミを一掃(VRAMクリア的な…)
    (gimp-drawable-fill Layer BACKGROUND-FILL)

    ; 描画本体(ループ)
    (let loop ((vec (list->vector (car lis-sawtooth-wave)))
               (lis (cdr lis-sawtooth-wave)))
      (gimp-context-set-brush-size (dyna-size dynamics-ID))
      (gimp-paintbrush-default Layer (vector-length vec) vec)
      (if (null? lis)
        #t
        (loop (list->vector (car lis)) (cdr lis)) ))

    (gimp-context-pop)            ;環境復元
    (gimp-display-new Image)      ;画像表示
    (gimp-image-clean-all Image)  ;[Ctrl-W] で破棄(メッセージ表示しない)
    ;戻り値(画像、レイヤ、座標データ)
    (list Image Layer lis-sawtooth-wave) ))

(script-fu-register
  "test-dyna-size-for-brushes"                        ;1 func name
  "<Image>/File/Create/ブラシ動的サイズのテスト"      ;2 menu label
  "ブツ切りノコギリ波(?)図形→ ブラシ動的サイズ描画"  ;3 description
  "foussin(japanese)"                                 ;4 author?
  "d.hatena.ne.jp/foussin/archive?word=*[script-fu]"  ;5 copyright notice
  "2016.10.27 Thu 20:59"                              ;6 date created
  ""                                                  ;7 image type
  SF-OPTION "ブラシ名" my-and-our-usable-brushes-list ;brush-ID
  SF-OPTION "ブラシサイズ(初期サイズ)"                ;size-ID
            my-and-our-brush-size-menu-list
  SF-OPTION "ブラシ動的サイズ"                        ;dynamics-ID
            my-and-our-brush-size-dynamics-menu-list
  SF-VALUE  "増減サイズ '(step lower upper)" "'(2 1 10)" ;gradientSizeArgs
  SF-STRING "備考:'(step lower upper) の"               ;notice
            "意味→ '(初期ステップ 下限値 上限値)"
  )

 全部で 127行ある。トップレベル部、バインド部、レジスター部、座標生成、副作用、本体…ひっくるめての 127行なので、まあまあコンパクトと言えると思う。分かり易く明示するために若干くどい記述もしているし。

 とは言え、コピペで保存するのも面倒くさそうなので、これも dropbox から DL できるようにしてみた。↓

dropbox:https://www.dropbox.com/s/dszxd421ifi66n0/test-dyna-size-for-brushes.scm?dl=0

 このコードでは、前回紹介した『r6rs-and-subspecies.scm』に収録したプロシージャ riffle-shuffle、往復運動表現ジェネレータ、などを使っているので、実際に動作させるにはそれらも必要となります。↓

dropbox:https://www.dropbox.com/s/vew5ds5v5n2va7b/r6rs-and-subspecies.scm?dl=0


実行風景:

f:id:foussin:20161028001302j:image
01-スクリプト起動.jpg
 スクリプトパスにファイルを放り込んで GIMP を起動したら、ここに表示されてる『ブラシ動的サイズのテスト』をクリックして実行開始。

f:id:foussin:20161028001303j:image
02-メニュー画面.png
 メニューの初期画面。『現在の設定(GUI画面)を使う』とは、この矢印の設定のこと。

f:id:foussin:20161028001304p:image
03-ブラシ名ボックスをクリック.png
 使用可能なブラシ名のリストがズラッと表示される。このリストはユーザー次第で変わってくるので同じブラシ名が表示されるとは限らない。

f:id:foussin:20161028001305p:image
04-ブラシサイズ(初期サイズ)をクリック.png
 すると、こんな感じでサイズが選択できる。現在の設定(20.0)では太すぎるので、今回は 2(ピクセル)を選択しておく。

f:id:foussin:20161028001306p:image
05-ブラシ動的サイズをクリック.png
 今はデフォルトの『00.なし(サイズ固定)』を選択し、実行。すると……

f:id:foussin:20161028001307p:image
06-ノコギリ波の図形.png …こうなる。さらに…

f:id:foussin:20161028001308p:image
07-ランダムサイズの描画例.png 線がランダムに太くなったり細くなったりする。

f:id:foussin:20161028001309p:image
08-増減サイズの描画例.png 線が連続的に、次第に太くなったり細くなったりする。バネの疎密波のような描画になる。


 今回はこんなところで。次回は座標データに『増加・減衰』を適用する例を紹介する予定(これは相当オモシロイので期待してね)。

2016-10-24 Mon

Script-Fu 用 汎用手続ライブラリ・ファイル(r5rs 以外の便利関数)

【587】

 前回の『往復運動表現プロシージャ』の使用例をここらで試したいところだが、ぐっと堪えて…今まで作りためた汎用手続をファイルにまとめたので dropbox で公開してみる(ホームページが【工事中】頓挫状態なので)。

dropbox:https://www.dropbox.com/s/vew5ds5v5n2va7b/r6rs-and-subspecies.scm?dl=0

ファイル名:r6rs-and-subspecies.scm (文字コード utf-8、50 KB)
内容はこんな風(コメントより抜粋)。↓

;;; vector-map,  vector-for-each    (r6rs,r7rs 準拠(たぶん))
;;; vector-null?                    (独自仕様?)
;;; vector-append,  vector-swap!    (srfi-43 準拠(たぶん))
;;; take,  drop,  remove            (srfi-1  準拠(たぶん))
;;;
;;; vector-iota,  cons-iota,  cons-iota-tr,  iota-like-for,
;;; serial-number-int               (srfi-1 iota の亜種(独自仕様))
;;;
;;; sort, merge(リスト版)(参考図書『プログラミング言語 SCHEME』の写経)
;;;
;;; vector-merge-sort!,  vector-index-sort
;;;      (連動ソート対応:引数順番を sort, merge に合わせた(独自仕様))
;;;
;;; 往復運動(レシプロ運動)をリストで表現   (習作:往復運動表現 iota風)
;;; reciprocating-motion-like-iota      (srfi-1 iota の変種(独自仕様))
;;;
;;; 往復運動表現ジェネレータ(独自仕様)
;;; 書式1:add-to-recipro-motion                (初期設定と要素の追加)
;;; 書式2:reciprocating-motion             (ループ中から毎回呼び出す)
;;; 書式3:clear-reciprocating-motion     (ベクタを初期状態 #f に戻す)
;;;
;;; ------------------------------------------------------------------
;;; 以降は動作検証用:Script-Fu コンソールで戻り値を桁揃え(見易く表示)
;;; (コンソール上で戻り値リスト、ベクタを観察するためのテストコード用)
;;; (テスト用という考えだったので効率はあまり重視してない…)
;;;
;;; ez-padding,  vector-ez-padding   (printf, format の代用(独自仕様))
;;;
;;; リスト、ベクタの文字列要素の連結、リスト再構築、…など
;;; join-strings                (srfi-13 string-join の亜種(独自仕様))
;;; riffle-shuffle        (srfi-1  append-map  の機能限定版(独自仕様))
;;;                       (Haskell intersperse の変種と言えなくもない)
;;; deal-alternately                (リスト要素を交互に分配(独自仕様))
;;; pieces-of            (フラットなリストを2重リストに分割(独自仕様))
;;; change-head             (リスト中の指定要素を先頭に移動(独自仕様))

 今年の 8月以降から当ダイアリーで掲載したコードを若干修正したものを収録。ダイアリーで掲載してないコードもいくつかある。この中で、今後仕様が変わるかもしれないのは…

  reciprocating-motion-like-iota
  change-head

…の 2つ、かな。このファイルを Script-Fu パスに放り込んでやれば、今後しばらくの間は、当ダイアリーで掲載する Script-Fu のサンプルコードが実行可能となる(はず)。…なので、興味のある方は DL してご自由にお使いください。