%表題   らくらく電能ライブラリ
%
%履歴
%\Drireki{
%         95/04/13 余田 成男
%        }
%
%  \Dchapter{描画の基本(2))}
\Dchapterhead

これまでは $[0,1] \times [0,1]$ の仮想直角座標系(V-座標系)だけを用いて
各出力プリミティブを説明してきました. しかし, 一般に扱っているデータは
$[0,1]$で正規化されているわけではありませんから, つねにV-座標系で作図
するのは能率的なことではありません. そこで, ユーザーが実際に使っている
単位の座標系, ユーザー座標系(U-座標系)を導入し, U-座標系からV-座標系へ
の変換(正規化変換)を定義して, U-座標系で作図することを考えましょう.
\vspace{1em}

また, 出力プリミティブのちょっと進んだ内容についても紹介しましょう.

%-----------------------------------------------------------------------
\section{ユーザー座標系(U-座標系)での基本描画}
\subsection{基本概念}

ユーザーが実際のデータをもとに作図する過程を {\tt KIHON6} のプログラム
例をもとに考えてみましょう. ある地点の年平均気温のデータが1950年から
2000年まであり, およそセ氏16度から19度の範囲内で変動していた(第
\ref{c:quick}章のロジスティク模型の結果をちょっと細工しただけですが)と
しましょう.  このデータを元に平均気温の年々変動の折れ線グラフを描こう
と思います. $x$軸を時間軸にとり1950年から2000年まで, $y$軸には15度から
20度を範囲として, このデータを折れ線で描くことにします.

\Dproginput{kihon2/kihon6.f}

\begin{center}
\Depsf[10cm]{kihon2/kihon6.eps}\\
{\bf kihon6.f: frame1}\\
\end{center}

ユーザーの使っている座標系(ここでは時間[年]と温度[度])を, ユーザー座標
系(U-座標系)と呼びます. U-座標系でグラフに描きたい範囲を「ウインドウ」
と呼び, それぞれの軸の最小値と最大値で設定します. この例では, {\tt
( UXMIN, UXMAX, UYMIN, UYMAX )} = {\tt ( 1950, 2000, 15, 20 )}で, 25行
めの{\tt GRSWND} ルーチンで設定しています. このプログラムでは30行めで 
GRPH2 の {\tt USDAXS} ルーチンを用いて座標軸を描くために {\tt GRxxxx} 
を使っていることに注意して下さい.
\vspace{1em}

次に, このウインドウをV-座標系のどの範囲に対応させるかを考えて, これを
「ビューポート」と呼びます. ビューポートとは, V-座標系で通常座標軸が描
かれる矩形の領域のことです. ここでは, {\tt GRSVPT} ルーチンを用いて 
{\tt ( VXMIN, VXMAX, VYMIN, VYMAX )} = {\tt ( 0.2, 0.8, 0.2, 0.8 )} と
設定しました.
\vspace{1em}

これで, ウインドウとビューポートの四隅は対応させることができましたが, 
ウインドウ内の各点をビューポート内の点に対応させる必要があります. これ
を「正規化変換」と呼びます. 線形に対応させるか, 対数をとって対応させる
かなどの任意性がありますから, 具体的に変換関数を決めなければなりません. 
SGPACK(GRPACK) ではいくつかの変換関数が用意されており, それぞれに変換
関数番号が付けられています. ここでは, {\tt GRSTRN} ルーチンで関数番号1
を指定しています. これは両軸ともに線形に対応させるもので, 直角一様座標
となります.
\vspace{1em}

このように設定されたパラメータの値は, 変換関数を確定するルーチン{\tt
GRSTRF} を呼ぶことで有効になります. U-座標系で描画するためには, {\tt
GRFRM} ルーチンを呼んだ後でかつ描画をはじめる前に変換関数を確定する必
要があります.

\vspace{1em}

