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

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

プログラミングについて
ホームページについて
キャドについて
電子カタログについて
書籍・雑誌
イベント
リンク集
DelphiXE3 [FMX] パス図形描画(4) 2014/05/26
 
パス図形描画(DrawPath)について、前回の続きです。
前回までは主に、直線・曲線描画関連について記述しました。今回はそれ以外のものについて記述します。
 
パス図形には直線・曲線による閉図形以外にも、四角形、円・楕円、といった独立した閉図形や、円弧・楕円弧を組み合わせた閉図形も追加する事が可能です。
 
その前に、曲線描画でもう1つ、ヘルプに記載がありませんが、QuadCurveToメソッドというものがあります。これについて一応確認しておきます。
TPathData.
QuadCurveTo
procedure QuadCurveTo(
 const ControlPoint, EndPoint: TPointF);
このトピックには現在ドキュメントが存在しません。「ノート」を利用してこのトピックの改良について話しあうことができます。
書式的には、SmoothCurveToメソッドと似ています。また、これまでのパターンのような、「QuadCurveToRel」なるメソッドは存在しない様子です。
 
[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(40,40));
 path.SmoothCurveTo(PointF(60,60),PointF(60,120));
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 20 ;
  DrawPath(path, 1.0);
 end;
 path.Clear ;
 path.MoveTo(PointF(20,20));
 path.LineTo(PointF(40,40));
 path.QuadCurveTo(PointF(60,60),PointF(60,120));
 with Canvas do begin
  Stroke.Color := claRed ;
  Stroke.Thickness := 10 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
保存・ビルド(コンパイル)・実行をすると下図のようになります。

 
QuadCurveは、SmoothCurveより緩やかな曲線のようですね。SmoothCurveがベジェ曲線(Bスプライン曲線)であれば、QuadCurveは、カーディナルスプライン曲線っぽい感じでしょうか?GDI+には、その機能が元々ありますし。
 
滑らかな曲線=スプライン曲線の種類は色々とありますし、それら全てが実装される訳でもありませんから、QuadCurveはそのうちの1つ、という事で余り気にしない事にします。
 
 
さて、パス図形には、直線・曲線以外に、四角形を追加する、という事も出来るようです。
TPathData.
AddRectangle
procedure AddRectangle(const ARect: TRectF;
 const XRadius, YRadius: Single;
 const ACorners: TCorners;
 const ACornerType: TCornerType
  = TCornerType.ctRound);
カスタマイズされた角を持つ四角形を、現在の TPathData に追加します。
 
ARectパラメータは、追加される rectangle を示します。
 
XRadius パラメータは、水平方向での、角からカスタマイズの始点への距離を示します。 XRadius の最大値は、四角形の幅の半分です。 これより大きい場合には、最大値が使用されます。
 
YRadius パラメータは、垂直方向での、角からカスタマイズの始点への距離を示します。 YRadius の最大値は、四角形の高さの半分です。 これより大きい場合には、最大値が使用されます。
 
ACorners パラメータは、カスタマイズを適用する角を示します。 すべての角にカスタマイズを適用するには、AllCorners 定数を使用します。
 
ACornerType パラメータは、角のタイプを示します。これは任意のパラメータで、デフォルト値は ctRound です。
 
AddRectangle は、楕円をシンプルな形に分割し、表現する必要のある Points に点を追加します。 追加される点は、異なる型を持っています。
最後の「楕円をシンプルな形に」というのは、ただの記述ミスでしょう。
 
ヘルプ内容を見た感じでは、四角形描画(DrawRect) とほぼ同じですね。ですので詳細はそちらに任せるとして、ざっとだけ確認しておきます。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
begin
 path := TPathData.Create ;
 path.MoveTo(PointF(20,20));
 path.LineTo(PointF(40,40));
 path.AddRectangle(RectF(40,40, 120,120),10,5,AllCorners);
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 20 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
保存・ビルド(コンパイル)・実行をすると下図のようになります。

想定通りですね。しかし、
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
begin
 path := TPathData.Create ;
 path.AddRectangle(RectF(40,40, 120,120),10,5,AllCorners);
 path.MoveTo(PointF(20,20));
 path.LineTo(PointF(40,40));
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 20 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
のように、作図順序を逆にすると、画面上には何も表示されなくなります。
 
