研究開発

通り芯作成(2)

第2章

このプログラムは基になる直線図形を数値入力による任意の間隔で配置していくプログラムです。

InitDialogは数値入力を行うモダンダイアログのレイアウトを処理する手続きです。
ID:1を入力
OKボタンID:2を、「入力」表示とします。
キャンセルボタンID:2を、「終了」表示とします。
編集不可能なフィールドをID:3とします。とくにメッセージはいれていませんので空白です。
文字列型の編集フィールドをID:4とします。初期値は0とします。
「戻る」プッシュボタンをID:5とします。

{
2009年 4月18日-1.0
著作・製作 エーアンドエー株式会社
}
PROCEDURE baseline;
LABEL
	9999;
CONST
	kOkButton = 1;
	kCancelButton = 2;
VAR
	dialogid : LONGINT;
	objH : HANDLE;
	theStr : STRING;
	p1X, p1Y, p2X, p2Y : REAL;
	vect : VECTOR;
	ang, leng : REAL;
	done : BOOLEAN;
	firstObjH : HANDLE;

	PROCEDURE InitDialog;
	BEGIN
		dialogID := CreateLayout( 'コマンドライン', FALSE, '入力', '終了' );

		CreateStaticText( dialogID, 3, '', 50 );
		SetFirstLayoutItem( dialogID, 3 );
		CreateEditText( dialogID, 4, '0', 50 );
		SetBelowItem( dialogID, 3, 4, 0, 0 );
		CreatePushButton( dialogID, 5, '戻る' );
		SetBelowItem( dialogID, 4, 5, 0, 0 );
	END;

CallDialogは数値入力を行うモダンダイアログのイベントループを処理する手続きです。
ダイアログが開かれたときに、選択されている図形が削除可能でない場合、戻るボタンをグレーにします。
入力ボタンを押した場合、編集フィールドの文字列を返します。
戻るボタンを押した場合、選択されている図形を削除し、一つ前の図形を選択状態にします。このとき選択されている図形が削除可能でない場合、戻るボタンをグレーにします。


	PROCEDURE CallDialog ( VAR key:LONGINT; Value:LONGINT );
	VAR
		objH : HANDLE;
	BEGIN
		CASE key OF
			SetupDialogC: 
			BEGIN
				IF firstObjH = FSActLayer THEN
				BEGIN
					SetItemEnable( 5, FALSE );
				END;
			END;
			kOkButton: 
 			BEGIN
			 theStr := GetField( 4 );
			END;
			kCancelButton: 
			BEGIN
			END;
			5: 
			BEGIN
				objH := PrevObj ( FSActLayer );
				DelObject ( FSActLayer );
				SetSelect (objH);
				RedrawAll;
				IF firstObjH = FSActLayer THEN
				BEGIN
					SetItemEnable( 5, FALSE );
				END;
			END;
		END;
	END;

StrAnalysisは文字列を先頭から分析して、数値を返す関数です。
基本はカンマが出てくるまでを数値として返します。
アスタリスクの場合には数値を回数分返します。


	FUNCTION StrAnalysis : REAL;
	LABEL
		666;
	VAR
		sDummy : STRING;
		comma, asterisk, num : INTEGER;
	BEGIN
666:
		comma := Pos ( ',', theStr );
		IF comma = 0 THEN
		BEGIN
			comma := Len ( theStr );
		END
		ELSE IF comma = 1 THEN
		BEGIN
			Delete ( theStr, 1, 1 );
			GOTO 666;
		END;
		asterisk := Pos ( '*', theStr );
		IF asterisk = 0 THEN
		BEGIN
			asterisk := Len ( theStr );
		END;
		IF comma = asterisk THEN
		BEGIN
			StrAnalysis := Str2Num ( theStr );
			theStr := '';
		END
		ELSE IF comma > asterisk THEN
		BEGIN
			StrAnalysis := Str2Num ( Copy ( theStr, 1, Pos ( '*', theStr ) - 1 ) );
			num := Str2Num ( Copy ( theStr, Pos ( '*', theStr ) + 1,1 ));
			IF num > 1 THEN
			BEGIN
					Delete ( theStr, Pos ( '*', theStr )+1, 1 );
					sDummy := Num2Str ( 0, num-1 );
					Insert ( sDummy,theStr, Pos ( '*', theStr )+1 );
			END
			ELSE
			BEGIN
					Delete ( theStr, 1, Pos ( '*', theStr )+1 );
			END;
		END
		ELSE
		BEGIN
			StrAnalysis := Str2Num ( Copy ( theStr, 1, Pos ( ',', theStr ) - 1 ) );
			Delete ( theStr, 1, Pos ( ',', theStr ) );
		END;

	END;

ここからメインルーチンです。
図形が一つだけ選択されているかを判定し、そうでなければなければ警告をします。
一つだけ選択されていても直線でない場合には警告をします。

BEGIN
	IF NumSObj( ActLayer ) = 1 THEN
	BEGIN
		IF GetType( FSActLayer ) <> 2 THEN
		BEGIN
			AlrtDialog( '基になる線が選択されていません。' );
			GOTO 9999;
		END;
	END
	ELSE
	BEGIN
		AlrtDialog( '基になる線が選択されていません。' );
		GOTO 9999;
	END;

数値入力ループに入る前に選択されている直線のハンドルを記憶しておきます。戻るボタンのオンオフのためです。
doneはつねにTRUEですので、このループは永久に回ります。終了ボタンを押すか、0を入力したときループから抜けます。


	firstObjH := FSActLayer;

	done := TRUE;
	WHILE done DO
	BEGIN
		InitDialog;
		IF RunLayoutDialog( dialogID, CallDialog ) = 2 THEN
		BEGIN
			GOTO 9999;
		END;

数値入力から返ってきた文字列がなくなるまで、繰り返します。
StrAnalysis関数から数値をもらい、今選択されている直線からオフセットする位置を計算します。


		WHILE Len( theStr ) > 0 DO
		BEGIN
			leng := StrAnalysis;
			IF leng <= 0.0 THEN
			BEGIN
				GOTO 9999;
			END;
			GetSegPt1( FSActLayer, p1X, p1Y );
			GetSegPt2( FSActLayer, p2X, p2Y );
			vect.x := p2X - p1X;
			vect.y := p2Y - p1Y;
			vect.z := 0.0;
			ang := Vec2Ang( vect );

選択されている直線の角度によって、右側にオフセットするか、左側にオフセットするかを判断します。
計算結果を元に選択図形をコピーします。

			IF ( ang >= -45.0 ) AND ( ang <= 45 ) THEN
			BEGIN
				vect := Ang2Vec( ang+90, leng );
			END
			ELSE
			BEGIN
				vect := Ang2Vec( ang-90, leng );
			END;
			Duplicate( vect.x,vect.y );
			RedrawAll;
		END;
	END;
9999:END;
Run ( baseline );