研究開発

はじめてのVectorScript

第4章 ハンドルを制する者はVSを制す

ハンドルとはVectorworksのすべてのオブジェクト(直線、四角形、円、多角形、文字、グループ、シンボル、ワークシート、レイヤ、etc.)の持っている情報に対してアクセスするためのアドレスです。それを扱うためにはHANDLE型の変数を使います。HANDLE型は他の変数と違って足したり引いたりするものではなく、手続き、関数の引数になりオブジェクトの情報を得るために使います。

・アクティブなレイヤ上にある選択された図形のタイプを調べる。

PROCEDURE sample401;
VAR
	objH : HANDLE;
	theType : INTEGER;
BEGIN
	objH := FSActLayer;
	theType := GetTypeN( objH );
	Message( theType );
END;
RUN( sample401 );
関数FSActLayerはアクティブなレイヤ上で選択されている最も上の図形のハンドルを返します。
アクティブなレイヤとは、関数FSActLayerの命令が実行されたとき、編集中のレイヤのことです。
レイヤは実行中でも表示状態や順序等を変えることが可能なため、アクティブなレイヤは実行前の状態ではなく実行中のそのときになるので注意が必要です。
選択されている最も上の図形とは、例えばVectorworksで手動で四角をいくつか描いたとします。図形はあとから描いたものが上に重なっていきます。このとき最も下にある図形がプログラムから見た場合、レイヤ上で最も上にある図形ということになります。さらに複数選択されている場合などに選択されている図形の中でも下に描かれた図形が最も上にある図形と考えます。もちろん、上か下かは前後関係メニューで変更可能なため、描いた順というのはあまり重要ではありません。
関数GetTypeNは図形の種類を数字で返します。引数には調べたい図形のハンドルを渡します。番号についてはFunction ReferenceのAppendix(アペンディックス)に書かれています。直線:2、四角形:3、長円:4、...というように。ここでは選択されている図形が何であるかを表示するだけですが、選択構造(IF文)で場合分けすることで、直線だったら処理する。それ以外だったら、「直線を選んで実行してください」と表示するとかに使ったりします。

・描いた図形の幅と高さを調べる。
PROCEDURE sample402;
VAR
	widhtR : REAL;
	heightR : REAL;
BEGIN
	Rect( 10, 10, 20, 30 );
	widhtR := HWidth( LNewObj );
	heightR := HHeight( LNewObj );
	Message( widhtR, ',', heightR );
END;
Run( sample402 );
四角形を描いて幅と高さを求めてみましょう。 手続きRectを使って四角形を描きます。四角形の第1、第2引数に10,10とすることで、四角形の左下の座標が(10,10)となり、第3、第4引数に20,30とすることで、四角形の右上の座標が(20,30)の四角形が描かれます。
関数HHeightは図形の幅を返します。引数に関数LNewObjを与えることで、直前に生成した図形(四角形)のハンドルを引数として与えたことになり、widhtRに幅が返ります。
関数HWidthは図形の高さを返します。引数に関数LNewObjを与えることで、直前に生成した図形(四角形)のハンドルを引数として与えたことになり、heightRに高さが返ります。
最後に手続きMessageで幅と高さを表示します。

・図形名「床-01」の面積を求める。
PROCEDURE sample403;
VAR
	objH : Handle;
	theArea : REAL;
BEGIN
	objH := GetObject( '床-01' );
	IF objH <> NIL THEN
	BEGIN
		theArea := ObjAreaN( objH );
		Message( theArea );
	END
	ELSE
	BEGIN
		Message( '図形が見つかりません。' );
	END;
END;
RUN( sample403 );
関数GetObjectは引数に名前を与えることで、その図形のハンドルを返します。
IF文において、ハンドルがNILかどうかを判定します。その名前の付いた図形が無かった場合、NILが返ってくるからです。
判定の結果、TRUEならば、関数ObjAreaNを呼んで面積を求めます。そして表示します。
判定の結果、FALSEならば、「図形が見つかりません。」と表示します。

・円弧を描いて、色とクラスを設定する。
PROCEDURE sample404;
VAR
	objH : HANDLE;
BEGIN
	Arc( 10, 10, 20, 30, 45, 270 );
	objH := LNewObj;
	SetFillBack( objH, 65535, 0, 0 );
	SetClass( objH, '1階-床' );
END;
Run( sample404 );
まず、手続きArcで円弧を描きます。
関数LNewObjで直前に描いた図形(円弧)のハンドルを求めます。
手続きSetFillBackで、面に色を指定します。
手続きSetClassで、クラスを指定します。

・レイヤの名前と縮尺を求める。
PROCEDURE sample405;
VAR
	txStr : STRING;
	scaleR : REAL;
BEGIN
	txStr := GetLName( ActLayer );
	scaleR := GetLScale( ActLayer );
	Message( txStr, ',', scaleR );