しかし、
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
begin
 path := TPathData.Create ;
 path.AddRectangle(RectF(40,40, 120,120),10,5,AllCorners);
 path.MoveTo(PointF(20,20));
 path.LineTo(PointF(40,40));
 path.LineTo(PointF(40,20));
 path.ClosePath;
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 20 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
のように閉図形を追加するようにすれば、

のように正常に描画されるようです。
これは別段、AddRectangle のあとの開図形、という事に限定した話ではなく、例えば、MoveTo・LineTo・ClosePathをした図形(閉図形)の後の、開図形、でも同様に描画されません。パス図形で開図形と閉図形を一緒に扱う場合には注意が必要ですね。
 
 
次に、円・楕円をパス図形に追加するための AddEllipse メソッドです。
TPathData.
AddEllipse
procedure AddEllipse(const ARect: TRectF);
四角形の境界線で定義される楕円を、現在の TPathData に追加します。
 
ARect パラメータは、楕円の境界線を定義する構造を示します。
 
楕円の始点を移動させるには、AddEllipse を呼び出す前に、MoveTo または MoveToRel を呼び出します。
 
AddEllipse は、楕円をシンプルな形に分割し、表現する必要のある Points に点を追加します。
 
TPathData の終点を見つけるには、LastPoint メソッドを呼び出します。
という事で、これもヘルプ内容を見た感じでは、楕円描画(DrawEllipse) とほぼ同じですね。ですので詳細はそちらに任せるとして、ざっとだけ確認しておきます。下記のようにしてみます。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
begin
 path := TPathData.Create ;
 path.MoveTo(PointF(20,20));
 path.LineTo(PointF(40,40));
 path.AddEllipse(RectF(20,40, 120,100));
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 20 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
保存・ビルド(コンパイル)・実行をすると下図のようになります。

180°の付近の微妙な出っ張りが気になりますが、これは、
「Stroke.Cap := TStrokeCap.scRound ;」を入れておけば出ませんし、楕円では目立ちますが円の場合には目立ちません。ヘルプにある「楕円の始点」だろうか?と直前に MoveToメソッドを使用してみましたが変化は無い様子です。
 
 
次に、円弧・楕円弧をパス図形に追加するための AddArc メソッドです。
TPathData.
AddArc
procedure AddArc(const Center, Radius: TPointF;
 StartAngle, SweepAngle: Single);
現在の TPathData に、楕円形の曲線の一部として弧を追加します。
 
Center パラメータは、親の楕円の中心を示します。
 
Radiusパラメータの座標は、親の楕円の半短径を示します。
 ・Radius.x は、x 軸の半短径を定義します。
 ・Radius.y は、y 軸の半短径を定義します。
StartAngle は、X 軸の直線から、楕円の中心点(Center)を通り、孤の開始点で楕円と交差する直線まで、時計回りに計測した角度を(度数で)示します。
 
SweepAngle は、StartAngle パラメータから、楕円の中心点(Center)を通り、孤の終了点で楕円と交差する直線まで、時計回りに計測した角度を(度数で)示します。
 
現在の TPathData 内に、以前の線や弧があった場合には、線は、前の線分の終点と、今回の弧の始点をつなぐように、追加されます。
 
弧の始点を移動させるには、AddArc を呼び出す前に、MoveTo または MoveToRel を呼び出します。
 
AddArc は、円弧をシンプルな形に分割し、表現する必要のある Points に点を追加します。 追加される点は、異なる型を持っています。
 
TPathData の終点を見つけるには、LastPoint メソッドを呼び出します。
という事で、これもヘルプ内容を見た感じでは、楕円弧描画(DrawArc) とほぼ同じですね。ですので詳細はそちらに任せるとして、ざっとだけ確認しておきます。下記のように、意図的に、前述の線と離れた楕円弧の描画を行うようにしてみます。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
begin
 path := TPathData.Create ;
 path.MoveTo(PointF(20,20));
 path.LineTo(PointF(40,40));
 path.AddArc(PointF(70,70),PointF(50,30),0,90);
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 20 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
保存・ビルド(コンパイル)・実行をすると下図のようになります。

というように、前回点が、描画する円弧・楕円弧の始点と離れている場合には、前回点から始点までの直線で結ばれるようですね。
 
 
これでパスデータへの図形追加については終了です。
 
これ以外には、作成したパス図形を編集(変形)する機能があります。既に、FitToRect・Flatten・FlattenToPolygonメソッドについては記述済です。あと、平行移動を行う Translateメソッド、拡大縮小を行う Scaleメソッド、変換マトリックスを適用して変形を行う ApplyMatrixメソッド、について記述します。
 
 
TPathData.
Translate
procedure Translate(const dX, dY: Single);
現在の TPathData を平行移動します。
 
