AFsoft WebSite(エーエフソフト・ウェブサイト)
 

オペレーティング・システムについて

プログラミングについて
ホームページについて
キャドについて
電子カタログについて
書籍・雑誌
イベント
リンク集
DelphiXE3 [FMX] パス図形描画(2) 2014/05/24
 
パス図形描画(DrawPath)について、前回の続きです。
前回は、パスデータ文字列(TPathData.Data)によりパス図形描画を行なっていましたが、今回は、TPathData の各メソッドにより図形描画を行ってみます。
 
パス図形描画は、パスデータに複数の図形描画機能を溜め込んでいって、DrawPathメソッドによって1度にそれらを描画しましょう、という感じです。複数図形の一体化みたいな感じですね。一体化する事によって、図形全体の色や線種、結合部の処理等が出来るようになります。
複数の描画系メソッドを連続して何度も実行する、という事でも同様に可能なのですが、特にグラデーションや結合部の処理は(独自に特殊なプログラミングをしない限りは)行えないので、この違いは明確になってきます。

上はパス図形、下は直線4本
この程度なら多角形描画でも可能ですが、もっと複雑な場合は…
 
まずは、パスデータをクリアする所から。
TPathData.
Clear
procedure Clear;
現在の TPathData をクリアします。
 
Clearは、現在の TPathData からすべての形を削除します。
Points の配列をクリアします。
1つの TPathData型のオブジェクトを何度も使いまわすような場合には必須になりますね。
 
一番簡単な図形は、直線から構成される図形でしょう。直線の作図は、VCL・WindowsGDIでの描画と同じく、MoveTo、LineTo で行います。
TPathData.
MoveTo
procedure MoveTo(const P: TPointF);
指定された点を、現在の TPathData の最後に追加します。
 
MoveTo を使用すると、現在の TPathData に追加される新しい要素の始点をカスタマイズすることができます。
P パラメータは、追加される TPointF を示します。
MoveTo は、指定された点を、Points 配列に追加します。追加される点は、ppMoveTo 型です。
 
TPathData がキャンバス上で描画される際、ppMoveTo 点とその前の点は、視覚的にはつながれていません(これらの間に線は描画されません)。TPathData がアニメーション内で使用される場合、アニメーションされるオブジェクトは、ある点から別の点へジャンプしませんが、それらの点をつなぐ線上を移動していきます。
TPathData.
LineTo
procedure LineTo(const P: TPointF);
現在の TPathData に直線を追加します。
 
直線は、TPathData の終点、および、指定された点によって定義されます。
P パラメータは、追加される直線の終点を示します。
直線の始点を移動させるには、LineTo を呼び出す前に、MoveTo または MoveToRel を呼び出します。
 
LineTo は、P を Points に追加します。追加される点は、ppLineTo 型です。
TPathData の終点を見つけるには、LastPoint メソッドを呼び出します。
直線を描画するのは、LineToメソッドです。前回点から、指定点へ結ぶ直線を作図します。そして指定点が次回描画の前回点となります。MoveToメソッドは、前回点を指定するだけで直線描画は行いません。2点指定で直線を描画する際の開始点となります。
 
[Shapes]内のペイントボックス(PaintBox)を配置し、ClipChildernプロパティを True にしておきます。uses節に「UIConsts」を追記します。

OnPaintイベントハンドラを下記のようにしてみます。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
begin
 path := TPathData.Create ;
 path.MoveTo(PointF(20,20));
 path.LineTo(PointF(120,120));
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 20 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
保存・ビルド(コンパイル)・実行をすると下図のようになります。

 
連続直線にする場合は、LineToメソッドを連続して記述していけば可能です。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
begin
 path := TPathData.Create ;
 path.MoveTo(PointF(20,20));
 path.LineTo(PointF(120,120));
 path.LineTo(PointF(120,20));
 path.LineTo(PointF(20,120));
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 20 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
とすれば下図のようになります。

 
 
MoveTo・LineToメソッドでの引数は絶対座標指定ですが、前回点からの相対座標指定をしたい場合は、MoveToRel・LineToRelメソッドを利用します。
TPathData.
MoveToRel
procedure MoveToRel(const P: TPointF);
指定された TpointF を現在の TPathData に追加します。
 
MoveToRel を使用すると、現在の TPathData に追加される新しい要素の始点をカスタマイズすることができます。
 
P パラメータの座標は、各軸上の現在の TPathData の終点への距離を示します。
 
MoveToRel は、新しい点を Points 配列に追加します。この座標は、終点の座標と P の座標との合計に等しくなります。 追加される点は、ppMoveTo 型です。
 
