研究開発

矢印を描く(2)

第2章 コマンドパレットで書く

前回の仕様をふまえて、プログラムを書いていきましょう。

ただし、いきなりツール(オブジェクト)化するのではなく、コマンドパレットを使ってトライ&エラーをしてから仕上げにいきます。

なお、オブジェクトが最終的な形ですので、クリックアプションについてはコードを書く必要がありません。
さらに、オブジェクトの原点(ローカル座標)はクリックアクションの1点目(グローバル)となりますので、
矢印の始点は(0,0)として考えます。 回転角度についてはシンボル図形を描くときと同じで、回転して描かれることは意識せずとも回転図形はVectorworksが自動的に描いてくれますので0度のときを意識して座標計算すればよいのです。

また、パラメータに関しては、予めCONSTを用意してパラメータ変数を意識して書きます。

PROCEDURE DrawArrow;
CONST
	PLineLength = 100.0;
	PWidth = 10.0;
	PAngle = 90.0;
	PHead = 10.0;

矢印のタイプもパラメータとしてデフォルトを設定しておきます。また、タイプについても宣言しておくと後々、オブジェクト化のときにソースの変更が少なくてすみます。

オブジェクトのパラメータは宣言した名称にPが付いた参照名としてプログラム内では使われますので、頭にPを付けた宣言で書いておきます。kで宣言してあるのはオブジェクト化したときにタイプの種類として、定数にしておくとプログラムが見やすくなります。

PROCEDURE DrawArrow;
CONST
	PLineLength = 100.0;
	PWidth = 10.0;
	PAngle = 90.0;
	PHead = 10.0;
	PType = '始点に矢印';
	kSTART = '始点に矢印';
	kEND = '終点に矢印';
VAR

描画する図形は多角形ですので、その座標を納めておくためにPOINT型で配列宣言しておきます。頂点数は最大10点あればよいでしょう。あとは、配列を参照するための添字としてiiと、頂点数を取っておくnumGridを変数宣言しておきます。

VAR
	xy : ARRAY[1..10] OF POINT;
	ii, numGrid : INTEGER;
BEGIN

プログラムの流れは、タイプに応じて頂点の座標を計算します、そして多角形を描く。
初期状態では始点に矢印「 PType = 'start';」となっていますが、終点に矢印と両端に矢印のときと分岐命令IF文を使って3パターン用意します。
まず、始点が矢印の場合、

1は(0,0)です。
2、7のX座標は矢印の大きさPHead
Y座標は矢印の大きさPHeadと角度PAngleを使ってタンジェント計算から導けます。
3、6のX座標は矢印の大きさPHead
Y座標は幅PWidthの1/2。
4、5のX座標は矢印全体の長さPLineLength。
Y座標は幅PWidthの1/2。
そして頂点数は7個です。

BEGIN
	IF PType = kSTART THEN
	BEGIN
		xy[1].x := 0.0;
		xy[1].y := 0.0;
		xy[2].x := PHead;
		xy[2].y := -PHead * Tan(Deg2Rad(PAngle/2.0));
		xy[3].x := PHead;
		xy[3].y := -PWidth / 2.0;
		xy[4].x := PLineLength;
		xy[4].y := -PWidth / 2.0;
		xy[5].x := PLineLength;
		xy[5].y := PWidth / 2.0;
		xy[6].x := PHead;
		xy[6].y := PWidth / 2.0;
		xy[7].x := PHead;
		xy[7].y := PHead * Tan(Deg2Rad(PAngle/2.0));

		numGrid := 7;
	END

つぎに、終点が矢印の場合、

1、7のX座標は0。
Y座標は幅PWidthの1/2。
2、6のX座標は矢印全体の長さPLineLengthから矢印の大きさを引いたところです。
Y座標は幅PWidthの1/2。
3、5のX座標は矢印全体の長さPLineLengthから矢印の大きさを引いたところです。
Y座標は矢印の大きさPHeadと角度PAngleを使ってタンジェント計算から導けます。
4のX座標は矢印全体の長さPLineLength。
Y座標は0。
そして頂点数は7個です。

END
	ELSE IF PType = kEND THEN
	BEGIN
		xy[1].x := 0.0;
		xy[1].y := -PWidth / 2.0;
		xy[2].x := PLineLength - PHead;
		xy[2].y := -PWidth / 2.0;
		xy[3].x := PLineLength - PHead;
		xy[3].y := -PHead * Tan(Deg2Rad(PAngle/2.0));
		xy[4].x := PLineLength;
		xy[4].y := 0.0;
		xy[5].x := PLineLength - PHead;
		xy[5].y := PHead * Tan(Deg2Rad(PAngle/2.0));
		xy[6].x := PLineLength - PHead;
		xy[6].y := PWidth / 2.0;
		xy[7].x := 0.0;
		xy[7].y := PWidth / 2.0;

		numGrid := 7;
	END

最後に、両端が矢印の場合、
始点が矢印のときと終点が矢印のときを組み合わせればよいわけです。
そして頂点数は10個です。

