4.4 アローとラインのサブプリミティブ

出力プリミティブには, ポリライン・ポリマーカー・テキスト・トーンの他に, 補助的にアロー(矢印)とライン(線分)のサブプリミティブがあります. アロー サブプリミティブには, 矢印の軸部分のラインインデクスとラインタイプの2 つの属性があり, ラインサブプリミティブにはラインインデクスの属性があり ます.

プログラム kihonc で, いろいろな矢印や線分を描いてみましょう. U-座標系での矢印描画は, sglau ルーチンで行ないます. 引数は, (X1,Y1) が始点の座標, (X2,Y2) が終点の座標です. 線分の終点から 対称な2本の線分を付け加えて矢じり部分とします. 最初の例のように, デフォ ルトでは, 本体部分が長くなるのに比例して矢じり部分も大きくなります.

# kihonc.rb


require "narray"
require "numru/dcl"
include NumRu
include Math


#-- graph ---
iws = (ARGV[0] || (puts ' WORKSTATION ID (I)  ? ;'; DCL::sgpwsn; gets)).to_i
DCL::sgopn iws

DCL::sgfrm

DCL::sgswnd(0.0, 10.0, 0.0, 10.0)
DCL::sgsvpt(0.0, 1.0, 0.0, 1.0)
DCL::sgstrn(1)
DCL::sgstrf

#-- デフォルト ----
y1 = 9.0
for i in 1..8
  x1 = i
  x2 = x1 + 0.1*i
  y2 = y1 + 0.1*i
  DCL::sglau(x1, y1, x2, y2)
end

#-- 線分のラインタイプ ----
y1 = 8.0
y2 = 8.6
for i in 1..4
  x1 = 2*i - 1
  x2 = x1 + 0.6
  DCL::sgslat(i)
  DCL::sglau(x1, y1, x2, y2)
end

DCL::sgslat(1)

#-- 線分のラインインデクス ----
y1 = 7.0
y2 = 7.6
for i in 1..4
  x1 = 2*i
  x2 = x1 + 0.6
  DCL::sgslai(i)
  DCL::sglau(x1, y1, x2, y2)
end

DCL::sgslai(1)

#-- 矢じり部分の長さ ----
DCL::sglset('LPROP', false)
DCL::sgrset('CONST', 0.03)

y1 = 6.0
for i in 1..8
  x1 = i
  x2 = x1 + 0.1*i
  y2 = y1 + 0.1*i
  DCL::sglau(x1, y1, x2, y2)
end

DCL::sglset('LPROP', true)

#-- 矢じり部分の角度 ----
y1 = 5.0
y2 = 5.6
for i in 1..8
  x1 = i
  x2 = x1 + 0.6
  DCL::sgrset('ANGLE', 10.0*i)
  DCL::sglau(x1, y1, x2, y2)
end

#-- 矢じり部分のぬりつぶし ----
DCL::sglset('LSOFTF', true)
DCL::sglset('LATONE', true)
DCL::sgiset('IATONE', 655)

y1 = 4.0
y2 = 4.6
for i in 1..8
  x1 = i
  x2 = x1 + 0.6
  DCL::sgrset('ANGLE', 10.*i)
  DCL::sglau(x1, y1, x2, y2)
end

#-- ラインサブプリミティブ ----
#-- デフォルト ----
DCL::sglnu(0.0, 3.0, 10.0, 3.0)

#-- 線分のラインインデクス ----
y1 = 0.5
y2 = 2.5
for i in 1..4
  x1 = 2*i - 1
  x2 = x1 + 2.0
  DCL::sgslni(i)
  DCL::sglnu(x1, y1, x2, y2)
end

DCL::sgcls

program kihonc

 

\resizebox{!}{10cm}{\includegraphics{kihon2/kihonc.eps}}
kihonc.rb: frame1

sgslat ルーチンでは矢印を描く線分のラインタイプを, sgslai ルーチンではそのラインインデクスを設定できます(2番めと3番め). また,ア ローサブプリミティブに関する内部変数を設定し直すことにより, 矢じり部分 の形状を変えることもできます. 4番めの例では, 内部変数 'LPROP'.false. として矢じり部分の長さが一定値となるようにし, その長さを 内部変数 'CONST' で陽に与えました. さらに, 矢じり部分の線分と本 体部分の線分のなす角を変化させたり(5番め), 矢じり部分を定義する三角形 の領域を塗りつぶしたり(6番め)することにより, 多種多様な矢印が可能です.

最後に, U-座標系での線分描画は, sglnu ルーチンで同様に行ないます. しかし, これはアローサブプリミティブの特殊な場合(矢じり部分がない場合) と考えられますので, 将来的には削除されるかも知れません.


DCLのしくみ 2

xxpGET/xxpSET で内部変数管理

地球流体電脳ライブラリでは,例えば,sglget/sglset のような内部変数管理ルーチンが多く使われています.内部変数管理ルーチンとは,設定された変数の値を保持し,問い合わせに答えて値を返す機能を持ったルーチンで,「掲示版」のような役目をするものです.この様なルーチンを使う理由として,次のようなことがあげられます.

  • 複数のメソッド(元サブルーチン)で情報を共有するため
  • メソッド(元サブルーチン)の引数の個数を最小限にするため
複数のメソッド(元サブルーチン)で情報を共有するには,COMMON BLOCK を使うこともできますが,大きなパッケージでこれを多用するとプログラムの可読性を落とすことにつながります. また,メソッド(元サブルーチン)の引数を少くすると融通が効かなくなりますが,かといって,むやみに引数の数を増やすとかえって使いにくいものです.

このような問題を解決するのが内部変数管理ルーチンです.もともと「パッケージの内部で使われる変数」という意味で,内部変数という言葉を使っていますが,その変数はパッケージ外からも参照/設定できるので,その有効範囲からすると C 言語の「外部変数」に似た性格を持つものです.

内部変数管理ルーチンは xxpget, xxpset という名前です.xx は通常パッケージの先頭2文字で,p は変数の型によって,i(整数型), r(実数型), l(論理型), c(文字型)のうちのひとつになります.内部変数は,あらかじめシステムが用意した値(初期値)をデフォルトで保持しています.この値は xxpget ルーチンによって参照し,xxpset ルーチンによって変更することがでます.ユーザーが何も指定しなければ初期値を使うことになります.