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

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

プログラミングについて
ホームページについて
キャドについて
電子カタログについて
書籍・雑誌
イベント
リンク集
DelphiXE3 [FMX] パス図形描画(3) 2014/05/25
 
パス図形描画(DrawPath)について、前回の続きです。
前回は主に、直線描画関連について記述しました。今回は主に曲線関連について記述します。
 
パスデータ文字列では、「C」「c」「S」「s」の指定がありましたが、勿論、これに相当するメソッドが存在します。
 
TPathData.
CurveTo
procedure CurveTo(const ControlPoint1,
 ControlPoint2, EndPoint: TPointF);
現在の TPathData に曲線を追加します。
 
曲線は、4 点で定義されます:
 ・始点 -- TPathData の終点。
 ・2 つの制御点。パラメータ ControlPoint1 と
  ControlPoint2 で指定される。
 ・終点。EndPoint パラメータで指定される。
CurveTo は、ControlPoint1、ControlPoint2、および EndPoint を、Points 配列に追加します。追加される点は、ppCurveTo 型です。
 
曲線の始点を移動させるには、CurveTo を呼び出す前に、MoveTo または MoveToRel メソッドを呼び出します。
 
TPathData の終点を見つけるには、LastPoint メソッドを呼び出します。
TPathData.
CurveToRel
procedure CurveToRel(const ControlPoint1,
 ControlPoint2, EndPoint: TPointF);
現在の TPathData に曲線を追加します。
 
曲線は、現在の TPathData の終点によって決まる 4 つの点で定義されます。
 
曲線の始点は、TPathData の終点です。
 
ControlPoint1 と ControlPoint2 パラメータの座標で、各軸上における、このカーブの 2 つの制御点それぞれの、現在の TPathData の終点への距離を示します。
 
EndPoint パラメータの座標では、各軸上における、この曲線の終点の、現在の TPathData の終点への距離を示します。
 
CurveToRel は、Points 配列に、曲線の 2 つの制御点と終点を追加します。追加された点それぞれの座標は、終点の座標と、パラメータで指定された対応点の座標を、足したものに等しくなります。追加される点は、ppCurveTo 型です。
 
曲線の始点を移動させるには、CurveToRel を呼び出す前に、MoveTo または MoveToRel メソッドを呼び出します。
 
TPathData の終点を見つけるには、LastPoint メソッドを呼び出します。
前回点を始点とし、制御点1・制御点2・終点を指定することにより曲線(おそらくはベジェ曲線)を描画します。直線の場合と同様、〜Rel は相対座標指定となります。
 
