HSP3 プログラミングの基礎W
前へ 目次へ 次へ 

(7) グラフィックス 2

◆ 四角形内部のハッチ描画命令(g_hatch)作成

 ハッチ(hatch)とは、辞書で引くと「線影」とある。図のように、線で影をつけることである。
 棒グラフなどは、四角形の塗りつぶしで描画して区別するとカラフルで見やすくなる。しかし、そのグラフを白黒で印刷するとすべてがグレーになり、区別がしにくくなる。このように白黒で印刷する場合、色で塗りつぶすのではなく、ハッチにすると区別がしやすくなる。
 ここでは、指定した四角形内部にハッチを描画する命令g_hatchを作成する。

 命令g_hatchの仕様は次の通りとする。

g_hatch 左上座標x,左上座標y,右下座標x,右下座標y,ハッチの種類

 ハッチの種類はビットパターンで指定する。ハッチの種類は次の通りとする。

ハッチ(8ドット間隔) ハッチ(最初4ドット、以降8ドット間隔)
1(0x01) 45度斜線右上がり 16(0x10) 45度斜線右上がり
2(0x02) 45度斜線左上がり 32(0x20) 45度斜線左上がり
4(0x04) 垂直 64(0x40) 垂直
8(0x08) 水平 128(0x80) 水平

 ハッチの種類をビットパターンで指定することによって、3(0x03)を指定するとクロス状のハッチを描画することができる。このように値を加算していくことでいろいろな模様のハッチを描画させることができる。



水平ハッチ

サンプル水平のハッチを描画する。(ハッチの種類=4(0x04))

#module
#deffunc g_circle int x, int y, int r, int nuri
 <<省略>>
#deffunc g_line int x1, int y1, int x2, int y2, int pat
 <<省略>>
#deffunc g_box int x1, int y1, int x2, int y2, int pat
 <<省略>>
#deffunc g_hatch int x1, int y1, int x2, int y2, int hc
;
;g_hatch  左上座標x,左上座標y,右下座標x,右下座標y,ハッチの種類
;  ハッチの種類は、ビットパターンで指定する。
;
    spc = 8        ;間隔(8ドット)
    if hc and 4 {           ;水平ハッチ
        if y1 < y2 : yy1 = y1 : yy2 = y2 : else : yy1 = y2 : yy2 = y1
        repeat , 1
            yy = cnt * spc + yy1   ;Y座標計算
            if yy > yy2 : break
            line x1, yy, x2, yy    ;描画
        loop
    }
    return
#global
    color 255, 0, 0     ;赤
    g_box 50, 50, 200, 200
    color 0, 0, 0       ;黒
    g_hatch 50, 50, 200, 200, 0x04
    stop

実行水平のハッチが描画される。四角形内部であることがわかりやすいように赤色で四角形を描画している。

 四角形の左上と右下の座標を逆に指定したときも処理できるようにif文でy1, y2の小さい方をyy1に、大きい方をyy2に格納している。
 水平の直線を描画するので、x座標はx1からx2までの範囲である。
 y座標は左上のyy1から8ドット間隔で描画するので、1本目は「1(本目)*8(ドット)+yy1」、2本目は「2(本目)*8(ドット)+yy1」となる。
 直線は繰り返しで描画している。繰り返しの終了はyyがyy2を超えたときである。

試してみよう最初の間隔だけ4ドットの水平のハッチ描画を追加する。(ハッチの種類=64(0x40))

#module
#deffunc g_circle int x, int y, int r, int nuri
 <<省略>>
#deffunc g_line int x1, int y1, int x2, int y2, int pat
 <<省略>>
#deffunc g_box int x1, int y1, int x2, int y2, int pat
 <<省略>>
#deffunc g_hatch int x1, int y1, int x2, int y2, int hc
;
;g_hatch  左上座標x,左上座標y,右下座標x,右下座標y,ハッチの種類
;  ハッチの種類は、ビットパターンで指定する。
;
    spc = 8        ;間隔(8ドット)
    if hc and 4 {           ;水平ハッチ
        if y1 < y2 : yy1 = y1 : yy2 = y2 : else : yy1 = y2 : yy2 = y1
        repeat , 1
            yy = cnt * spc + yy1   ;Y座標計算
            if yy > yy2 : break
            line x1, yy, x2, yy    ;描画
        loop
    }
    if hc and 0x40 {        ;水平ハッチ
        if y1 < y2 : yy1 = y1 : yy2 = y2 : else : yy1 = y2 : yy2 = y1
        repeat , 1
            yy = cnt * spc + yy1 - (spc / 2)    ;Y座標計算
            if yy > yy2 : break
            line x1, yy, x2, yy                 ;描画
        loop
    }
    return
