4.2 もっとポリライン

U-座標系で折れ線を描くルーチンは sgplu です. これを使ってポリラ インプリミティブをもっと深く探ってみましょう(kihon9, kihona). 属性の1つがラインタイプですが, ユーザーの指定により, 多種多 様なラインタイプをつくることができます.

まず, kihon9 のプログラムですが, 一番上にラインタイプが4の折れ線 (一点鎖線)を描いています. sgrset ルーチンでポリラインプリミティ ブに関する実数型内部変数の 'BITLEN' を変更すると, パターンの1サ イクルの長さを変えることができます. この初期値はV-座標系の単位で0.003 ですが, 倍の0.006に設定し直したのが2本めの折れ線です. ビューポートのと り方次第で, パターンが間延びしたり, 逆にパターンが潰れて判別できなくなっ たりすることがありますが, そのようなときには 'BITLEN' を調節しま しょう.

SGPACK では, 実線, 破線, 点線, および一点鎖線以外のパターンのラインタ イプも指定できます. 実は, sgsplt ルーチンの引数に5以上の整数を指 定すると, その2進表現のパターンを指定したものと見なされます. すなわち, 整数の下位16 bit のうち1の部分に線を描き, 0の部分は空白とするようなパ ターンを設定します. 自分の描きたいパターンに対応する整数を求めるには, MISC1 の BITLIB パッケージ中のbitpci ルーチン(47行め)を使うと便 利です. '1111111100100100' のように文字型でビットパターンを与え ると, それに対応する整数値 itype が返されて, そのラインタイプで 描いた二点鎖線が3本めです.

さらに複雑なパターンを指定したいときには, sgiset で内部変数 'NBITS'を変更することにより, パターンのビット長を32 bitまで長くするこ とができます. 4本めの折れ線はこれを32 bitにして, 3本めと同様に bitpci ルーチンで新しいパターンを作っています.

# kihon9.rb


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


nmax = 40
xmin = 0.0
xmax = 4*PI
ymin = -1.0
ymax = 1.0

x = NArray.sfloat(nmax+1)
y = NArray.sfloat(nmax+1)

#-- data ---
dt = xmax/nmax
x = x.indgen * dt
y = sin(x)

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

DCL::sgfrm

#--  ラインタイプ = 4 (デフォルト) ----
DCL::sgswnd(xmin, xmax, ymin, ymax)
DCL::sgsvpt(0.0, 1.0, 0.7, 0.9)
DCL::sgstrn(1)
DCL::sgstrf

DCL::sgsplt(4)
DCL::sgplu(x, y)

#--  ラインタイプ = 4 (BITLEN*2) ----
DCL::sgswnd(xmin, xmax, ymin, ymax)
DCL::sgsvpt(0.0, 1.0, 0.5, 0.7)
DCL::sgstrn(1)
DCL::sgstrf

DCL::sgrset('BITLEN', 0.006)
DCL::sgplu(x, y)

DCL::sgrset('BITLEN', 0.003)

#--  ビットパターン ----
DCL::sgswnd(xmin, xmax, ymin, ymax)
DCL::sgsvpt(0.0, 1.0, 0.3, 0.5)
DCL::sgstrn(1)
DCL::sgstrf

#itype = bitpci('1111111100100100')
itype = '0b1111111100100100'.oct
DCL::sgsplt(itype)
DCL::sgplu(x, y)

#--  ビットパターン(倍長) ----
DCL::sgswnd(xmin, xmax, ymin, ymax)
DCL::sgsvpt(0.0, 1.0, 0.1, 0.3)
DCL::sgstrn(1)
DCL::sgstrf

DCL::sgiset('NBITS', 32)
#itype = bitpci('10010010011111000111110001111100')
itype =  '0b10010010011111000111110001111100'.oct -  ('0b1' + "0"*32).oct 
DCL::sgsplt(itype)
DCL::sgplu(x, y)

DCL::sgcls

program kihon9

 

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

次のプログラム kihona は, ラベルつきの折れ線を描く例です.

sglset ルーチンで内部変数 'LCHAR'.true. にすると, ポリラインプリミティブはラベルつき折れ線を描きます. ラベル付き折れ線と は, 描くべき線分のある長さを1サイクルとして, その一部分に空白域をとり, そこに指定した文字列を描くものです. 描く文字列は sgsplc ルーチン で指定します. この例では, まず 'A' のラベルをつけて折れ線を描き ました.