さて, U-座標系での描画ですが, V-座標系での各種描画ルーチンに対応するも
のが, すべて用意されています. この例では, U-座標系でのポリラインプリミ
ティブ {\tt SGPLU} で折れ線を描いています. 引数の与え方は全く同じで, 
データ{\tt X}, {\tt Y} がU-座標系の単位で用意されています. V-座標系で
の描画ルーチンのサブルーチン名が {\tt V} で終っていたのに対して, U-座
標系での描画ルーチンは {\tt U} で終るところが違っているだけで, 全く同
じ機能になっています.

%-----------------------------------------------------------------------
\subsection{ウインドウとビューポート}
\label{s:kihon2_wv}

次のプログラム {\tt KIHON7} では, U-座標系でのポリラインやテキストプリ
ミティブの出力結果が, ウインドウとビューポートの設定の仕方によってどの
ようになるかを示しましょう.

\Dproginput{kihon2/kihon7.f}

\begin{center}
\Depsf[10cm]{kihon2/kihon7_001.eps}\\
{\bf kihon7.f: frame1}\\
\end{center}

\begin{center}
\Depsf[10cm]{kihon2/kihon7_002.eps}\\
{\bf kihon7.f: frame2}\\
\end{center}

1フレームめが基本形で, まず {\tt SLPVPR} ルーチンでビューポートの枠を
描き, U-座標系描画ルーチンの {\tt SGPLU} で円と正三角形を描き, {\tt
SGTXU} で文字列 {\tt 'SGTXU'} を描いています(サブルーチン {\tt
APLOT}).
\vspace{1em}

2フレームめの左上には, 同じ {\tt APLOT} サブルーチンでビューポートだけ
を小さくして描いてみました. ビューポートが小さくなったのに対応して 
{\tt SGPLU} で描いた円と三角形は小さくなりましたが, 文字の大きさは1フ
レームめと変わりません.  U-座標系でのテキストプリミティブでも, 文字の
大きさはV-座標系の単位で指定するので, ビューポートの大きさが変わっても
文字の大きさは変わらないのです.
\vspace{1em}

次に, ウインドウの$y$軸の範囲を変えてみました(右上). 範囲を40\%に狭め
たので, 図形は縦に引き延ばされて, 円が楕円になりました. この場合にも, 
文字は変わりません.
\vspace{1em}

左下の例では, ウインドウの縦横比を元に戻して, {\tt UYMIN=-200}, {\tt
UYMAX=0} と $y$軸負方向に平行移動させました. その結果, 設定したビュー
ポートをはみ出して図形を描いています.
\vspace{1em}

最後に, 右下の例はウインドウの$y$軸を逆転させた場合です.
{\tt UYMIN=0}, {\tt UYMAX=-200} として, 左下の場合と逆にしました. この
時の三角形を見れば明らかなように, 図形は上下に折り返されています. ただ
し, 文字列は正立のままで折り返されません.
\vspace{1em}

下の2つの例のように, 設定したビューポートをはみ出して図形を描く場合, 
はみ出した部分を描かないようにすることも出来ます.  {\tt SGLSET} ルーチ
ンを用いてクリッピングに関する内部変数 {\tt 'LCLIP'} を{\tt .TRUE.} に
してやると, ビューポートをはみ出した部分はラインでも文字でも描かれませ
ん. 8行めのコメント行をもとに戻せばクリッピングを行ないます.

%-----------------------------------------------------------------------
\subsection{正規化変換の変換関数}
\label{s:kihon2_trn}

変換関数を変えることによってさまざまな座標系での描画が可能です. SGPACK 
で扱える座標系には, 大別して, 直交直線座標系(1$\sim$4), 直交曲線座標系
(5$\sim$7), 地図投影座標系(10番台$\sim$30番台), ユーザー定義座標系
(99), の4種類があります. 括弧内の数字は変換関数番号です. {\tt KIHON8} 
のプログラム例では, よく使う直交直線座標系の4つを見ておきましょう.
\vspace{1em}