追加された点は、TPathData に追加される要素の新しい始点となります。TPathData がキャンバス上で描画される際、ppMoveTo 点とその前の点は、視覚的にはつながれていません(これらの間に線は描画されません)。 TPathData がアニメーション内で使用される場合、アニメーションされるオブジェクトは、ある点から別の点へジャンプしませんが、それらの点をつなぐ線上を移動していきます。
 
TPathData の終点を見つけるには、LastPoint メソッドを呼び出します。
TPathData.
LineToRel
procedure LineToRel(const P: TPointF);
現在の TPathData に直線を追加します。
 
直線は、TPathData の終点、および、指定されたパラメータで決まる点によって定義されます。
 
P パラメータの座標は、各軸上の現在の TPathData の終点への距離を示します。
 
LineToRel は、直線の終点を Points 配列に追加します。 この座標は、終点の座標と P の座標との合計に等しくなります。追加される点は、ppLineTo 型です。
 
直線の始点を移動させるには、LineToRel を呼び出す前に、MoveTo または MoveToRel メソッドを呼び出します。
 
TPathData の終点を見つけるには、LastPoint メソッドを呼び出します。
相対座標指定は、CADソフト的に言えばオフセット位置に相当しますが、前回点から、これくらい離れた位置、という場合に利用します。例えば
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
begin
 path := TPathData.Create ;
 path.MoveTo(PointF(20,20));
 path.LineTo(PointF(60,60));
 path.MoveToRel(PointF(20,30));
 path.LineToRel(PointF(40,50));
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 20 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
のようにすれば下図のように描画されます。

 
 
直線描画にて、水平線を描画する場合は、Y座標値は前回点と同じになりますので、いちいちY座標値を書きたくない、という事はあるかもしれません。垂直線の場合も同様に、X座標値が同じになります。そういう場合には別のメソッドが用意されています。
TPathData.
HLineTo
procedure HLineTo(const X: Single);
現在の TPathData に直線を追加します。
 
直線は、TPathData の終点、および、指定されたパラメータで決まる点によって定義されます。
 
X パラメータは、直線の終点の X 座標を示します。
 
HLineTo は、直線の終点を Points 配列に追加します。直線の終点は、TPathData の終点から、X に等しい X 座標を持つ点へと、水平に移動します。追加される点は、ppLineTo 型です。
 
直線の始点を移動させるには、HLineTo を呼び出す前に、MoveTo または MoveToRel メソッドを呼び出します。
 
TPathData の終点を見つけるには、LastPoint メソッドを呼び出します。
TPathData.
HLineToRel
procedure HLineToRel(const X: Single);
現在の TPathData に直線を追加します。
 
直線は、TPathData の終点、および、指定されたパラメータで決まる点によって定義されます。
 
X パラメータは、X 軸上の現在の TPathData の終点への距離を示します。
 
HLineToRel は、直線の終点を Points 配列に追加します。 直線の終点は、TPathData の終点まで、X に等しい距離単位で、水平に移動します。追加される点は、ppLineTo 型です。
 
直線の始点を移動させるには、HLineToRel を呼び出す前に、MoveTo または MoveToRel メソッドを呼び出します。
 
TPathData の終点を見つけるには、LastPoint メソッドを呼び出します。
 
TPathData.
VLineTo
procedure VLineTo(const Y: Single);
現在の TPathData に直線を追加します。
 
直線は、TPathData の終点、および、指定されたパラメータで決まる点によって定義されます。
 
Y パラメータは、直線の終点の Y 座標を示します。
 
VLineTo は、直線の終点を Points 配列に追加します。 直線の終点は、TPathData の終点から、Y に等しい Y 座標を持つ点へと、垂直に移動します。 追加される点は、ppLineTo 型です。
 
直線の始点を移動させるには、VLineTo を呼び出す前に、MoveTo または MoveToRel メソッドを呼び出します。
 
TPathData の終点を見つけるには、LastPoint メソッドを呼び出します。
TPathData.
VLineToRel
procedure VLineToRel(const Y: Single);
現在の TPathData に直線を追加します。
 
直線は、TPathData の終点、および、指定されたパラメータで決まる点によって定義されます。
 
Y パラメータは、Y 軸上の現在の TPathData の終点への距離を示します。
 
VLineToRel は、直線の終点を Points 配列に追加します。 直線の終点は、TPathData の終点まで、Y に等しい距離単位で、垂直に移動します。 追加される点は、ppLineTo 型です。
 
直線の始点を移動させるには、VLineToRel を呼び出す前に、MoveTo または MoveToRel メソッドを呼び出します。
 