Translate は、現在の TPathData を、各軸上で指定された距離分移動します。
 
dX パラメータは、x 軸上の距離を示します。
 
dY パラメータは、y 軸上の距離を示します。
下記のように、パス図形を作成して描画させるようにしてみます。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
begin
 path := TPathData.Create ;
 path.AddArc(PointF(50,50),PointF(40,20),0,180);
 path.LineTo(PointF(50,10));
 path.ClosePath;
 // path.Translate(30,40);
 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.Translate(30,40);」の部分の「//」を除去して実行すると、下図のようになります。

Translateメソッドにより平行移動が行われたのが確認出来ます。
 
 
TPathData.
Scale
procedure Scale(const scaleX, scaleY: Single);
このトピックには現在ドキュメントが存在しません。「ノート」を利用してこのトピックの改良について話しあうことができます。
ヘルプ内容は記載されていませんが、想像は出来ます。
下記のように、パス図形を作成して描画させるようにしてみます。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
begin
 path := TPathData.Create ;
 path.AddArc(PointF(50,50),PointF(40,20),0,180);
 path.LineTo(PointF(50,10));
 path.ClosePath;
 // path.Scale(1.5,1.2);
 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.Scale(1.5,1.2);」の部分の「//」を除去して実行すると、下図のようになります。

Scaleメソッドにより拡大が行われたのが確認出来ます。
 
 
TPathData.
ApplyMatrix
procedure ApplyMatrix(const M: TMatrix);
変換マトリックスを、現在の TPathData に適用します。
 
M パラメータは、変換マトリックスを示します。
 
変換では、現在の TPathData を、平行移動(translate)、拡大縮小(scale)、回転(rotate)などさせることができます。
変換マトリックス TMatrix はヘルプで下記のように記載されています。
System.Types.TMatrix
TMatrix = record
 private
 public
  function Transform(const AVector: TVector): TVector;
  case Integer of
   0: (M: TMatrixArray;);
   1: (m11, m12, m13: Single;
     m21, m22, m23: Single;
     m31, m32, m33: Single);
 end;
 
System.Types.TMatrixArray
type TMatrixArray = array [0..2] of TVector;
 
行列を TVector の配列として表したものです。
 
System.Types.TVector
TVector = record
 private
  function Norm: Single;
  function RSqrt(const AValue: Single): Single;
  function Add(const AVector: TVector): TVector;
  function Subtract(const AVector: TVector): TVector;
 public
  constructor Create(const AX, AY, AW : Single); overload;
  constructor Create(const APoint : TPointF); overload;
  function Normalize: TVector;
  function Scale(const AFactor: Single): TVector;
  function Length: Single;
  function DotProduct(const AVector: TVector): Single;
  function Reflect(const AVector: TVector): TVector;
  function ToPointF: TPointF;
  class operator Add(const AFirstVector,
   ASecondVector : TVector) : TVector ;
  class operator Subtract(const AFirstVector,
   ASecondVector : TVector) : TVector ;
  class operator Equal(const AFirstVector,
   ASecondVector : TVector) : Boolean;
  class operator NotEqual(const AFirstVector,
   ASecondVector : TVector): Boolean;
  class operator Implicit(AVector : TVector) : TPointF;
  class operator Explicit(AVector : TVector) : TPointF;
  class operator Implicit(APointF : TPointF) : TVector;
  class operator Explicit(APointF : TPointF) : TVector;
  class operator Implicit(ASizeF : TSizeF) : TVector;
  class operator Explicit(ASizeF : TSizeF) : TVector;
  case Integer of
   0: (V: TVectorArray;);
   1: (X: Single;
     Y: Single;
     W: Single;);
 end;
 
変換マトリックスなので、まずは基本形の単位行列は
var
 m : TMatrix ;
・・・
 m.M[0].X := 1.0 ;
 m.M[0].Y := 0.0 ;
 m.M[0].W := 0.0 ;
 m.M[1].X := 0.0 ;
 m.M[1].Y := 1.0 ;
 m.M[1].W := 0.0 ;
 m.M[2].X := 0.0 ;
 m.M[2].Y := 0.0 ;
 m.M[2].W := 1.0 ;
又は
var
 m : TMatrix ;