[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.CurveTo(PointF(100,50), PointF(120,80),
  PointF(120,120));
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 10 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
保存・ビルド(コンパイル)・実行をすると下図のようになります。

 
制御点2を始点〜終点の逆側に指定すると、ひねったような図形になります。
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.CurveTo(PointF(120,50), PointF(40,90),
  PointF(120,120));
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 10 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;
保存・ビルド(コンパイル)・実行をすると下図のようになります。

 
 
連続曲線(おそらくはBスプライン曲線)にする場合には、「S」「s」に相当する下記メソッドを利用します。
TPathData.
SmoothCurveTo
procedure SmoothCurveTo(
 const ControlPoint2, EndPoint: TPointF);
現在の TPathData にスムーズな曲線を追加します。
 
スムーズな曲線は、4 点で定義されます:
 ・始点 -- TPathData の終点。
 ・2 つの制御点。Points に 2 つより多く項目がある場合、最初の制御点は、曲線の始点と同じになり、そうでなければ、2 つ目の制御点と等しくなります。Control2 パラメータは、2 つ目の制御点を示します。
 ・終点。EndPoint パラメータで指定される。
SmoothCurveTo は、Points 配列に、制御点と曲線の終点を追加します。 追加される点は、ppCurveTo 型です。
 
曲線の始点を移動させるには、SmoothCurveTo を呼び出す前に、MoveTo または MoveToRel メソッドを呼び出します。
 
TPathData の終点を見つけるには、LastPoint メソッドを呼び出します。
TPathData.
SmoothCurveToRel
procedure SmoothCurveToRel(
 const ControlPoint2, EndPoint: TPointF);
現在の TPathData にスムーズな曲線を追加します。
 
スムーズな曲線は、現在の TPathData の終点によって決まる 4 つの点で定義されます。
 
曲線の始点は、TPathData の終点です。
 
Points に 2 つより多く項目がある場合、最初の制御点は始点と同じになり、そうでなければ、2 つ目の制御点と等しくなります。
 
ControlPoint2 パラメータの座標では、各軸上における、この曲線の 2 つ目の制御点の、現在の TPathData の終点への距離を示します。
 
EndPoint パラメータの座標では、各軸上における、この曲線の終点の、現在の TPathData の終点への距離を示します。
 
SmoothCurveToRel は、Points 配列に、制御点と曲線の終点を追加します。 点それぞれの座標は、現在の TPathData の終点の座標と、パラメータで指定された対応点の座標を、足したものに等しくなります。 追加される点は、ppCurveTo 型です。
 
曲線の始点を移動させるには、SmoothCurveToRel を呼び出す前に、MoveTo または MoveToRel メソッドを呼び出します。
 
TPathData の終点を見つけるには、LastPoint メソッドを呼び出します。
 
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
begin
 path := TPathData.Create ;
 path.MoveTo(PointF(20,20));
 path.LineTo(PointF(100,20));
 path.CurveTo(PointF(140,20), PointF(100,30),
  PointF(120,40));
 path.SmoothCurveTo(PointF(100,100),PointF(120,120));
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 10 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;




Bスプライン曲線の場合は通常、4点区間のうち、第2点〜第3点の区間を連続して描画していく事になりますが(最初は第1点〜第3点、最後は第2点〜第4点を描画する)、このメソッドでは常に 〜第4点の描画を行う、という所に違いはあります。そのため、若干、描画の仕方がBスプライン曲線の感覚とは違ってくるようには思いますが、”スムーズな曲線”の描画を行うという点においては十分に利用価値があると思われます。
 
 
次に、この”スムーズな曲線”を、例えば、点列データやDXF等のデータとして出力したいが、曲線状態では 曲線上の座標点が分からない、という何とも出来ない状況となってしまいます。そういった場合、連続直線状態になるよう線分補間を行う事ができれば、各頂点の座標を読み取ればOKという事になりますが、それを行うのが、Flattenメソッドです。
TPathData.
Flatten
procedure Flatten(const Flatness: Single = 0.25);
現在の TPathData 内の各曲線を、つながれた直線の分節群に変換します。
 
Flatness パラメータは、曲線とその平坦化近似値との間での、許容できる最大エラー数を示します。デフォルトでは、0.25 です。平坦化値を減らすと、近似値での直線の分節数が増えます。
それでは先のプログラムで試してみましょう。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
begin
 path := TPathData.Create ;
 path.MoveTo(PointF(20,20));
 path.LineTo(PointF(100,20));
 path.CurveTo(PointF(140,20), PointF(100,30),
  PointF(120,40));
 path.SmoothCurveTo(PointF(100,100),PointF(120,120));
 path.Flatten ;
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 10 ;
  DrawPath(path, 1.0);
 end;
 path.Free ;
end;


ぱっと見、よく分かりません。
引数省略時の引数デフォルト値は、0.25 のようですが、「path.Flatten(5);」としてみると

のようになり、少しカクカクしました。更に「path.Flatten(10);」としてみると、

という具合に、更にカクカクしました。
カクカクするという事は、粗いけれどもデータ量が少ない、という事を示します。スムーズに見える=綺麗に見える場合は、その分、データ量が多い、という事になります。この引数値が具体的にどういう値なのか?というのは分かりませんが。。。
 
点データは、パスデータ文字列=Dataプロパティを参照する事で可能です。Flattenメソッドを利用しない場合に「ShowMessage(path.Data);」とすると

となりますが、「path.Flatten(5);」を行なった場合は

のようになります。
 
また、
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
 i : integer ;
 s : string ;
begin
 path := TPathData.Create ;
 path.MoveTo(PointF(20,20));
 path.LineTo(PointF(100,20));
 path.CurveTo(PointF(140,20), PointF(100,30),
  PointF(120,40));
 path.SmoothCurveTo(PointF(100,100),PointF(120,120));
 path.Flatten(5) ;
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 10 ;
  DrawPath(path, 1.0);
 end;
 s := '';
 for i := 0 to path.Count-1 do
  s := s+ FloatToStr(path.Points[i].Point.X) + ' , '
     + FloatToStr(path.Points[i].Point.Y) + #13 + #10;
 ShowMessage(s);
 path.Free ;
end;
のようにした場合は下図画面が表示されます。

座標点がダブっている場合は、それを除去するようプログラミングしておけばいいでしょう。
あるいは、FlattenToPolygon メソッドを利用する方法です。
TPathData.
FlattenToPolygon
function FlattenToPolygon(
 var Polygon: TPolygon;
 const Flatness: Single = 0.25): TPointF;
現在の TPathData を、つながれた直線の分節群に変換し、TPolygon としてそのシーケンスを返します。
 
Polygon パラメータは、返される変数です。これは、変換の結果です。
 
Flatness は任意パラメータで、曲線とその平坦化近似値との間での、許容できる最大エラー数を示します。 デフォルトでは、0.25 です。 平坦化値を減らすと、近似値での直線の分節数が増えます。
プログラムは下記のようになります。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
 po : TPolygon;
 i : integer ;
 s : string ;
begin
 path := TPathData.Create ;
 path.MoveTo(PointF(20,20));
 path.LineTo(PointF(100,20));
 path.CurveTo(PointF(140,20), PointF(100,30),
  PointF(120,40));
 path.SmoothCurveTo(PointF(100,100),PointF(120,120));
 path.FlattenToPolygon(po,5) ;
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 10 ;
  DrawPolygon(po, 1.0);
 end;
 s := '';
 for i := 0 to path.Count-1 do
  s := s+ FloatToStr(po[i].X) + ' , '
     + FloatToStr(po[i].Y) + #13 + #10;
 ShowMessage(s);
 path.Free ;
end;
 
 
パス図形は、[Shapes]内の パス図形(Path)と同様、指定枠内にフィット表示させる事が出来ます。それを行うのが、FitToRectメソッドです。
TPathData.
FitToRect
procedure FitToRect(const ARect: TRectF);
現在の TPathData を、指定された四角形領域に合致するよう、平行移動または拡大縮小します。ARect パラメータは、パスを中に収める四角形領域を示します。
下記のようにしてみます。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
 path : TPathData ;
 i : integer ;
 s : string ;
begin
 path := TPathData.Create ;
 path.MoveTo(PointF(20,20));
 path.LineTo(PointF(100,20));
 path.CurveTo(PointF(140,20), PointF(100,30),
  PointF(120,40));
 path.SmoothCurveTo(PointF(100,100),PointF(120,120));
 path.Flatten(5) ;
 path.FitToRect(RectF(20,20,60,60));
 with Canvas do begin
  Clear(claWhite);
  Stroke.Kind := TBrushKind.bkSolid ;
  Stroke.Color := claBlue ;
  Stroke.Thickness := 10 ;
  DrawPath(path, 1.0);
 end;
 s := '';
 for i := 0 to path.Count-1 do
  s := s+ FloatToStr(path.Points[i].Point.X) + ' , '
     + FloatToStr(path.Points[i].Point.Y) + #13 + #10;
 ShowMessage(s);
 path.Free ;
end;
保存・コンパイル・実行を行うと下図のように表示されます。

 

点列データ内容も変化しているのが分かります。
 
 
バッチファイル
BASIC
C言語のお勉強
拡張子な話
DOSプログラム
Delphi
>Dehi入門編
>Delphi2010
>DelphiXE3
▲2014/05/24
 2014/05/25
▼2014/05/26
 
シェアウェア
Script!World
データベース
 
お問い合わせ 
本サイトはリンクフリーです
リンクバナー
(C)Copyright 1999-2015. By AFsoft All Rights Reserved.