矢印を描く


始点を(x1,y1),終点を(x2,y2),矢じりの長さおよび広がりをそれぞれLおよびθとしたとき, 矢じりの先端の座標(x,y)および(x',y')は次式で求まる.

x = x2 - L cos ψ
y = y2 - L sin ψ

x' = x2 - L sin( π/2 - ρ )
y' = y2 - L cos( π/2 - ρ )

ここで,ψ = φ - θ,ρ = φ + θ および φ = arctan | ( y2 - y1 ) / ( x2 - x1 ) | である. 実際には始点と終点の位置関係によりいくつかの場合分けが必要である.

以下のDrawArrow手続きは,始点,終点,矢じりの長さと広がり(度),矢じりの形状(線か三角)を指定して 矢印を描く.

type
   TArrowHead = ( ahLine, ahTriangle );

procedure DrawArrow( Canvas: TCanvas; X1, Y1, X2, Y2: Integer;
                     Len: Integer; Theta: Double; Head: TArrowHead );
var
  Pai, Psi, Rho: Double;
  Points: array[ 0..2 ] of TPoint;
begin
   Theta := Theta * Pi / 180;
   Pai := ArcTan( Abs( ( Y1 - Y2 ) / ( X2 - X1 ) ) );
   Psi := Pai - Theta;
   Rho := Pai + Theta;
   if X2 >= X1 then
   begin
      Points[ 0 ].x := Round( X2 - Len * Cos( Psi ) );
      Points[ 2 ].x := Round( X2 - Len * Sin( Pi / 2 - Rho ) );
   end
   else begin
      Points[ 0 ].x := Round( X2 + Len * Cos( Psi ) );
      Points[ 2 ].x := Round( X2 + Len * Sin( Pi / 2 - Rho ) );
   end;
   if Y2 >= Y1 then
   begin
      Points[ 0 ].y := Round( Y2 - Len * Sin( Psi ) );
      Points[ 2 ].y := Round( Y2 - Len * Cos( Pi / 2 - Rho ) );
   end
   else begin
      Points[ 0 ].y := Round( Y2 + Len * Sin( Psi ) );
      Points[ 2 ].y := Round( Y2 + Len * Cos( Pi / 2 - Rho ) );
   end;
   Points[ 1 ].x := X2;
   Points[ 1 ].y := Y2;
   Canvas.MoveTo( X1, Y1 );
   Canvas.LineTo( X2, Y2 );
   if Head = ahLine then
      Canvas.Polyline( Points )
   else
      Canvas.Polygon( Points );
end;

以下はDrawArrowを使ったプログラムの実行例である. 拙作のTColorComboBoxを使っている.


お問い合わせはメールにて: akasaka@klc.ac.jp

戻る
SEO [PR] 爆速!無料ブログ 無料ホームページ開設 無料ライブ放送