次に, 42行めで sgnplc ルーチンを呼ぶと, 設定されている文字列の最 後の文字の文字番号が1つ増えます. そこで, 2本め, 3本めの折れ線のラベル が 'B', 'C' と変わります. また, 文字列として 'K=1' と指定すると, まず 'K=1' というラベルを描き, 次の呼び出しでは 'K=2' というラベルを描きます(4本めと5本め). これらの折れ線では, sgsplt ルーチンで線分のラインタイプも変えています.

ラベルの文字列の高さは, sgspls ルーチンで指定できます. 初期値は V-座標系の単位で0.02ですが, 6本めの例ではこれを0.01として小さめのラベ ルにしています. さらに, ラベル付折れ線に関するパラメータを陽に設定する と, さまざまな変形が可能です. 内部変数 'LROT'.true. に して, 'IROT' で回転角を整数値で指定すると, 一定の回転角でラベル を付けます. これが .false. の場合(初期値)には, 線分に沿ってラベ ルを描きます. また, ラベルの間隔は内部変数 'CWL' で, ラベルの書 き始めは内部変数 'FFCT' で, それぞれ調節できます.

# kihona.rb


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


nmax = 40
xmin = 0.0
xmax = 4*PI
ymin = -1.0
ymax = 1.0
x = NArray.sfloat(nmax+1)
y = NArray.sfloat(nmax+1)

#-- data ---
dt = xmax/nmax
x = x.indgen * dt
y = sin(x)

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

DCL::sgfrm

DCL::sglset('LCHAR', true)

#-- ラベルつき折れ線 ----
DCL::sgswnd(xmin, xmax, ymin, ymax)
DCL::sgsvpt(0.0, 1.0, 0.9, 1.0)
DCL::sgstrn(1)
DCL::sgstrf

DCL::sgsplc('A')
DCL::sgsplt(1)
DCL::sgplu(x, y)

#-- 順序ラベル: A,B,C,... ----
for i in 1..2
  vymin = 0.9 - 0.1*i
  vymax = vymin + 0.1
  DCL::sgswnd(xmin, xmax, ymin, ymax)
  DCL::sgsvpt(0.0, 1.0, vymin, vymax)
  DCL::sgstrn(1)
  DCL::sgstrf

  DCL::sgnplc
  DCL::sgplu(x, y)
end

#-- 順序ラベル: K=1,K=2,... ----
DCL::sgsplc('K=1')

for i in 3..4
  vymin = 0.9 - 0.1*i
  vymax = vymin + 0.1
  DCL::sgswnd(xmin, xmax, ymin, ymax)
  DCL::sgsvpt(0.0, 1.0, vymin, vymax)
  DCL::sgstrn(1)
  DCL::sgstrf

  DCL::sgsplt(i-1)
  DCL::sgplu(x, y)
  DCL::sgnplc
end

DCL::sgsplt(1)

#--  ラベルの文字列の高さ ----
DCL::sgswnd(xmin, xmax, ymin, ymax)
DCL::sgsvpt(0.0, 1.0, 0.4, 0.5)
DCL::sgstrn(1)
DCL::sgstrf

DCL::sgspls(0.01)
DCL::sgsplc('small')
DCL::sgplu(x, y)

DCL::sgspls(0.02)

#--  ラベルの角度 ----
DCL::sgswnd(xmin, xmax, ymin, ymax)
DCL::sgsvpt(0.0, 1.0, 0.3, 0.4)
DCL::sgstrn(1)
DCL::sgstrf

DCL::sglset('LROT', true)
DCL::sgiset('IROT', 90)
DCL::sgsplc('ROT')
DCL::sgplu(x, y)

DCL::sglset('LROT', false)

#--  ラベルの間隔 ----
DCL::sgswnd(xmin, xmax, ymin, ymax)
DCL::sgsvpt(0.0, 1.0, 0.2, 0.3)
DCL::sgstrn(1)
DCL::sgstrf

DCL::sgrset('CWL', 5.0)
DCL::sgsplc('CWL')
DCL::sgplu(x, y)

DCL::sgrset('CWL', 30.0)

#--  ラベルの書き始め ----
DCL::sgswnd(xmin, xmax, ymin, ymax)
DCL::sgsvpt(0.0, 1.0, 0.1, 0.2)
DCL::sgstrn(1)
DCL::sgstrf

DCL::sgrset('FFCT', 0.9)
DCL::sgsplc('FCT')
DCL::sgplu(x, y)

DCL::sgcls

program kihona

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