矢印描いたことありますか?
そこそこ長くプログラマをやってるんですけどプログラムで矢印描く事がなくて、ついこないだ初めて矢印描いたんですよね。仕事で。
そうしたら思いのほかキレイな式になったよというお話しです。
最初の考え方
最初、こういう風に考えたんですよね。
矢印の
矢頭の部分、そのまま伸ばして角度を求めればいけそう、と。
それが下の図です。
それぞれの角度を求めると↓こう
線 A の角度:θ - τ
線 B の角度:θ + τ
式がめっちゃキレイに纏まりました!
考え方を変える
それで、導出された式を見ていてアレ?これもっと簡単に考えられたんじゃね?ってなりました。
↓のように角θからτ分を引けば A の角度になるし、足せば B の角度になるんです。
こんなに単純に考えられたなんて!
出てくる結論は同じなんですけど、考え方で求め方の簡単さが違うんだなあ。みつを。
矢印を描くコントロール
導出された式を使って矢印を描く TArrowLine というコントロールを作りました。
下記、ソース全文です。
Paint メソッドの中で左下から右上に向かって矢印を描います。
unit PK.Graphic.ArrowLine;
interface
uses
System.SysUtils
, System.Types
, FMX.Controls
, FMX.Graphics
, FMX.Objects
;
type
TArrowLine = class(TShape)
public
procedure Paint; override;
end;
implementation
uses
System.Math;
{ TArrowLine }
procedure TArrowLine.Paint;
const
// 矢印の部分の長さ
ARROW_SIZE = 8;
// 矢印の角度
ARROW_HEAD_TAU = Pi / 6;
begin
var C := Canvas;
C.Stroke.Assign(Stroke);
C.Fill.Assign(Fill);
// 本体の線の描画
var X1 := 0.0;
var Y1 := Height;
var X2 := Width;
var Y2 := 0.0;
C.DrawLine(PointF(X1, Y1), PointF(X2, Y2), 1);
// 角度・座標の計算
var Theta := ArcTan2(Y2 - Y1, X2 - X1);
var TauA := Theta - ARROW_HEAD_TAU;
var XA := X2 - ARROW_SIZE * Cos(TauA);
var YA := Y2 - ARROW_SIZE * Sin(TauA);
var TauB := Theta + ARROW_HEAD_TAU;
var XB := X2 - ARROW_SIZE * Cos(TauB);
var YB := Y2 - ARROW_SIZE * Sin(TauB);
// 矢印部分を塗りつぶす
C.FillPolygon([PointF(XA, YA), PointF(X2, Y2), PointF(XB, YB)], 1);
end;
end.
コントロールをもっとちゃんと作る場合は左下から右上だけの線じゃなく TLine.LineType のように、線をどう引くかをプロパティで指定できた方がいいですね。
描画結果
描画するとこんな感じです。
描画例
procedure TForm1.FormCreate(Sender: TObject);
begin
var AL := TArrowLine.Create(Self);
AL.Align := TAlignLayout.Client;
// 赤に設定
AL.Stroke.Color := TAlphaColors.Red;
AL.Fill.Color := TAlphaColors.Red;
AL.Parent := Panel1;
end;
最後に
式がキレイに纏まるとすごく気持ちがいいですね!