TPathData の終点を見つけるには、LastPoint メソッドを呼び出します。
という訳で、水平線が HLineTo・HLineToRel、垂直線が VLineTo・VLineToRelとなります。〜Rel は上記同様、相対座標指定です。
 
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
begin
 path := TPathData.Create ;
 path.MoveTo(PointF(20,20));
 path.HLineTo(40);
 path.VLineTo(40);
 path.HLineToRel(60);
 path.VLineToRel(60);
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 10 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
のようにすれば下図のように描画されます。

 
 
上記ヘルプには、「TPathData の終点を見つけるには、LastPoint メソッドを呼び出します。」と書かれてあるので、これを確認してみます。前回点を忘れた場合や、相対座標を何度も使って座標値が分かりにくいというような場合には、利用出来ると思われます。
TPathData.
LastPoint
function LastPoint: TPointF;
現在の TPathData の終点を返します。LastPoint は、TPointF を返します。
以下のように確認してみます。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
 pt : TPointF ;
begin
 path := TPathData.Create ;
 path.MoveTo(PointF(20,20));
 path.HLineTo(40);
 path.VLineTo(40);
 path.HLineToRel(60);
 path.VLineToRel(60);
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 10 ;
  DrawPath(path, 1.0);
 end;
 pt := path.LastPoint ;
 ShowMessage(FloatToStr(pt.X)+' , '+FloatToStr(pt.Y));
 path.Free ;
end;
保存・コンパイル・実行すると、下記画面が表示されます。

点(20,20)→点(40,20)→点(40,40)→点(100,40)→点(100,100)ですので最終点=最後の前回点は点(100,100)ですから確認出来ました。
 
 
次に、閉じた図形(閉図形)を描画する場合には、どうするかです。一番最初の点を指定して描画する、という訳にはいきません。第1点&最終点の結合部処理が行われないからです。パスデータ文字列を指定する場合には「Z」文字を利用しましたが、メソッドで実装する場合には、ClosePath メソッドを利用します。
TPathData.
ClosePath
procedure ClosePath;
現在の TPathData を閉じます。
 
閉じられた path とは、始点と LastPoint が同一のパスを指します。
 
TPathData の始点は、Points 配列の最初の点です。
 
ClosePath は、TPathData の始点を、Points 配列の最後に追加します。追加される点は、ppClose 型です。
以下のように確認してみます。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
begin
 path := TPathData.Create ;
 path.MoveTo(PointF(20,20));
 path.HLineTo(40);
 path.VLineTo(40);
 path.HLineToRel(60);
 path.VLineToRel(60);
 path.closePath;
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 10 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
保存・コンパイル・実行すると、下記画面が表示されます。

もし「path.closePath;」ではなく「path.LineTo(PointF(20,20));」となっていると、下図のようになってしまいます。

 
 
1つの TPathData オブジェクト型変数を使いまわす場合、手続き・関数内でのローカル変数の場合はさほど必要ないかもしれませんが、グローバル変数の場合には、その変数の中身が空かどうかを確認したい場合が出てくるかもしれません。例えば、空でない場合には、クリアする、等です。
TPathData.
IsEmpty
function IsEmpty: Boolean;
TPathData が空かどうかを示します。
 
IsEmpty は、TPathData が空の場合に True を、そうでなければ False を返します。
 
TPathData は、Count が 0 の際に空になります。
 
 
パス図形の境界ボックスを取得する関数が用意されているようです。お絵描きソフト等で図形を選択して移動・複写するような場合に、図形を囲うような四角形を描画する等で利用出来るかもしれません。
TPathData.
GetBounds
function GetBounds: TRectF;
現在の TPathData の境界四角形を返します。パスが描画される際、GetBounds が返す四角形は、ペン筆の太さやスタイルには影響を受けません。
下記のようにして確認してみます。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
 r : TRectF ;
begin
 path := TPathData.Create ;
 path.MoveTo(PointF(20,20));
 path.HLineTo(40);
 path.VLineTo(40);
 path.HLineToRel(60);
 path.VLineToRel(60);
 path.closePath;
 r := path.GetBounds ;
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 10 ;
  DrawPath(path, 1.0);
  
  Stroke.Color := claRed ;
  Stroke.Thickness := 1 ;
  DrawRect(r,0,0,AllCorners,1.0);
 end;
 path.Free ;
end;
保存・コンパイル・実行すると、下記画面が表示されます。

線幅や結合部処理などは考慮されない様子ですね。
 
 
バッチファイル
BASIC
C言語のお勉強
拡張子な話
DOSプログラム
Delphi
>Dehi入門編
>Delphi2010
>DelphiXE3
▲2014/05/23
 2014/05/24
▼2014/05/25
 
シェアウェア
Script!World
データベース
 
お問い合わせ 
本サイトはリンクフリーです
リンクバナー
(C)Copyright 1999-2015. By AFsoft All Rights Reserved.