・・・
 m.m11 := 1.0 ;
 m.m12 := 0.0 ;
 m.m13 := 0.0 ;
 m.m21 := 0.0 ;
 m.m22 := 1.0 ;
 m.m23 := 0.0 ;
 m.m31 := 0.0 ;
 m.m32 := 0.0 ;
 m.m33 := 1.0 ;
と書けますね。取り敢えず後者の方が書きやすいので、後者で書きます。
変換マトリックスでの平行移動は、m31 に X移動量、m32 に Y移動量を指定します。
下記のように、パス図形を作成して描画させるようにしてみます。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
 m : TMatrix ;
begin
 m.m11 := 1.0 ;
 m.m12 := 0.0 ;
 m.m13 := 0.0 ;
 m.m21 := 0.0 ;
 m.m22 := 1.0 ;
 m.m23 := 0.0 ;
 m.m31 := 30.0 ;
 m.m32 := 40.0 ;
 m.m33 := 1.0 ;
 
 path := TPathData.Create ;
 path.AddArc(PointF(50,50),PointF(40,20),0,180);
 path.LineTo(PointF(50,10));
 path.ClosePath;
 path.ApplyMatrix(m);
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 10 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
保存・ビルド(コンパイル)・実行をすると下図のようになります。

変換マトリックスでの拡大縮小は、m11 に X倍率、m22 に Y倍率を指定します。下記のように、パス図形を作成して描画させるようにしてみます。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
 m : TMatrix ;
begin
 m.m11 := 1.5 ;
 m.m12 := 0.0 ;
 m.m13 := 0.0 ;
 m.m21 := 0.0 ;
 m.m22 := 1.2 ;
 m.m23 := 0.0 ;
 m.m31 := 0.0 ;
 m.m32 := 0.0 ;
 m.m33 := 1.0 ;
 
 path := TPathData.Create ;
 path.AddArc(PointF(50,50),PointF(40,20),0,180);
 path.LineTo(PointF(50,10));
 path.ClosePath;
 path.ApplyMatrix(m);
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 10 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
保存・ビルド(コンパイル)・実行をすると下図のようになります。

勿論、平行移動と拡大縮小を同時に行う場合は、
 m.m11 := 1.5 ;
 m.m12 := 0.0 ;
 m.m13 := 0.0 ;
 m.m21 := 0.0 ;
 m.m22 := 1.2 ;
 m.m23 := 0.0 ;
 m.m31 := 5.0 ;
 m.m32 := 10.0 ;
 m.m33 := 1.0 ;
のように指定すれば良いだけです。
 
次に、回転(写像)を行うには、
 a := 回転角度[rad] ;
 m.m11 := Cos(a) ;
 m.m12 := Sin(a) ;
 m.m13 := 0.0 ;
 m.m21 :=-Sin(a) ;
 m.m22 := Cos(a) ;
 m.m23 := 0.0 ;
 m.m31 := 0.0 ;
 m.m32 := 0.0 ;
 m.m33 := 1.0 ;
を行う事になります。Y軸は下方向がプラスになりますから、時計回りの回転となります。反時計回りにしたければ角度をマイナス値にすれば簡単でしょう。回転の中心は勿論、(0,0)点となります。ですので、
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
 m : TMatrix ;
 a : double ;
begin
 path := TPathData.Create ;
 path.AddArc(PointF(50,50),PointF(40,20),0,180);
 path.LineTo(PointF(50,10));
 path.ClosePath;
 
 a := 45.0/180.0*Pi ;
 m.m11 := Cos(a) ;
 m.m12 := Sin(a) ;
 m.m13 := 0.0 ;
 m.m21 :=-Sin(a) ;
 m.m22 := Cos(a) ;
 m.m23 := 0.0 ;
 m.m31 := 0.0 ;
 m.m32 := 0.0 ;
 m.m33 := 1.0 ;
 path.ApplyMatrix(m);
 
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 10 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
とすれば下図のようになります。

例えば、パス図形内の楕円弧の中心点は(50,50)としていますから、この点(50,50)を中心に回転をしたい場合には、図形を平行移動で(-50,-50)をして、回転をして、平行移動(50,50) を行う、という作業を行う事になります。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
 m : TMatrix ;
 a : double ;
