前頁は、独自拡張のハッチング(透過塗り)について考えてみました。今回も同じく、独自拡張によるハッチング(グラデーション塗り)について考えてみます。
グラデーション塗りは、線形グラデーション、放射グラデーション、があります。線形グラデーションは、開始点・終了点とそれぞれの色値・アルファ値を指定して、開始点から終了点へ徐々に色が変化していく表現方法です。
赤色→青色 のグラデーション例
放射グラデーションは、指定放射点の色と外形線側の色(周囲色)を指定しますが、GDI+では、外形線の状態により表現が変わってきます。
しかし残念ながら Direct2Dでのパスグラデーションの方法がよく分かりません。存在するのかしないのかも分かりませんが、楕円形状での放射グラデーションは可能である事は確認済みです。ですのでここでは、線形グラデーションと円形の放射グラデーションに対応する事とします。
但し注意しないといけないのは、いずれの場合も、指定範囲を超えている箇所の色は、想定外の塗り潰しをされてしまうって事です。例えば長方形に対してその内部に接するような円形のグラデーションを行った場合、長方形の四隅の楕円外の部分は、塗り潰されない、のではなく、青色になるのでもなく、GDI+の場合には、何故か、赤色になってしまったりします。線形グラデーションの場合も同様で、開始点・終了点が外形線の内側になっていると、その外側の色は、想定外の色になってしまいます。そのため開始点・終了点は不用意に指定出来ない状態となります。ですので、開始点・終了点を指定するのではなく、角度を指定するようにして、開始点・終了点は外形線の状態から算出するようにします。四角形グラデーションは、外形線の境界ボックスの大きさとし、円形グラデーションは、外形線の境界ボックスの中心を中心点とし、外形線の各頂点を範囲内に収めるような楕円形を算出する、という風にします。
ハッチング(グラデーション塗り)のデータ構造は下記のようにします。
UnitData.pas |
type
・・・
TDataHatch6 = record // 独自|ハッチング(グラデーション塗り)
exf : Boolean ; // 存在フラグ(True:有り False:無し)
Layer : Integer ; // レイヤ(1〜256)
Color1 : Integer ; // 色 (0:レイヤ色 1〜256)始点/放射点
Color2 : Integer ; // 色 (0:レイヤ色 1〜256)終点/周囲
Alpha : Integer ; // 塗りアルファ値(0〜255)
Gtype : Integer ; // グラデーションタイプ(0-2)
Angle : double ; // 線形グラデーション角度[°]
housya_x : double ; // 放射点X座標
housya_y : double ; // 放射点Y座標
out_id : Integer ; // 外形の複合曲線のフィーチャコード
Number : Integer ; // 中抜の閉領域数(0〜)
in_id : array of Integer; // 中抜の複合曲線のフィーチャコード
end;
・・・ |
データ登録は下記のようにします
UnitData.pas |
// ハッチング(グラデーション塗り) データ項目の追加登録
function TDataClass.AddDataHatch6(s:string;lay,col1,col2,al,
gtp:integer;an,hx,hy:double;
oid,num:integer;iid:array of integer) : Boolean ; |
なお、外形・中抜きの複合曲線部はグラデーション化しませんので、外形線・中抜き線が不要な場合には、それぞれの複合曲線定義で非表示にされると良いでしょう。
Gtype項目値に「0」を入れると線形グラデーションとなり、Angle値にグラデーションの角度[°]を指定します。例えば 30°とした場合、30°側がグラデーション終了点、反対側の210°側がグラデーション開始点となります。
Gtype項目値に「1」を入れると円形グラデーションとなり、放射点は中心点となります。「2」を入れても円形グラデーションですが、放射点は任意となり、(housya_x,housya_y)に座標値を指定します。
円形グラデーションは、外形線の最大・最小を取得し、境界ボックスを想定して、その境界ボックスに外接する角度0の楕円形を想定し、円形グラデーションを描画します。そのため、部分図・作図部品などにより変形されることになると、グラデーションの描画状態も変わってきますので注意して下さい。
ハッチング(グラデーション塗り)の描画は、恒例のように UnitDataGraph.pasにて行いますが、塗り部分が手続きDisplayPolygon4〜6 で行うようになっているだけで他はハッチング(塗り)とほぼ同じです。
UnitDataGraph.pas |
// ハッチング(グラデーション塗り)の表示
procedure DisplayHatch6(lay,cf,col1,col2,al,gtp:integer;
an,hx,hy:double;oid,num:integer;iid:array of integer;t:TMatrix);
var
c,cc1,cc2 : integer ;
i,j,co : integer ;
begin
with CData do begin
// 一応チェック
j := CCrvIDCheck(oid); // ID番号が有効かどうかをチェック
if (j = -1) then exit ; // ID番号無効
for i:=0 to num-1 do begin
j := CCrvIDCheck(iid[i]); // ID番号が有効かどうかをチェック
if (j = -1) then exit ; // ID番号無効
end;
// ハッチング領域図形のセット
zHArN := 1 + num ;
SetLength(zHAr,zHArN);
CCrvDataToHAr(oid,1); // 複合曲線定義 oid → 外郭部
j := 2 ;
for i:=0 to num-1 do begin
CCrvDataToHAr(iid[i],j); // 複合曲線定義 iid → 中抜き
Inc(j);
end;
// 塗りの表示
DisplayLayCol1(lay,col1,c,cc1);
DisplayLayCol1(lay,col2,c,cc2);
gp.G_SetWidth(1);
Case(gtp)of
0: DisplayPolygon4(cc1,cc2,al,an,t);
1: DisplayPolygon5(cc1,cc2,al,t);
2: DisplayPolygon6(cc1,cc2,al,hx,hy,t);
end;
// 外郭線の表示
j := CCrvIDCheck(oid);
if (cDef[j].invisibility = 1) then begin
co := cDef[j].Color ; if (cf = 1) then co := col;
DisplayHArLines(0,lay,co,cDef[j].Ltype,cDef[j].line_width,t);
end;
// 中抜き線の表示
for i:=0 to num-1 do begin
j := CCrvIDCheck(iid[i]);
if (cDef[j].invisibility = 1) then begin
co := cDef[j].Color ; if (cf = 1) then co := col;
DisplayHArLines(i+1,lay,co,cDef[j].Ltype,cDef[j].line_width,t);
end;
end;
// メモリ解放
DataClearHAr ;
end;
end; |
手続き DisplayPolygon4、DisplayPolygon5、DisplayPolygon6 はそれぞれ、線形グラデーション、円形グラデーション(放射点=中心)、円形グラデーション(放射点=任意)を実行するもので、その中から更に、実際の描画を行う UnitGraph.pas 内の G_PolygonA 手続き(メソッド)を呼び出します。
それでは、ハッチング(グラデーション塗り)の登録・描画のテストです。
まずは線形グラデーションから。30°、開始色=No2=赤、終了色=No3=緑、での作図結果です。
Unit1.pas |
// 線形グラデーション塗り
CData.AddDataHatch6('' ,1,2,3,255,0,30.0,0,0, 1,3,[2,3,4]);
CData.AddDataHatch6('部分図A',1,2,3,255,0,30.0,0,0, 1,3,[2,3,4]); |
アルファ値を 128 にして透過させてみます。
Unit1.pas |
// 線形グラデーション塗り
CData.AddDataHatch6('' ,1,2,3,128,0,30.0,0,0, 1,3,[2,3,4]);
CData.AddDataHatch6('部分図A',1,2,3,128,0,30.0,0,0, 1,3,[2,3,4]); |
次に円形グラデーションをしてみます。角度・放射点位置には何を入れても無効となりますので「0」にしています。
Unit1.pas |
// 円形グラデーション塗り 放射点=中心
CData.AddDataHatch6('' ,1,2,3,128,1,0,0,0, 1,3,[2,3,4]);
CData.AddDataHatch6('部分図A',1,2,3,128,1,0,0,0, 1,3,[2,3,4]); |
次に放射点指定の円形グラデーションをしてみます。放射点を(50,50)にしています。この位置は、左下の点マーカ「*」の位置に相当します。放射点が任意だからといっても余りに遠く離れた位置を指定するのは避けた方が良いと思われます。
Unit1.pas |
// 円形グラデーション塗り 放射点=中心
CData.AddDataHatch6('' ,1,2,3,128,2,0,50,50, 1,3,[2,3,4]);
CData.AddDataHatch6('部分図A',1,2,3,128,2,0,50,50, 1,3,[2,3,4]); |
グラデーション塗りは、これくらいにしておきます。GDI+だけに絞ると他にも色々な表現が出来ますし、Direct2Dだけに絞れば2色より以上の色を扱う事も可能ですが、双方で同じように扱えることを重視すると、このような感じではないかと思います。
それでは、ここまでのテストプログラムです。実行ファイル、gdiplus.dll、gdipフォルダは入っていません。ソースのみです。
|