描画 - みる会図書館


検索対象: 月刊 C MAGAZINE 1994年1月号
50件見つかりました。

1. 月刊 C MAGAZINE 1994年1月号

特集実用ク目回 9 ク術 メンバ関数 GraphicLine List 1 4 多くのマシンクロックを消費するのて、 , 汎 用的なルーチンの場合にはあまり用いたく ありません。 一般に , 傾きが a の直線のグラフを描く場 合 , 、、 x が 1 増加したら , y が a 増加するクよう に描くわけて、す ( Fig. 19 ) 。ここて、 , これを 、、 y を a 個描いたら , x を 1 増やす〃と読み換 えます。たとえば傾き 3 の直線の場合は , 、、 y を 3 個描いたら , x を 1 増やすクとなります (Fig. 20 ) 。長さ 3 の短い直線の集まりがて、き ますが , グラフィックの場合 , どんなに解 像度が上がってもしよせんは離散値の集合 て、すから , これて、十分直線になります。 傾きの計算は除算て、す。除算とはどうい う計算て、しようか ? 、、割られる数 ( 分子 ) の中に割る数 ( 分母 ) がいくつ入っているかク という計算になります。つまり、、分子から 分母をいくっ引くことがて、きるかク と読み 換えられます ( ただし , 分子が分母より大き いと仮定します ) 。 つまり分子から分母を引き続け , 分子が 0 より小さくなったところて、計算をいったん 止め , 引けた分だけ点を打ち , 次のステッ プに進みます。このとき負数になってしま った分子に元々の分子を足して再び 0 以上の 値にします。 こて、分子を単純に元の値て、置き換えな いのは割り切れなかった場合に誤差が生じ るのを防ぐためて、す。 除乗算が一切なくなり , 加減算だけて、直 となります。 線を描けるのて、処理自体は高速化します。 ( 1 ー 2 ) 式から明らかなように , この計算に こて、用いた割り算を減算て、行うテクニ は除乗算をともないます。除乗算は一般に TabIe 12 グラフィック八一ドウェアを直接アクセスする仮想関数 機能 関数名 初期化 GraphicInit グラフィック画面表示 GraphicStärt グラフィック画面停止 GraphicStop 垂直同期信号チェック VsyncCheck 垂直同期信号スタートチェック VsyncStart 点描画 GraphicPset グラフィック画面モード復帰 GraphicRestoreMode 水平ライン描画 GraphicHIine カラーバレット設定 GraphicPaIette テキスト画面表示 TextSta テキスト画面停止 TextSto p 2 : / / 直線描画 3 : / / (pxl,pyI)&(px2,py2) へ色 color の線を描画する :GraphicLine(int pxl, int PYI, int px2, int py2, int C010r ) 5 : VOid Gscreen: 7 : int dx, dy; 8 : int XX, yy; 9 : i nt i, d : 17 : 18 : 20 : 22 : 23 : 25 : 28 : 29 : 30 : 32 : 33 : 35 : 36 : 38 : 39 : 40 : 42 : 43 : 44 : 45 : 46 : 48 : } び x び y X X 、ノー 0 ワ朝っ朝 ー pxl; dx = i f ()y > dx ) { / / 縦長の線 d = dy > > l; for (i = 0 : i く dy; GraphicPset(pxI,pYI,c010r); / / この関数がオプジェクト型に 〃により入れ替わる pyl 十 = yy; = dx : i f (d くの { d + ニ dy ; pxl + = XX; } se { 〃横長の線 d = dx 〉〉 1 ; for (i = 0 : i く dx; GraphicPset(pxl,pYI,c010r); / / この関数がオプジェクト型に / / により入れ替わる pxl 十ニ xx; i f (d く 0 ) { d + ニ dx; pyl 十ニ yy; Table 1 1 Gsc 「 een 基本クラスのメンバ関数 関数名 GraphicCircle GraphicOval GraphicCircIeFilI GraphicOvaIFiII GraphicLine GraphicBox GraphicBoxFiII GraphicCls GraphicPolygon GraphicHSV GraphicGetLines 1 1 2 1 機 能 円描画 楕円描画 円塗り 楕円塗り 直線描画 長方形描画 長方形塗り 画面クリア ボリゴン描画 HSV → RGB カラー変換 Lines 数取得 特集実用グラフィック術 57

2. 月刊 C MAGAZINE 1994年1月号

ックは比較的基本的なものて、す。分母が分 子より小さくなる ( つまり , 商が 1 以上にな る ) ように調整してやらなければならないう えに , 負の数は扱えないが , 離散値を用い る場合には有効な手法になります。 GraphicOvaI(List 16 ) GraphicCircIe (List 1 5 ) 円 / 楕円の描画 円や楕円も幾何学の方程式に従って描画 Fig. void Gscreen::GraphicCircle(int cx, int cy, int radius, int color) 2 4 : } 19 直線のグラフ 0 ←ー 1 ー ) ー Fig. 20 傾き 3 の直線の場合 y 方向に三つ描いて x を 1 増やす うよりは円というものがそもそも楕円の特 楕円も , 基本的には円と同じて、す。とい と , あっという間に円が完成します。 称となる点 8 か所に同時に点を打っていく 題はなさそうて、す。 1 / 8 円周を求めながら対 45 。まて、の 1 / 8 円周を計算することにすれば間 いうのは扇形の寄せ集めて、描けるのて、 , 0 。 ~ 大きいのは 2x ー 2y 十 1 > 0 の間て、す。幸い円と 母を 2y ー 1 に改めます。また分子が分母より 数 ( く 0 ) て、あってはなりません。よって , 分 ( 1 ー 2y ) より大きく , かっ分母分子ともに負 を減算て、処理する場合には分子 (2x) が分母 先ほど直線の説明て、触れたように , 除算 List メンノヾ関数 GraphicCircle 2 : / / 円描画 これを繰り返せば最終的に 傾き 3 の直線になる するのが一般的て、す。 (x-xo)2 十 (y-yo) 2 2 殊形 ( 長軸半径と短軸半径とが等しい ) て、あ ると考えられますから , 当たり前といえば 当たり前て、すが。ただ , 楕円を描く場合に は , 関数のインタフェイスが問題となりま す。 No-BASIC などて、は円に縦横比を与える ことて、楕円を描くようになっていますが , 比率を使うとすると実数演算を行わなけれ ばならなくなり , うまくいきません。 PC-9 801 の ROM 内に用意されている GLIO は x 方 向の半径と y 方向の半径とをそれぞれ与えて やることて、楕円を描画するのて、 , ここて、は このインタフェイスを使うことにします。 式 ( 2 ー 1 ) は ( xo , yo ) を中心とする半径 r の円 の方程式て、す。式から明らかなように , 2 乗 の計算があるうえに , x を決めて y を求めよ うとすると平方根の計算をしなければなら ず , かなりめんどうなことになります。 関数 f ( x ) を微分して得られる導関数 f' ( x ) は一般に y = f ( x ) の x における傾きを表して います。曲線といえどもグラフィック画面 上に描く場合には短い直線の集合になり , それらしく見えればいいというレベルて、十 分て、す。これなら , 導関数を利用して済ま 58 C MAGAZINE 1994 1 という非常にシンプルな形になります。 2x dx 円の方程式は x て、微分すると すことがて、きそうて、す。 3 : / / ( cx , cy ) を中心とする半径 radius の円を色 c 引 or で描く 5 : 7 : 8 : 9 : 13 : 20 : 22 : 23 : int dx, dy; rad i us : dY = 0 ; dx while ()x > = (y) { GraphicPset()x + dXi GraphicPset()x 十 dy, GraphicPset()x ー dx, GraphicPset()x ー dY, GraphicPset()x ー dx, GraphicPset(cx ー dy, GraphicPset()x 十 dx, GraphicPset()x + dy, : ()y くく 1 ) radius i f (rad i us くの { radius 十 = ()X くく CY CY CY CY CY CY CY + dy, + dx, + dY, + dx, ー dy, ー dx, ー dy, ー dx, 十十 dy ; color); color); color) : color) : color) : color) : color) ; color) : / / 計算は 1 / 8 ( 0 ~ 冗 / 4 ) 〃除算

3. 月刊 C MAGAZINE 1994年1月号

特集実用ク目回を 9 ク術 [ 3 ] [ 2 ] を追加したいと考えています。 現在進行中の作業はメンバ関数をすべて アセンプラて、書き直すことて、 , 徹底的な高 速化を行っています。近いうちに , そのよ うなテクニックを発表て、きる機会があるの て、はないかと思います。 [ 参考文献 ] [ 1 ] 『注解 C 十十リファレンスマニュア ル』 , M. A. 工リス , B. ストラウスト ラップ著 , 足立高徳 , 小山裕司訳 , ト ッパン , 1992 . secti()ll 2 実践「 Gscreen 」 クラスライプラリ「田 1 」は , 直線 描画 , 円描画 , 多角形描画など基本 的な描画処理を備えたクラスライプ ラリですが , さらに機能拡張する余 地も残されています。本節では「・ 司を使用したサンカレプログラム を示しながら , ポリゴンの抽象化を 例にしてクラスライプラリ拡張のテ クニックについて説明します。 実行ファイル共通の サンプルプログラム Section 1 て、作成したグラフィックライプ ラリを用いてサンプルプログラムを作成し こては作成したサンプルプログ ラムについて説明します。 今回用意したサンプルプログラム プログラム 1 gsdemo プログラム 2 polydemo は , PC ー 98 シリーズて、も AT 互換機て、も同じ 実行ファイルて、動作させることがて、きます。 サンプルプログラム gsdemo はグラフィッ クライプラリの各種描画関数を利用して図 形を描くプログラムて、 , ほとんど C のプログ ラムを作るのと変わらない感覚て、作成して います。 もうひとつの polydemo はポリゴンをクラ ス化した , どちらかというと C 十十らしいプ ログラムて、す。 Gscreen ライプラリはハードウェアに依存 する処理ルーチンをレイトバインディング 処理することにより , PC-98 シリーズと AT の VGA とて、実行ファイルを共通化している ことが最大の特長て、す。 実行時にはまず , 実行環境を調べてそれ に合わせて Gscreen のいずれかの派生クラス のオプジェクトを生成することが必要とな 今回はメニュー形式て、ユーザが指定するこ ることにより自動化することが可能て、すが , この「機種判別」は , ワークエリアを調へ ります。 れば ( 1 ) ~ ( 3 ) て、ほば同じ画面を作ることが が違いますが , PC ー 9801 の表示能力に合わせ それぞれ縦方向ライン数と表示可能色数 トが構築されます ) 。 クラス , ( 3 ) て、は GsVGA クラスのオプジェク 択した場合は GS9801 クラス , ( 2 ) て、は GS9821 築し , デモを実行します ( Fig. 24 て、 ( 1 ) を選 と , それに合わせて画面オプジェクトを構 Fig. 24 に示した選択肢から番号を選ぶ ( 2 ) PC ー 9821 ( 3 ) VGA Fig. 24 メニューによる機種選択 ( 1 ) PC ー 9801 Microsoft C/C 十十 C 十十 TutoriaI IfTHE C Graphics HANDBOOK 』 , ROGER T. STEVENS, ACADEMI C PRESS, INC. , 1992 . [ 4 ] 『最新 C 言語によるプログラム事典第 2 巻』 , 平林雅英 , 技術評論社 , 1992. 山崎義博 ( ZOB が us ) 意識して作成することにしました。 グラムて、はライン数や表示色数をいくらか きなくなります。そのため本サンプルプロ くの 256 色 24 ビットカラーを活かすことがて、 801 に合わせてしまっては PC ー 9821 のせつか ログラムしようかと思ったのて、すが , PC-9 以降はまったく機種を意識しないようにプ 当初は , 最初の画面オプジェクトの構築 て , だいたい同じ色を出すことがて、きます。 を利用して色を HSV 形式て、扱うことによっ てしまいますが , GraphicHSV メンバ関数 じ値て、あっても機種ごとに色合いが変わっ 色について単純に RGB の値を扱うと , 同 しないて、済みます。 ラムはハードウェアの違いをほとんど意識 可能て、 , このときアプリケーションプログ プログラム 1 ご gsdemo 特集実用グラフィック術 63 きる PC ー 9821 て、のみ動作します。 を行います。ただし 4 は 256 色を同時表示て 4. 色相環の描画 3. 楕円の描画 2. ポックスの描画 1. 円と直線の描画 種を選ぶと描画が始まります。 描画動作を行います。メニューに従って機 プログラム 1 の gsdemo は , 比較的単純な

4. 月刊 C MAGAZINE 1994年1月号

最新ロ口ロレポート IZ 09 ロ ご 0 ホご 0 にロ Fig. 7 描画エレメント Fig. 8 完成したノヾネル 衄番号 メディアーー 評価ロー Total 「二こ : 〕 曲数 I¯I 司画コ⑩国 No title t it le 0 番号 メディアーー 曲数ロ 評価ロー Total 「 : : : 二〕 メモー STR I NG ー 国スタイル団 SLIDER ロー サイス、団ー INTEGER 1 ーへこて 0 [ 左 ] : 線の色 ーく直線 > 始点を指定してください . Fig. 9 ノヾネルエテイタから C ソースを作成 Fig. IO ノヾネルエテイタから実行 司画コ⑩国 0 0 ジャンル国歌謡曲 ロ struct メンバのパックロエレメント番号の生成 変数名の接頭部一 [ STOP ] キーで終了します . ー残りメモリは引 6496 バイトです . を決めてから , 必要に応じてどんなタン 能て、すが , 後て、表形式て、一括して一覧し , ムに取り込むことがて、きます。この場合は にするのか詳細内容を定義します。ほかの 位置や色などを数値て、直接指定することも て、 ~ ぐのフロッビーて、提供されているライ プラリをリンクします。 エレメントも同様て、す (Fig. 4 ) 。ここて、 , ノ て、きます。表形式て、の詳細編集て、は , 座標 ネル自体の設定もしておきます (Fig. 5 ) 。た に一定の値を加えたり引いたりといった操 また , コンパイルせずとも , パネルエデ とえば , パネルをユーザにクローズされた 作もて、きるのて、 , 編集作業がはかどります。 イタ内から試しに実行することもて、きるの くない場合には , それなりの設定がて、きま このようなパネル ( Fig. 8 ) が完成します。 て、便利て、す ( Fig. 10 ) 。 実際のアプリケーション作成のときには , 試しに実行して , 気に入らないところが す。 もう 1 枚のパネルをオープンし , 1 枚目と こういったパネルを何枚も作成します。フ あったり , おかしいと思うところがあった 同様に作業を進めます ( Fig. 6 ) 。描画エレメ ァイル選択用パネルとか , セープファイル ら , パネルを編集しなおせば OK て、す。いく ントとして , て、たらめにラインを引いてみ 名入力用パネルとか , 別フォーマットの入 らて、もやりなおしがて、きるのて、神経を使い ましよう (Fig. 7 ) 。描画エレメントは必要十 カ用パネルとか , ヘルプ表示用パネルとか すぎることもなく , とっても気楽て、ストレ 分なだけ用意されています。パターンエデ 作成するアプリケーションの要求によりさ スがたまりません。 イタがドットて、グラフィックを描くのに対 まざまなパネルが作成されるはずて、す。 バターンエテイタ して , パネルエデイタては線や円やペイン 作ったパネルは , パネルエデイタから C ソ トなどて、グラフィックを描きます。描画工 ースを生成 ( Fig. 9 ) て、きるのて、 , 自分のコン レメントについては , マウスて、の編集も可 パイラて、コンパイルして , 自分のプログラ パネルエデイタて、作成するパネルには , 最新開発環境レポート 149

5. 月刊 C MAGAZINE 1994年1月号

今回と次回の 2 回に分けて , プログラムリ ストを見ながら , 正しいクラスの書き方に ついて説明していきます。これて、 , 継承と 仮想関数を除いた基本的な事項をマスター て、きるはずて、す。 題材とするプログラムは , タートルグラ フィックスのプログラムて、す。タートルグ ラフィックスはペンを持った亀 ( タートル ) を動かし , その軌跡て、図形を描くものて、 , プログラミング言語 LOGO に採用されている 機能て、す。 Fig. 1 に典型的な描画を示してお きます。 今回は , 代入と初期化をめぐって , というものて、す。 int 型の age については値の コヒ。ー元のデータメンバの値を初期値とし ・コピーコンストラクタ コピーだけて、うまくいきます。しかし , 文 ・代入演算子の定義 て , 自分のデータメンバをひとつずっ初期 字列の name のほうは , ポインタの値だけを ・参照型 化していきます。このときも , それぞれの コピーするのて、 ,b. name は a. name と同じ文 ・初期化の順序 メンノヾのコピーコンストラクタが用いられ 字列を指すことになります。 ・配列の初期化 ます。 一方 , 代入のほうは , 代入演算子 前回学んだライフタイムの図て、調べてみ について勉強します。 の働きて、す。代入演算子も , デフォルトて、 , ることにしましよう。 Fig. 2 に示すように 初期イと代入 f00 ( ) の場合 , b が消滅するときに , デスト 自分のデータメンバにコヒ。ー元のデータメ ラクタて、 b. name が delete されますが , これ ンバの値を , ひとつずっ代入していきます。 ⅢⅢⅢⅢⅢⅢⅢⅢⅢⅡⅢⅢ【例」題 1 】ⅢⅡⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢ このときもメンバの代入演算子が用いられ は , とりもなおさ ia. name が delete される ことになります。したがって , これ以後の List 1 は , Fig. 1 の樹形を描くプログラ ます。 文字列へのアクセスは不正て、す。しかし , ムの一部です。 6 行目 ( 1 ) と 12 行目 ( 2 ) の違 このようなデフォルトの動作をするコピ a が消滅するときに , デストラクタて、再び a. ーコンストラクタや代入演算子は , 単純な いをいいなさい。 ⅢⅢⅢⅢⅢⅢⅡⅢⅢⅢⅢⅢく解答 > ⅢⅢⅢⅢⅡⅢⅢⅢⅢⅢⅢⅢ name が delete される , という不正なアクセ クラスの場合には良好に動作しますが , 動 的オプジェクトを扱うクラスて、は , しばし スが生じてしまいます。 ( 1 ) は初期化。 ( 2 ) は代入。 bar ( ) の場合も同様に , a. name を 2 回 del 初期化はオプジェクトの生成時に値が入 ば弊害が生じます。次の【例題 2 】て、体験し ete しようとしますが , これ以外に , もとも ることて、す。一方 , 代入は以前の値を捨て てみましよう。 と b. name が指していた文字列を見失うこと てから , 新たな値を入れることて、す。見た メモ理問題再び にもなります。解放すべき領域を解放せず , 目は同じようて、すが , 動作が異なります。 解放してはいけない領域を解放してしまっ UTurtle tt=t ; ⅢⅡⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢ【例題 2 】ⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅱ ているのて、す。 List 2 の関数 f 。。 ( ) , ba 「 ( ) を実行する これらは明らかなバグて、す。不安定な動 UTurtle tt(t) ; 作や異常終了は必至て、しよう。しかも , 見 と , どんなことが起こりますか ? 〃の右側のオプ とみなされます。実は , ⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢ < 解答 > ⅢⅢⅢⅢⅢⅢⅢⅢⅢ日ⅢⅢ た目にバグとはわからないのが厄介て、す。 ジェクト t を , コンストラクタの引数に渡し どちらも動的オプジェクトを 2 回 de te し コンストラクタ / デストラクタのペアて、 , ているのて、す。したがって , 初期化になり てしまう。さらに , bar ( ) では動的オプジ 見 , 正しく管理しているように見えるから ます。このコンストラクタは , 自分と同じ ェクトを行方不明にしてしまう。 て、す。コピー生成や代入て、 , ポインタのコ クラスのオプジェクトをコピーする働きを b = a て、生じるデフォルトのコヒ。ー動作は , ピーが作られた数だけ , 弊害は増えます。 するのて、 , コピーコンストラクタと呼ばれ さて , どうすればよいて、しようか ? ます。 b. age=a. age ; デフォルトのコピー動作をさせなければ コピーコンストラクタは , デフォルトて、 , b. name=a. name , 【例題 1 】樹形描画プログラム List 1 : static void draw-branch(const UTurtIe& t, double len) if (len く min-length) return; / / 左の枝の描画 UTu r 凵 e t t tt.left(branch-theta); tt. forward(len) : draw-branch(tt, / / 右の枝の描画 tt. right(branch-theta); tt. forvard(len); draw-branch(tt, 【例題 1 】 ( 1 ) / / 枝を再帰的に描く len * reduce_rate) ; 【例題 1 】 ( 2 ) / / 枝を再帰的に描く len * reduce_rate) ; 102 C MAGAZINE 1994 1

6. 月刊 C MAGAZINE 1994年1月号

→プロクラミング道場 Dr. 望洋の LiSt 1 クモードて、は不可能て、ある。このように gp oint の返すパレット番号によって判別て、きる のて、ある。 : 98 スーノヾーライプラリ』 のグラフィック 誌面の量的な制約のため , あまり詳しい 解説がて、きないことに対するいい訳 ? と いうわけて、はないが , 拙著℃ : 98 スーパー ライプラリ』中のソースファイルを , 付録 ディスクに収録することにした。収録した ソースは , Fig. 4 のファイルて、ある。ここて、 サポートされるライプラリ ( 関数・マクロ ) box boxf は , TabIe 3 のとおりだ。 circle circlef C ー 86 Ve 「 . 3.30C e Ⅲ pse 試食版用ライプラリ ellipsef gcircle ℃ : 98 スーパーライプラリ』は , 発表当 cls gcolor 初に存在した処理系て、ある LSI C ー 86 Ver. gget 3.2 試食版やの LSI C ー 86 Ver. 3.3 には対応 gGRBset init, _ginit している。しかし , 本誌の 1993 年 11 月号付 録ディスクにも収録された , LSIC-86Ver. gline 3.30C 試食版には対応していない。そこて、 , paint' gpaint2 palette, gpaletts Ver. 3.30C 試食版に対応させて新たに作成 point したライプラリファイルなどを特別に収録 gpset put することにした。 g 「 0 付録ディスクを参照していただきた い screen gte 「 m VleW 募集 isganalog line 本連載て、は , 読者からの質問にお答えし , また希望に応じてプログラムの添削も行う。 ( 1 ) 氏名・住所・電話番号 下記必要事項を明記のうえ , フロッヒ。ーデ ②匿名希望の有無 / ペンネーム イスクにて応募していただきたい ( 短い質問 ( 3 ) 質問・相談事項 ( なるべく具体的に ) て、あれば , 書面のみて、可 ) 。 宛先 なお , 応募いただいたフロッヒ。ーディス 〒 108 東京都中央区日本橋浜町 3 ー 42 ー 3 クは返却て、きないことや , 個人的な質問に ソフトバンクスクウェア はいっさいお答えて、きないことをあらかじ ソフトバンク ( 株 ) 出版事業部 めご了承されたい C マガジン編集部 どんな小さな疑問点てもけっこうなのて、 , 「 Dr. 望洋のプログラミング道場』係 気後れせずに , 応募していただきたい ( ただ 上参考文献 し , 特殊な題材よりも , 一般性の高い題材 を優先的に取り上げることを , あらかじめ [ 1 ] 平林雅英 , 「 ANSI C 言語辞典』 , 技術 -Ghires) Gana log 引 se { gc 引 or ( 0. 0. 7 , GC4096P16 ) ; gpset(), 0 , 8 ) : GanaIog : (gpoint(0, の gpset(0,0, の : --GanaIog) gc010r(), 0 , 7 , GC8P8) : 00 ーれ 0 ー 0 リ 0 リ 0 1 ー 0 し 8 8 8 8 00 0 リ / * ハイレゾでは常に 1 6 色使用可 * / Fig. 4 付録ティスクに収録したソースファイル ASSEMBL. H GRAPH ℃ . H BSGRINIT ℃ BSGRLINE ℃ BSGRPHXX ℃ BSGRPLTS ℃ BSGRSCRN ℃ Table 3 付録ティスクに収録したライプラリのサポート関数・マクロ 関数・マクロ 内容 矩形枠を描画 矩形 ( 塗りつふし ) を描画 円枠を描画 円 ( 塗りつぶし ) を描画 楕円枠を描画 楕円 ( 塗りつぶし ) を描画 円を描画 画面を消去 バレットモードなどの設定 描画情報の格納 カラーノヾレットの設定 初期化 日本語文字の描画 直線の描画 塗りつぶし カラーパレットの設定 表示色の取得 点の描画 描画情報の返却 描画画面の移動 画面モードの設定 終了処理 表示領域の設定 拡張グラフィックモードの判別 直線の描画 評論社 , 1989 [ 2 ] アスキー出版局テクライト編 , 「新版 PC ー 9800 シリーズテクニカルデータブッ ク』 , アスキー , 1990 [ 3 ] アスキー出版局第二書籍編集部編 , rp C ー H98m0de170 テクニカルデータブッ ク』 , アスキー , 1990 [ 4 ] 柴田望洋 , ℃ : 98 スーパーライプラ リ』 , ソフトバンク , 1992 BSGRANI 6. C BSGRCRCL ℃ BSGRPAIN ℃ BSGRPALT. C BSGRPSET. C BSGRPUTG ℃ ご了承願いたい ) 。 しばた・ばうよう ( 工学博士・国立特殊教育総合研究所 ) Dr. 望洋のプログラミング道場 139

7. 月刊 C MAGAZINE 1994年1月号

特集戻用目回 9 ク術 除算の関係から縦長 ( rx < ry ) の場合と横 dy, 次の線分のライン構造体へのポインタ ポリゴン関数は , List 17 ー ( a ) に示したポ リゴン構造体の参照を引数とします。この next_lp, 前のライン構造体へのポインタ b 長 ()x と ry ) の場合とて場合分けを行う必要 があります。 ポリゴン構造体は多角形を構成する線分の efore lp を順次格納します。 円周の 1 / 8 だけを計算するという基本的な 本数と , その線分のデータを保持するライ これらの設定を最初に行うことにより描 部分は変更せず , 点を打っ部分のみを変更 ン構造体配列のポインタによって構成され 画ルーチンにおけるデータ処理が軽減て、き , します。横長の場合 ( rx と ry ) 半径 ry の真円 高速化に役立ちます。 ています。 に比べて , 円周上の各点の x 座標が rx / ry 倍に ライン構造体は片側 XY 座標データのみを ポリゴン描画はポリゴンの上端 ( Y 座標小 ) なっていれば期待する楕円が得られるわけ 設定し , もう片側の XY 座標は次のライン構 から行われるため , 最上端に位置する左右 て、す。縦長の楕円の場合は x , y を逆に考え 造体の XY 座標を使います。すなわち , この 2 本の線分をサーチし , その 2 本の線分のラ ればいいことになります。 dx, dy が変化す ライン構造体配列の線分は連続的につなが イン構造体のポインタを求めます。ふたっ るたびに割り算 ( 減算 ) を行い値を補正して っているものと仮定されており , 最後の線 のライン構造体のデータを使って , その Y 座 標における左右の X 座標を直線のアルゴリズ いきます。 分は最初の線分に接続されていることが前 提条件となります。 ムを利用して求め , 水平ラインを描画しま ポリゴン描画 ライン構造体におけるそれ以外のデータ す。 Y 座標を十 1 ずっ増加させ , 左右どちら GraphicPOIygon(List 17- ( b ⅱ。ー、 はワークエリアとしてポリゴン関数の中て、 かの線分の下端部に到達するまて、同様な処 高速性を高めるために利用されています。 理を繰り返します。 ポリゴンは複数の線分を結んて、多角形を ポリゴン関数は Fig. 21 に示すような流れ 下端部に到達すると次の線分のライン構 形成しています。したがって , 基本のアル て、実行されます。最初にポリゴンの最上端 , 造体のポインタを求めます。接続される線 ゴリズムは直線と同様て、すが , 複数の線分 最下端の Y 座標とライン構造体のワークエリ 分は next_lp か before lp のライン構造体のど アの設定が行われます。線分の両端の XY 座 ちらかなのて、 , サーチはふたつの線分のみ の座標を効率よく求める必要があるため , て、済みます。そしてポリゴン最下部に達す 直線描画以外のテクニックが必要となりま 標が ye > ys になるように xs, ys, xe, ye に 格納します。そして , 描画 X 方向 xx , 線分の るまて、描画処理を繰り返し , 最下端部て、最 す。このポリゴン関数は凸多角形のみの塗 y 変位 dy, dhx=dx / dy, dlx=abs(dx) % 後の水平ラインを引いて終了します。 り潰しを行います。 メンノヾ関数 G 「 aphicOv 引 List i f (ddy くの { ddy + = rx; , 1 り朝 CO -4 ・ C.D 内ー 8 ・ 0 リ 0 1 ーワ 3 り -4- リ 00 っーし 0 、 1 ワ編 CO - ・内ー 8 0 , 1 り 0 っ 0 り 0 り 0 ワ 0 っ 0 っ 0 ワ 0 っ 0 ・・・ -4 ・ 4 ・・ -4 ・・ -4 ・ -4 ・・ 0 リ LO LO 00 わり 2 : / / 楕円描画 3 : / / ( cx , cy ) を中心とする半径 ( rx , ry ) の楕円を色 c 引 or で描く 5 : void Gscreen::Graphic0val(int cx, int cy, int rx,int ry, int color) 7 : int dx, dy; 8 : int xx, yy; 9 : int ddx,ddy; i nt dd : i f ()x > ry ) { / / 除算のために長軸方向で場合わけを行なう dx = rx; dy = 0 ; xx : 0 : yy = ry : dd X ニ ddy : dd : while ()x > = (y) { / / 計算は 1 / 8 で済ます GraphicPset()x + dx, color) : CY 十 XX, GraphicPset()x 十 dy, 16 : color) : CY 十 YY, GraphicPset()x ー dx, 17 : color) : CY 十 XX, GraphicPset()x ー dy, color) : cy 十 yy, Graph icPset (cx XX, color) : CY GraphicPset (cx 20 : ー dY, color); CY ー YY' GraphicPset()x + dx, XX, color) : CY Graph icPset ()x + dy, 22 : ー YY, color); CY dd ーニ ()y くく 1 ) 23 : ー 1 : 十 + dy : ddx ーニ ry; 24 : i f (ddx くの { 25 : ddx 十 = rx; 十十 xx; 26 : 27 : i f ( dd く 0 ) { 28 : dd + : ( dx くく 1 ) : --dx; 29 : 30 : ddy ー ry ; } 引 se { / / 縦長 ( y 軸方向が長軸 ) dx = 0 : dy = rx : yy ニ 0 : ddx ニ ddy ニ dd = ry : XX wh ⅱ e ( dx ← dY ) { GraphicPset()x 十 xx, color) ; cy 十 dx, GraphicPset()x 十 yy, color) : cy 十 dy, GraphicPset(cx color) ; XX, cy 十 dX, GraphicPset()x ー yy, color) ; cy 十 dy, GraphicPset(cx ー dx, color) ; XX, CY color) : GraphicPset()x ー yy, CY ー dy, GraphicPset()x 十 xx, ー dx, color) : CY GraphicPset()x 十 yy, - dy, color) ; CY dd ーニ ()x くく 1) ー 1 ; 十十 dx ; ddy ー i f (ddy くの { ddy 十ニ ry; 十十 yy : if ()d くの { dd + = ()y くく l); ddx rx : i f (ddx くの { ddx + = ry; ニ r Y : —XX; 特集実用グラフィック術 59

8. 月刊 C MAGAZINE 1994年1月号

最新 開発環境 レポート 、ルで ~ ぐ 円羽信夫 GUI 設計構築ツール ノヾネルで ~ ぐ バネルで ~ ぐは C 言語による GUI の設計・作 成ためのソフトウェアである。 ハネで ~ 0 パネルて ~ ぐ ( 以下て、 ~ ぐ ) は , ソフトウ ェアの外見を含めたユーザインタフェイス 全般の作成を補助する GUI 設計ツールて、あ り , 決まりきった GUI 部分をライプラリへ渡 すデータとして書き出す C ソース自動作成機 て、あり , 設計した GUI をとどこおりなく稼働 させるための関数ライプラリ集て、す。 に分かれる ヾネルで ~ ぐ」ツール 「パネルて、 ~ ぐ」はおもに次の三つのツー ルプログラムと , 多数の関数からなるライ プラリからて、きています。 バネルエデイタ 作成するアプリケーションの内容に即し たウインドウ ( ューザが作成するウインドウ をて、 ~ ぐて、は、、パネルクと呼ぶ ) を設計しま す。パネルエデイタて、は , パネルに入力項 目などの部品 ( て、 ~ ぐて、は、、入力エレメント〃 と呼ぶ ) を配置したり , ボタンやメニューな ど何らかの実行動作へのきっかけとなる部 品 ( て、 ~ ぐて、は、、実行エレメント〃と呼ぶ ) を貼り付けたり , 画面表示を装飾 ( て、 ~ ぐて、 は、、描画エレメント〃と呼ぶ ) したりしてパ ネルを作成します。 パターンエデイタ ノヾネルエデイタ上に開かれるパネルには , 任意のビットマップデータを貼り付けるこ とがて、きます。専用プログラム、、パターン 工デイタクて、は , このビットマップデータ を作成・編集します。 / ヾネルマネージャ 列させることがて、きます。スナップは 10 種 のエレメントをドットずれすることなく整 動しなくなります。この機能を使えば各種 定のドット間隔て、しかマウスカーソルが移 な機能があり , これを使うと定義された一 パネルエデイタにはスナップという便利 よう。 描画速度は , まあまあといったところて、し て、きるようになっています。グラフィック ック描画のため , 1 ドット単位の位置決めが パネルは , 文字も含めてオールグラフィ 気楽な感覚て、パネルを作成します。 描きソフトて、お絵描きて、もしているような を進めていきます。全般的に , まるてお絵 たがって , 基本的にはマウスの操作て、作業 ットキーを駆使しなければなりません。し 場合はマニュアルと首っ引きて、ショートカ キーポードて、の操作も可能て、すが , その / 、ルエテイタ えるようになっています。 切り換えながらそれぞれに適した作業を行 て、 ~ ぐは , これらの三つのプログラムを 1 か所にまとめて作成します。 ソースは , 複数のパネルに共通のデータを 関する C ソースを作成します。作成される C ルを総合的に取り扱い , 最終的に GUI 部分に パネルエデイタて、作成された複数のパネ 類定義てきます。テキストと違って , オー ルグラフィックのノヾネルて、すからスナップ 機能は重宝します。 パネルエデイタは一度に 10 個まて、パネル をオープンて、きます。いくつもパネルを開 いているとメモリ容量が心配になりますが , EMS 対応によりこの不安を回避していま す。 て ~ ぐて、提供するパネル ( パネルは最終的 には目的のアプリケーションのウインドウ になる ) は多機能なウインドウて , リサイズ やドラッグによる移動 , クローズ , スクロ ール , プライオリティ変更などをサポート しています。 Fig. 1 は , パネルエデイタを起 動したところて、す。左上にあるのがパネル に配置てきるエレメントの数々て、す。パネ ルを 1 枚オープンし , いくつかのエレメント をドラッグしてきて , ポンポンとパネル上 に気楽に置いていきます (Fig. 2 ) 。各エレ メントはて、きあいのデザインがなされてい ます。 エレメントには表形式の入力をサポート するような非常に高度なものもあります。 文字入力は 4 , 095 文字まて、可能て、すが , 残念 ながらライン入力のみて、 , テキストエディ タのように縦に広がりのあるフルスクリー ン入力はてきません。 高機能といえば , プルメニューから選択 したり , 選択肢をスクロールさせて選択す るといった , 自分て、作るとなるとそう簡単 には作れないエレメントもあります。ラジ オのポリュームのように , スライダーをマ 最新開発環境レポート 147

9. 月刊 C MAGAZINE 1994年1月号

GraphicPolygon 用の構造体 1 : / / ポリゴン用ライン構造体 2 : struct PLINE { 3 : int X ; int Y : 5 : int XS ; 6 : int YS ; 7 : int 8 : int 9 : int XX ; int dY ; int dhx; 12 : int 引 x : PLINE* next_lp; PLINE* before_lp; 17 : / / ポリゴン構造体 18 : struct POLY { int line_n; 19 : 20 : PLINE* 1 ine_p; 22 : List ポリゴンの描画はスヒ。ードを追求したい ところて、すが , C 十十 ( C ) 言語て、はなかなか 満足したものにはなりません。このポリゴ ン関数はライン構造体の設定など , て、きる だけの高速性を考えて作成しましたが , ス ピードには不満が残ります。このような関 数はアセンプラて、命令クロックや CPU フェ ッチを考慮して書くほうが望ましいわけて、 す。アセンプラて、実際に組む前にこのよう な C 言語て、アルゴリズムを追求したルーチン を作成し , その流れに添ってアセンプラて、 プログラムを組むとアルゴリズムとしても CPU 命令としても最適なプログラムが作成 て、きるようになります。 Fig. 21 ポリゴン関数の流れ ymax,ymin 取得 G 凵 NE ワーク設定 17 ー a / / 先頭 X 座標 / / 先頭 Y 座標 / / 上端 X 座標 / / 上端 Y 座標 / / 下端 X 座標 / / 下端 Y 座標 / / 描画 X 方向 + 1 : 右 , ー 1 : 左 / / ye ー YS / / dx / dY / / abs(dx) % dy / / 次のライン構造体のポインタ / / 前のライン構造体のポインタ / / 線分本数 / / ライン構造体先頭ポインタ Fig. 22 ホリゴン描画方法 ←上端から描画が始まる この位置で次の 左線分をサーチする→ →十 X この位置で次の ←右線分をサーチする ←下端で終了 ↓ 先頭左右ラインサーチ 十 Y 左右 X 座標計算 Fig. 23 HSV 形式と色相環 白 1 水平ライン描画 Y 座標十十 紫 左右どちらかの線分の 終端かどうか ? 終端 最下端かどうか ? 1 80 黄 終端ではない 緑 終了 最下端 0 次に接続される ライン取得 黒 (J) 0 1 1 60 C MAGAZINE 1994 1

10. 月刊 C MAGAZINE 1994年1月号

特集戻用ク目回ク術 ています。 もな仕事は , Polygon オプジェクトやほかの べてのポリゴンを一度に描画て、きます。角 ポリゴンの描画は , ほかの図形に比べる PolyGro 叩オプジェクトを自分の中に取り 度を変えたコピーなどもコヒ。ーコンストラ と少々ややこしいのて、ソースを参照してく 込むことと , 取り込んだすべてのポリゴン クタ呼び出し一発て、済んて、しまいます。 ださい に描画や色変更といった各種操作を行うよ PolyGroup て、はポリゴンをリスト構造に う指示を出すことて、す。 して持っているため , Polygon クラスと同様 、 , 甲 0 Ⅳ Group クラス このようにしておくことにより , たとえ なポインタメンバの問題が起きます。代入 ポリゴンをグループとしてまとめて扱う ば PoIyGroup のオプジェクトに Draw という やコヒ。ーが起きるときには , 持っているポ ためのクラスて、す。 PoIyGroup クラスのお ッセージを送ると , それが取り込んだす メ リゴンをすべてコピーするようにプログラ ムしてやる必要があります。 AbstructPolygon クラスの宣言 サンプルプログラムて、は足跡が 8 個の P01 ygon から構成されていて , これらをまとめ て PoIyGroup にしています。最初に左足の 足跡の PolyGroup を作り , これを元にコヒ。 ーコンストラクタて、大きさや角度の違う足 跡を作っています。 List 20 1 : / / = = ・ポリゴンの抽象クラス = 2 : class AbstructPolygon 4 : pub ⅱ c : 5 : AbstructPOIygon(void) virtual 6 : AbstructPoI ygon* MakeCl one(i nt angle virtual 7 : double sc 引 e = 1. の 8 : void ChangePaIette(word16 pal) 9 : virtual void FIipX(void) virtual void FlipY(void) v i r tual int Draw(Gscreen& gs, int X, int y) virtual 13 : int DrawWire(Gscreen& gs, virtual int y) = 0 : 〃輪郭線描画 int X, / / デストラクタ / / 自分のコピーを作成 〃描画色変更 / / X 座標の符号反転 / / Y 座標の符号反転 / / 描画 おわりに グラフィックライプラリを使ったふたっ のサンプルプログラムを紹介しました。 も っとも polydemo のほうは , グラフィックラ イプラリの使用例というよりはポリゴンを より抽象化して扱うことのて、きるライプラ リの可能性を示すような内容になっていま す。 P01ygon はまだまだ熟成が不足したクラス て、す。たとえば項点がリスト構造て、管理さ れているわりには , これらを操作するため の関数が乏しいといえます。また , 別のア プリケーションプログラムを作ることによ り , 拡張されていく余地を残しているとい えるて、しよう。 [ 参考文献 ] [ 1 ] 『注解 C 十十リファレンスマニュア ル』 , M. A. 工リス , B. ストラウストラ ップ著 , 足立高徳 , 小山裕司訳 , トッパ ン , 1992. [ 2 ] fEffectiveC 十十』 , スコット・マイヤ ーズ著 , 岩谷宏訳 , ソフトバンク , 1993. [ 3 ] 「入門グラフィックス』 , 佐藤義雄 , スキー , 1984. PO Ⅳ gon クラスの宣言 List = 2 次元座標ニ 2 : struct POint 4 : 6 : 8 : class Polygon ・ public AbstructP01ygon / / = 頂点の構造体ニ 10 : struct Vertex / / 頂点の座標 Point P ; / / 次の頂点へのポインタ Vertex* next : / / 頂点リストの最初の要素へのポインタ Vertex* head; Vertex* tai l; / / 頂点リストの最後の要素へのポインタ / / 頂点数 0rd16 count; Point 〃全ての頂点を囲む矩形の左下座標 Point / / 全ての頂点を囲む矩形の右上座標 ru; 20 : / / 描画パレット番号 当 0rd16 palette; 2 1 : public: PoIygon(word16 pal=7) ; 22 : / / コンストラクタ Polygon(const Polygon& poly, 23 : int angIe=0,double scale=l. の : 24 : / / コピーコンストラクタ POIygon(void); 25 : / / テストラクタ PoIygon& operator=(Polygon& poly) : 26 : 〃代入演算子 AbstructPoIygon* MakeCIone(int angle:(), 27 : double sca = 1. の : 28 : / / 自分のコピーを作成 CIear(void); VO i d 29 : / / 頂点リストの解放 Add(const Point& point); VO i d 30 : / / 頂点の追加 Add(const Point* points); VO i d / / 複数の頂点の追加 32 : VO i d ChangePalette(word16 pal); 33 : / / 描画色変更 FIipX(void); VO i d / / X 座標の符号反転 VO i d FlipY(void); / / Y 座標の符号反転 int Draw(Gscreen& gs, i nt 36 : X, int / / 描画 int DrawWire(Gscreen& gs, int X. int y); / / 輪享 5 線描画 38 : } ; / / x, y 座標 i n t X, y ; ニポリゴンニ 特集 実用グラフィック術 65