begin
 path := TPathData.Create ;
 path.AddArc(PointF(50,50),PointF(40,20),0,180);
 path.LineTo(PointF(50,10));
 path.ClosePath;
 
 m.m11 := 1.0 ;
 m.m12 := 0.0 ;
 m.m13 := 0.0 ;
 m.m21 := 0.0 ;
 m.m22 := 1.0 ;
 m.m23 := 0.0 ;
 m.m31 :=-50.0 ;
 m.m32 :=-50.0 ;
 m.m33 := 1.0 ;
 path.ApplyMatrix(m);
 
 a := 45.0/180.0*Pi ;
 m.m11 := Cos(a) ;
 m.m12 := Sin(a) ;
 m.m13 := 0.0 ;
 m.m21 :=-Sin(a) ;
 m.m22 := Cos(a) ;
 m.m23 := 0.0 ;
 m.m31 := 0.0 ;
 m.m32 := 0.0 ;
 m.m33 := 1.0 ;
 path.ApplyMatrix(m);
 
 m.m11 := 1.0 ;
 m.m12 := 0.0 ;
 m.m13 := 0.0 ;
 m.m21 := 0.0 ;
 m.m22 := 1.0 ;
 m.m23 := 0.0 ;
 m.m31 := 50.0 ;
 m.m32 := 50.0 ;
 m.m33 := 1.0 ;
 path.ApplyMatrix(m);
 
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 10 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
とすれば下図のようになります。

 
上記のように変換マトリックスの適用を3回もせず、通常は、アフィン変換を行って、1回で済ませるでしょうね。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
 m,m1 : TMatrix ;
 a : double ;
begin
 path := TPathData.Create ;
 path.AddArc(PointF(50,50),PointF(40,20),0,180);
 path.LineTo(PointF(50,10));
 path.ClosePath;
 
 m.m11 := 1.0 ;
 m.m12 := 0.0 ;
 m.m13 := 0.0 ;
 m.m21 := 0.0 ;
 m.m22 := 1.0 ;
 m.m23 := 0.0 ;
 m.m31 :=-50.0 ;
 m.m32 :=-50.0 ;
 m.m33 := 1.0 ;
 
 a := 45.0/180.0*Pi ;
 m1.m11 := Cos(a) ;
 m1.m12 := Sin(a) ;
 m1.m13 := 0.0 ;
 m1.m21 :=-Sin(a) ;
 m1.m22 := Cos(a) ;
 m1.m23 := 0.0 ;
 m1.m31 := 0.0 ;
 m1.m32 := 0.0 ;
 m1.m33 := 1.0 ;
 m := MatrixMultiply(m,m1) ;
 
 m1.m11 := 1.0 ;
 m1.m12 := 0.0 ;
 m1.m13 := 0.0 ;
 m1.m21 := 0.0 ;
 m1.m22 := 1.0 ;
 m1.m23 := 0.0 ;
 m1.m31 := 50.0 ;
 m1.m32 := 50.0 ;
 m1.m33 := 1.0 ;
 m := MatrixMultiply(m,m1) ;
 path.ApplyMatrix(m);
 
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 10 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
 
プログラムコードが助長になっていますので、通常は、平行移動を行う変換マトリックスを生成する関数、拡大縮小を行う変換マトリックスを生成する関数、回転を行う変換マトリックスを生成する関数、を用意しておいて、それを呼び出すでしょう。
関数を自作せずとも、
 FMX.Types.CreateTranslateMatrix
 FMX.Types.CreateScaleMatrix
 FMX.Types.CreateRotationMatrix
というルーチンは用意されているようです。
これを利用すれば、上記のプログラムは、下記のように書き直せます。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
 m,m1 : TMatrix ;
begin
 path := TPathData.Create ;
 path.AddArc(PointF(50,50),PointF(40,20),0,180);
 path.LineTo(PointF(50,10));
 path.ClosePath;
 
 m := CreateTranslateMatrix(-50,-50);
 m1:= CreateRotationMatrix(45.0/180.0*Pi);
 m := MatrixMultiply(m,m1) ;
 m1:= CreateTranslateMatrix(50,50);
 m := MatrixMultiply(m,m1) ;
 path.ApplyMatrix(m);
 
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 10 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
 
パス図形についての説明は、以上で終了です。
 
 
バッチファイル
BASIC
C言語のお勉強
拡張子な話
DOSプログラム
Delphi
>Dehi入門編
>Delphi2010
>DelphiXE3
▲2014/05/25
 2014/05/26
▼2014/05/27
 
シェアウェア
Script!World
データベース
 
お問い合わせ 
本サイトはリンクフリーです
リンクバナー
(C)Copyright 1999-2015. By AFsoft All Rights Reserved.