END
	ELSE
	BEGIN
		xy[1].x := 0.0;
		xy[1].y := 0.0;
		xy[2].x := PHead;
		xy[2].y := -PHead * Tan(Deg2Rad(PAngle/2.0));
		xy[3].x := PHead;
		xy[3].y := -PWidth / 2.0;
		xy[4].x := PLineLength - PHead;
		xy[4].y := -PWidth / 2.0;
		xy[5].x := PLineLength - PHead;
		xy[5].y := -PHead * Tan(Deg2Rad(PAngle/2.0));
		xy[6].x := PLineLength;
		xy[6].y := 0.0;
		xy[7].x := PLineLength - PHead;
		xy[7].y := PHead * Tan(Deg2Rad(PAngle/2.0));
		xy[8].x := PLineLength - PHead;
		xy[8].y := PWidth / 2.0;
		xy[9].x := PHead;
		xy[9].y := PWidth / 2.0;
		xy[10].x := PHead;
		xy[10].y := PHead * Tan(Deg2Rad(PAngle/2.0));

		numGrid := 10;
	END;

あとは多角形に頂点を追加していくだけです。多角形は予め手続きClosePolyを使って閉じておきましょう。

END;

	ClosePoly;
	BeginPoly;

	FOR ii := 1 TO numGrid DO
	BEGIN
		AddPoint( xy[ii].x, xy[ii].y );
	END;

	EndPoly;

END;
Run( DrawArrow );

コマンドを実行すると、始点側に矢印の付いた多角形が描画されます。
終点側のテストは
PType = 'end';

と変更することで、終点側に矢印の付いた多角形が描画されます。
両端に矢印がある場合のテストは
PType = 'start-end';
とすると 両端に矢印の付いた多角形が描画されます。
すなわち、始点でも終点でもない場合は両端(ELSE)の処理ということになります。

PROCEDURE DrawArrow;
CONST
	PLineLength = 100.0;
	PWidth = 10.0;
	PAngle = 90.0;
	PHead = 10.0;
	PType = '始点に矢印';
	kSTART = '始点に矢印';
	kEND = '終点に矢印';
VAR
	xy : ARRAY[1..10] OF POINT;
	ii, numGrid : INTEGER;
BEGIN

	IF PType = kSTART THEN
	BEGIN
		xy[1].x := 0.0;
		xy[1].y := 0.0;
		xy[2].x := PHead;
		xy[2].y := -PHead * Tan(Deg2Rad(PAngle/2.0));
		xy[3].x := PHead;
		xy[3].y := -PWidth / 2.0;
		xy[4].x := PLineLength;
		xy[4].y := -PWidth / 2.0;
		xy[5].x := PLineLength;
		xy[5].y := PWidth / 2.0;
		xy[6].x := PHead;
		xy[6].y := PWidth / 2.0;
		xy[7].x := PHead;
		xy[7].y := PHead * Tan(Deg2Rad(PAngle/2.0));

		numGrid := 7;
	END
	ELSE IF PType = kEND THEN
	BEGIN
		xy[1].x := 0.0;
		xy[1].y := -PWidth / 2.0;
		xy[2].x := PLineLength - PHead;
		xy[2].y := -PWidth / 2.0;
		xy[3].x := PLineLength - PHead;
		xy[3].y := -PHead * Tan(Deg2Rad(PAngle/2.0));
		xy[4].x := PLineLength;
		xy[4].y := 0.0;
		xy[5].x := PLineLength - PHead;
		xy[5].y := PHead * Tan(Deg2Rad(PAngle/2.0));
		xy[6].x := PLineLength - PHead;
		xy[6].y := PWidth / 2.0;
		xy[7].x := 0.0;
		xy[7].y := PWidth / 2.0;

		numGrid := 7;
	END
	ELSE
	BEGIN
		xy[1].x := 0.0;
		xy[1].y := 0.0;
		xy[2].x := PHead;
		xy[2].y := -PHead * Tan(Deg2Rad(PAngle/2.0));
		xy[3].x := PHead;
		xy[3].y := -PWidth / 2.0;
		xy[4].x := PLineLength - PHead;
		xy[4].y := -PWidth / 2.0;
		xy[5].x := PLineLength - PHead;
		xy[5].y := -PHead * Tan(Deg2Rad(PAngle/2.0));
		xy[6].x := PLineLength;
		xy[6].y := 0.0;
		xy[7].x := PLineLength - PHead;
		xy[7].y := PHead * Tan(Deg2Rad(PAngle/2.0));
		xy[8].x := PLineLength - PHead;
		xy[8].y := PWidth / 2.0;
		xy[9].x := PHead;
		xy[9].y := PWidth / 2.0;
		xy[10].x := PHead;
		xy[10].y := PHead * Tan(Deg2Rad(PAngle/2.0));

		numGrid := 10;
	END;

	ClosePoly;
	BeginPoly;

	FOR ii := 1 TO numGrid DO
	BEGIN
		AddPoint( xy[ii].x, xy[ii].y );
	END;

	EndPoly;

END;
Run( DrawArrow );