#global
    color 255, 0, 0     ;赤
    g_box 50, 50, 200, 200
    color 0, 0, 0       ;黒
    g_hatch 50, 50, 200, 200, 0x40
    stop

実行水平のハッチが描画される。

 8ドット間隔のハッチ描画処理でy座標を4ドット(通常間隔8ドットの半分)ずらすだけである。Y座標計算でspc/2だけ減算している。左上のy座標より4ドット上から描画しているのでY軸方向の長さはspc/2だけ加算している。
 最後のハッチが四角形の下辺と重なっている。これを防ぐには、if文を次のようにする。

    if yy >= y2 : break
 ハッチの種類として、0x44を指定すると間隔の狭い(4ドット)水平のハッチが描画できる。



垂直ハッチ

サンプル垂直のハッチを描画する。(ハッチの種類=8(0x08)と128(0x80))

#module
#deffunc g_circle int x, int y, int r, int nuri
 <<省略>>
#deffunc g_line int x1, int y1, int x2, int y2, int pat
 <<省略>>
#deffunc g_box int x1, int y1, int x2, int y2, int pat
 <<省略>>
#deffunc g_hatch int x1, int y1, int x2, int y2, int hc
;
;g_hatch  左上座標x,左上座標y,右下座標x,右下座標y,ハッチの種類
;  ハッチの種類は、ビットパターンで指定する。
;
    spc = 8        ;間隔(8ドット)
    if hc and 4 {       ;水平ハッチ
      <<省略>> 
    }
    if hc and 0x40 {    ;水平ハッチ
      <<省略>> 
    }
    if hc and 8 {       ;垂直ハッチ
        if x1 < x2 : xx1 = x1 : xx2 = x2: else : xx1 = x2 : xx2 = x1
        repeat , 1
            xx = cnt * spc + xx1    ;X座標計算
            if xx > xx2 : break
            line xx, y1, xx, y2
        loop
    }
    if hc and 0x80 {        ;垂直ハッチ
        if x1 < x2 : xx1 = x1 : xx2 = x2: else : xx1 = x2 : xx2 = x1
        repeat , 1
            xx = cnt * spc + xx1 - (spc / 2)    ;X座標計算
            if xx > xx2 : break
            line xx, y1, xx, y2
        loop
    }
    return
#global
    color 255, 0, 0     ;赤
    g_box 50, 50, 200, 200
    color 0, 0, 0       ;黒
    g_hatch 50, 50, 200, 200, 0x08
    stop

実行垂直のハッチが描画される。

 水平ハッチ処理のX座標とY座標の役割が入れ替わっているだけである。



斜線(右上がり)ハッチ

サンプル斜線(右上がり)のハッチを描画する。(ハッチの種類=1(0x01))

#module
#deffunc g_circle int x, int y, int r, int nuri
 <<省略>>
#deffunc g_line int x1, int y1, int x2, int y2, int pat
 <<省略>>
#deffunc g_box int x1, int y1, int x2, int y2, int pat
 <<省略>>
#deffunc g_hatch int x1, int y1, int x2, int y2, int hc
;
;g_hatch  左上座標x,左上座標y,右下座標x,右下座標y,ハッチの種類
;  ハッチの種類は、ビットパターンで指定する。
;
    spc = 8    ;間隔(8ドット)
    if hc and 4 {       ;水平ハッチ
      <<省略>> 
    }
    if hc and 0x40 {    ;水平ハッチ
      <<省略>> 
    }
    if hc and 8 {       ;垂直ハッチ
      <<省略>> 
    }
    if hc and 0x80 {    ;垂直ハッチ
      <<省略>> 
    }
    if hc and 1 {       ;斜線右上がりハッチ
        repeat , 1
            xx1 = x1 + cnt * spc    ;斜線の始点
            yy1 = y1
            xx2 = x1                ;斜線の終点
            yy2 = y1 + cnt * spc
            if xx1 > x2 : yy1 = yy1 + xx1 - x2 : xx1 = x2  ;※1
            if yy2 > y2 : xx2 = xx2 + yy2 - y2 : yy2 = y2  ;※2
            if xx2 > x2 : break
            line xx1, yy1, xx2, yy2
        loop
    }
    return
#global
    color 255, 0, 0     ;赤
    g_box 50, 50, 200, 200
    color 0, 0, 0       ;黒
    g_hatch 50, 50, 200, 200, 0x01
    stop