サブルーチン {\tt BPLOT} では, ビューポートの枠を描き, 一次関数を実線
で, 指数関数を破線で, 対数関数を点線で描き, {\tt (X=30,Y=40)} を中心に 
{\tt SGTXU} で文字列 {\tt '(30,40)'} を描きます. {\tt SGSTRN} ルーチン
で変換関数番号を1と指定すると,直角一様座標(左上)となります. 2ならば$y$
軸が対数の片対数座標(右上), 3ならば$x$軸が対数の片対数座標(左下), 4な
らば両対数座標(右下)となります.
\vspace{1em}

\begin{center}
\Depsf[10cm]{kihon2/kihon8.eps}\\
{\bf kihon8.f: frame1}\\
\end{center}

\Dproginput{kihon2/kihon8.f}


%-----------------------------------------------------------------------
\section{もっとポリライン}
\label{s:kihon2_pl}

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

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

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

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

\Dproginput{kihon2/kihon9.f}

\begin{center}
\Depsf[10cm]{kihon2/kihon9.eps}\\
{\bf kihon9.f: frame1}\\
\end{center}

次のプログラム {\tt KIHONA} は, ラベルつきの折れ線を描く例です.
\vspace{1em}

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

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

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

\Dproginput{kihon2/kihona.f}

\begin{center}
\Depsf[10cm]{kihon2/kihona.eps}\\
{\bf kihona.f: frame1}\\
\end{center}

%-----------------------------------------------------------------------
\section{もっとテキスト}

プログラム {\tt KIHONB} で, ちょっと進んだ文字出力をしてみましょう.
\vspace{1em}

SGPACK においては '{\tt |}', '{\tt \_}', '{\tt "}'の3文字が添字の制御
に使われるのですが, 何も指定しなければ, これらの文字も他の文字と同様に
文字として出力されます(最初の例). {\tt SGLSET} ルーチンでテキストプリ
ミティブに関する内部変数 {\tt 'LCNTL'} を {\tt .TRUE.} にすると, 2番め
の例のように, 上付や下付の添字を出力することができます. '{\tt |}'と 
'{\tt \_}'は, それぞれ, 上付添え字と下付添え字のモードの始まりをしめす
制御文字で, '{\tt "}'は上付および下付添え字のモードの終わりをしめす制
御文字です. ここで注意すべきことは, 文字列が添字で終る場合でも, 添字の
後に必ず '{\tt "}'を入れて通常の文字モードに戻すことです. こうしないと
文字列の長さが正確に求まらないので, センタリングや右よせ等の処理がうま
くいきません.  また, 添字の大きさや上下の移動量は, それぞれ {\tt
SGRSET} ルーチンで内部変数 {\tt 'SMALL'}, {\tt 'SHIFT'} を指定すること
により変更できます(3番め).
\vspace{1em}

巻末付録に示したように SGPACK は2種類のフォントを持っています. {\tt
SGISET} ルーチンで内部変数 {\tt 'IFONT'} を2とすると, フォント番号2の
高品位フォントを出力することができます. 高品位フォントは複数の線を引い
て線の太さを調節していますから, {\tt SGSTXI} ルーチンで文字を描く線の
太さを太くすると空白が潰れてそれらしい文字になります.  また, 当然のこ
とながら高品位フォントを使うと出力量が増えますから,出力に時間がかかる
ようになります.
\vspace{1em}

フォントテーブルを見ればわかるように, SGPACK は普通のアルファベットだ
けでなく, ギリシャ文字や特殊記号のフォントも持っています. プログラムの
50行め以降に示したように, これらのフォント番号をDCL文字関数(SGPACK に
ある関数)の1つ {\tt CSGI} で文字コードに変換して, それをテキストとして 
{\tt SGTXV} ルーチン等に渡せば, 出力できます. 5行めのCHARACTER文で
{\tt CSGI*1} を忘れないで下さい. 

\Dproginput{kihon2/kihonb.f}

\begin{center}
\Depsf[10cm]{kihon2/kihonb.eps}\\
{\bf kihonb.f: frame1}\\
\end{center}

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

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

\Dproginput{kihon2/kihonc.f}

\begin{center}
\Depsf[10cm]{kihon2/kihonc.eps}\\
{\bf kihonc.f: frame1}\\
\end{center}

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

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