6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DelphiAdvent Calendar 2024

Day 6

[Delphi] 矢印描いたことある?

Last updated at Posted at 2024-12-05

矢印描いたことありますか?

そこそこ長くプログラマをやってるんですけどプログラムで矢印描く事がなくて、ついこないだ初めて矢印描いたんですよね。仕事で。

そうしたら思いのほかキレイな式になったよというお話しです。

最初の考え方

最初、こういう風に考えたんですよね。
矢印の

image.png

矢頭の部分、そのまま伸ばして角度を求めればいけそう、と。
それが下の図です。

image.png

それぞれの角度を求めると↓こう

image.png

線 A の角度:θ - τ
線 B の角度:θ + τ

式がめっちゃキレイに纏まりました!

考え方を変える

それで、導出された式を見ていてアレ?これもっと簡単に考えられたんじゃね?ってなりました。

↓のように角θからτ分を引けば A の角度になるし、足せば B の角度になるんです。

image.png

こんなに単純に考えられたなんて!
出てくる結論は同じなんですけど、考え方で求め方の簡単さが違うんだなあ。みつを。

矢印を描くコントロール

導出された式を使って矢印を描く 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 のように、線をどう引くかをプロパティで指定できた方がいいですね。

描画結果

描画するとこんな感じです。

image.png

描画例
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;

最後に

式がキレイに纏まるとすごく気持ちがいいですね!

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?