実行斜線(右上がり)のハッチが描画される。

 図は、斜線の始点(水色)と終点(青色)を示している。
 始点のy座標はy1で変化しない。始点のx座標はspc(=8)ドットずつ右にずれていくのでx1に加算していく。
 終点のx座標はx1で変化しない。終点のy座標はspc(=8)ドットずつ下にずれていくのでy1に加算していく。
 斜線の始点(xx1, yy1)と終点(xx2, yy2)は次の式で求まる。cntはrepeatの回数で1で初期化する。

    xx1 = x1 + cnt * spc
    yy1 = y1
    xx2 = x1
    yy2 = y1 + cnt * spc

 このままでは、図のように四角形(赤色)の範囲を超えるので、計算値の修正が必要である。
 まず、始点のxx1がx2を超えたとき、xx1がx2を超えた分だけすなわち xx1-x2 ドットだけy方向にもずれるので、修正した始点は次の式で求まる。(※1)

    yy1 = yy1 + xx1 - x2
    xx1 = x2

 同じように、終点のyy2がy2を超えたとき、yy2がy2を超えた分だけx方向にもずれる。修正した始点は次の式で求まる。(※2)

    xx2 = xx2 + yy2 - y2
    yy2 = y2

 繰り返しの終了は、終点のxx2がx2を超えたときである。

試してみよう最初の間隔だけが4ドットの斜線(右上がり)のハッチを追加せよ。(ハッチの種類=16(0x10))

 斜線の始点(xx1, yy1)と終点(xx2, yy2)の座標計算を次のようにするだけである。

    xx1 = x1 + cnt * spc - (spc / 2)
    yy1 = y1
    xx2 = x1
    yy2 = y1 + cnt * spc - (spc / 2)



斜線(左上がり)ハッチ

サンプル斜線(左上がり)のハッチを描画する。(ハッチの種類=2(0x02)と32(0x20))

#module
#deffunc g_circle int x, int y, int r, int nuri
 <<省略>>
#deffunc g_line int x1, int y1, int x2, int y2, int pat
 <<省略>>
#deffunc g_box int x1, int y1, int x2, int y2, int pat
 <<省略>>
#deffunc g_hatch int x1, int y1, int x2, int y2, int hc
;
;g_hatch  左上座標x,左上座標y,右下座標x,右下座標y,ハッチの種類
;  ハッチの種類は、ビットパターンで指定する。
;
    spc = 8    ;間隔(8ドット)
    if hc and 4 {       ;水平ハッチ
      <<省略>> 
    }
    if hc and 0x40 {    ;水平ハッチ
      <<省略>> 
    }
    if hc and 8 {       ;垂直ハッチ
      <<省略>> 
    }
    if hc and 0x80 {    ;垂直ハッチ
      <<省略>> 
    }
    if hc and 1 {       ;斜線右上がりハッチ
      <<省略>> 
    }
    if hc and 0x10 {    ;斜線右上がりハッチ
      <<省略>> 
    }
    if hc and 2 {       ;斜線左上がりハッチ
        repeat , 1
            xx1 = x1 + cnt * spc    ;斜線の始点
            yy1 = y2
            xx2 = x1                ;斜線の終点
            yy2 = y2 - cnt * spc
            if xx1 > x2 : yy1 = yy1 - xx1 + x2 : xx1 = x2
            if yy2 < y1 : xx2 = xx2 + y1 - yy2 : yy2 = y1
            if xx2 > x2 : break
            line xx1, yy1, xx2, yy2
        loop
    }
    if hc and 0x20 {    ;斜線左上がりハッチ
        repeat , 1
            xx1 = x1 + cnt * spc - (spc / 2)    ;斜線の始点
            yy1 = y2
            xx2 = x1                            ;斜線の終点
            yy2 = y2 - cnt * spc + (spc / 2)
            if xx1 > x2 : yy1 = yy1 - xx1 + x2 : xx1 = x2
            if yy2 < y1 : xx2 = xx2 + y1 - yy2 : yy2 = y1
            if xx2 > x2 : break
            line xx1, yy1, xx2, yy2
        loop
    }
    return
#global
    color 255, 0, 0     ;赤
    g_box 50, 50, 200, 200
    color 0, 0, 0       ;黒
    g_hatch 50, 50, 200, 200, 0x02
    stop

実行斜線(左上がり)のハッチが描画される。

 サンプルと図を見ながら考えてみよう。

 以上でハッチの描画命令は完成である。

 

前へ 目次へ 次へ 
2006  © Hiroshi Masuda 

 

 

inserted by FC2 system