END;
Run( sample405 );
レイヤの情報もハンドルを使うことで知ることができます。
関数GetLNameはレイヤの名前を返します。引数に関数ActLayerを与えることで、アクティブなレイヤのハンドルを引数として与えたことになり、txStrにレイヤ名が返ります。
関数GetLScaleはレイヤの縮尺を返します。引数に関数ActLayerを与えることで、アクティブなレイヤのハンドルを引数として与えたことになり、scaleRにレイヤの縮尺が返ります。
最後に手続きMessageでレイヤ名と縮尺を表示します。

・図形に名前を付けてみる。
PROCEDURE sample406;
VAR
	objH : Handle;
BEGIN
	Rect( 0, 0, 10, 10 );
	ArcByCenter( 10, 10, 5, 0, 360 );
	Poly( 10, 10, 20, 10, 10, 20, 10, 10 );

	objH := FSActLayer;
	SetName( objH, '四角形' );
	objH := NextSObj( objH );
	SetName( objH, '円' );
	objH := NextSObj( objH );
	SetName( objH, '多角形' );

	AlrtDialog( GetName( objH ) );
	objH := PrevSObj( objH );
	AlrtDialog( GetName( objH ) );
	objH := PrevSObj( objH );
	AlrtDialog( GetName( objH ) );
END;
Run( sample406 );
ハンドルを順に辿ることで図形情報を知ることもできます。
手続きRect、ArcByCenter、Polyを使って四角形、円、多角形を描きます。
そしてアクティブなレイア上で選択されているもっとも上位の図形のハンドルを取るために関数FSActLayerを使います。First(最初)、Select(選択)、Active(編集中)という意味だと思ってください。
手続きSetNameで「四角形」と名前を付けます。
そして次のハンドルを探すために関数NextSObjを使います。これは引数にハンドルを与えるとNext(次の)、Select(選択されている)、Object(図形)のハンドルを返します。
手続きSetNameで「円」と名前を付けます。
さらに次のハンドルを探し、「多角形」と名前を付けます。
つづけて、付けた順とは反対に図形のハンドルを辿り、図形名を表示してみます。
まずは付けたばかりのハンドルを使って、関数GetNameをすると「多角形」と戻ります。その戻り値を手続きAlrtDialogで表示させます。
つづいて、次の図形のハンドルではなく前のハンドルですので、関数PrevSObjを使います。これは引数にハンドルを与えるとPrev(前の)、Select(選択されている)、Object(図形)のハンドルを返します。
関数GetNameをすると「円」と戻ります。
さらに、前のハンドルを取って図形名を取ると、「四角形」と戻ります。

最初に図形を描かせていますが、このとき書類上で特徴的なことが起こります。
もし、手動で3つの図形を描くとどうなるでしょう。一番最後に描いた図形のみ選択状態になります。
スクリプトの場合、プログラム側で選択状態を解除しない限り全て選択状態になります。

・座標値をワークシートに入れてみる。
PROCEDURE sample407;
VAR
	objH, worksheetH : Handle;
	num, ii : INTEGER;
	pX, pY : REAL;
	aString : DYNARRAY[] OF CHAR;
BEGIN
	Poly( 10, 10, 30, 10, 30, 20, 20, 20, 20, 30, 10, 30 );
	objH := LNewObj;

	num := GetVertNum( objH );
	worksheetH := CreateWS( '座標値', num, 2 );

	FOR ii := 1 TO num DO
	BEGIN
		GetPolyPt( objH, ii, pX, pY );
		aString := Num2Str( 3, pX );
		SetWSCellFormulaN( worksheetH, ii, 1, ii, 1, aString );
		aString := Num2Str( 3, pY );
		SetWSCellFormulaN( worksheetH, ii, 2, ii, 2, aString );
	END;

	worksheetH := CreateWSImage( worksheetH, 0, 0 );
	ReDrawAll;
END;
Run( sample407 );
ワークシートもハンドルを操る事で作成できます。
手続きPolyを使って多角形を描きます。
関数LNewObjを使って直前に描いた図形(多角形)のハンドルを取得します。
関数GetVertNumを使って多角形の頂点数を取得します。
関数CreateWSを使ってワークシートを作成します。ワークシートの名前は「座標値」、大きさは頂点数とx,y座標(2次元)を入れる大きさで作ります。戻り値はワークシートのハンドルになります。

ここからワークシートへデータを入れます。繰り返しになりますのでFOR文を使います。
手続きGetPolyPtを使って多角形の頂点座標を取得します。頂点番号は1からです。
x座標を関数Num2Strを使って文字列に変換します。
手続きSetWSCellFormulaNを使ってワークシートのセルに文字列を入れます。x座標は1列目にいれます。
y座標を関数Num2Strを使って文字列に変換します。
手続きSetWSCellFormulaNを使ってワークシートのセルに文字列を入れます。y座標は2列目にいれます。
ここまでを頂点数分(num回)繰り返す事で、num行分の節点座標がワークシートに入ります。

仕上げに関数CreateWSImageを使って今作ったワークシートを図形化します。
手続きReDrawAllで画面が再描画され、ワークシート図形が画面上に現れます


といったように図形のハンドルを得ることでその図形のほとんどの情報を知ることができます。