通り芯作成(2)
このプログラムは基になる直線図形を数値入力による任意の間隔で配置していくプログラムです。
第2章 解説
InitDialogは数値入力を行うモダンダイアログのレイアウトを処理する手続きです。
ID:1を入力
OKボタンID:2を、「入力」表示とします。
キャンセルボタンID:2を、「終了」表示とします。
編集不可能なフィールドをID:3とします。とくにメッセージはいれていませんので空白です。
文字列型の編集フィールドをID:4とします。初期値は0とします。
「戻る」プッシュボタンをID:5とします。
{ 2009年 4月18日-1.0 著作・製作 Vectorworks Japan } 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 );