押し出し方向と高度を使った図形配置
【押し出し方向】と「高度」を使った図形配置は、ライトウェイトポリラインや 2D ポリラインといった、三次元空間内の任意の平面上であるが、一つの平面上に載った図形で使われます。具体的には DXF グループコード 30 または 38 等や VLA オブジェクトのプロパティ Elevation をもつものです。
図面データベース内で、ライトウェイトポリラインは DXF グループコードと VLA オブジェクトのプロパティでは次のように表されます。
DXF グループコード | プロパティ | 意味 |
---|---|---|
90 | 頂点の数 | |
10(複数個) | Cordinates | 頂点の座標 (OCS) |
38 | Elevation | 高度 |
210 | Normal | 【押し出し方向】ベクトル |

WCS 上で (0.0 0.0) と (100.0 50.0) を対角頂点とする長方形のライトウェイトポリラインを、Z 軸方向に 25.0 移動し、Y 軸を中心に45度回転させた図形を作成してみます。この課題を言い換えますと Z 軸方向に 25.0 移動し、Y 軸を中心に 45 度回転させたある任意の座標系を基準に(0.0 0.0) と (100.0 50.0) を対角頂点とする長方形を描くことになります。同じ計算であっても、視点の取り方で思考の表現が変わることを認識してください。
この時、軸の回転から【押し出し方向】ベクトルは頭でイメージすると分かるとおり (1.0 0.0 1.0) となります。しかし話は難しくなります。次のようにすると期待したものと異なったものとなるでしょう。そして仮に X 軸を中心に 45 度回転させたものとして【押し出し方向】ベクトルが (0.0 -1.0 1.0) とした場合は期待したような図形になります。理解していないと、うまくいったり、いかなかったり、どこが悪いのかわからなくて頭を抱えることになります。
(100 . "AcDbEntity")
(100 . "AcDbPolyline")
(90 . 4) ; 頂点数
(10 0.0 0.0)
(10 100.0 0.0)
(10 100.0 50.0)
(10 0.0 50.0)
(70 . 1) ; 閉じている
(38 . 25.0)
(210 1.0 0.0 1.0)
)
)
これは、【任意の軸のアルゴリズム】によって決まる OCS の X 軸 Y 軸の向きが、【押し出し方向】によってダイナミックに変化してしまうことに起因します。そのため OCS で指定する頂点の座標は【押し出し方向】によって変化させなければなりません。
いくつか方法があるかと思いますが、イメージしやすい方法として、頂点の座標を自前で WCS 内で目的の位置へ座標変換します。それを【押し出し方向】ベクトルによって決まる OCS 上の座標に変換して図面データベースに書き込みます。
Z 軸方向に 25.0 移動し、Y 軸を中心に45度回転させる変換マトリックスは次のとおりです。
(setq amatrix (matrix:Product (rotate-matrix:Y-axis (/ PI 4)) (translation-Matrix '(0.0 0.0 25.0)) ) )
この変換マトリックスで表される Z 軸の向きが【押し出し方向】ベクトルになります。表示させてみると単位ベクトルに丸められていますが、イメージしているものと同じ方向を向いています。
_$ (transformation-matrix:element amatrix 'Z) ⏎
(0.707107 0.0 0.707107)
この【押し出し方向】ベクトルを使って WCS 上の座標を OCS 上の座標に変換します。
ここまでの一連の計算まとめると次のように書けます。
(setq amatrix (matrix:Product (rotate-matrix:Y-axis (/ PI 4)) (translation-Matrix '(0.0 0.0 25.0)) ) normal (transformation-matrix:element amatrix 'Z) plist (mapcar (function (lambda (point) (trans (transform amatrix point) acWorld normal) ) ) '((0.0 0.0 0.0) (100.0 0.0 0.0) (100.0 50.0 0.0) (0.0 50.0 0.0)) ) )
最後の plist に図形にセットすべき OCS の座標が代入されます。表示させると以下のようなものです。このように OCS が介入すると図面データベースに設定する値は予測しにくいものになります。
_$ plist⏎
((0.0 0.0 25.0) (0.0 -100.0 25.0) (50.0 -100.0 25.0) (50.0 0.0 25.0))
上の Z 座標の値 25.0 は「高度」に設定しますので、XY 座標だけの値にして頂点の座標として図形を作成します。まとめますと、今回のライトウェイトポリラインの作成は DXF グループコードと entmake 関数を使う場合は次のように書けます。
(setq amatrix (matrix:Product (rotate-matrix:Y-axis (/ PI 4)) (translation-Matrix '(0.0 0.0 25.0)) ) normal (transformation-matrix:element amatrix 'Z) plist (mapcar (function (lambda (point) (trans (transform amatrix point nil) acWorld normal) ) ) '((0.0 0.0 0.0) (100.0 0.0 0.0) (100.0 50.0 0.0) (0.0 50.0 0.0)) ) elevation (3DVector:ref (car plist) 'Z) ) (entmake (append '((0 . "LWPOLYLINE") (100 . "AcDbEntity") (100 . "AcDbPolyline") (90 . 4) ; 頂点数 ) (mapcar (function (lambda (point) (cons 10 (3DVector:~ref point 'Z)))) plist ) (list '(70 . 1) ; 閉じている (cons 38 elevation) ; 高度 (cons 210 normal) ; 押し出し方向 ) ) )
ActiveX 対応関数を使った場合も座標についての考えは同じです。
(setq amatrix (matrix:Product (rotate-matrix:Y-axis (/ PI 4)) (translation-Matrix '(0.0 0.0 25.0)) ) normal (transformation-matrix:element amatrix 'Z) plist (mapcar (function (lambda (point) (trans (transform amatrix point nil) acWorld normal) ) ) '((0.0 0.0 0.0) (100.0 0.0 0.0) (100.0 50.0 0.0) (0.0 50.0 0.0)) ) elevation (3DVector:ref (car plist) 'Z) ) (setq lwpline-obj (vla-AddLightWeightPolyline *ModelSpace* (pointList->xyPointArray plist) ) ) (vla-put-Normal lwpline-obj (vlax-3D-point normal)) (vla-put-Elevation lwpline-obj elevation) (vla-put-Closed lwpline-obj :vlax-true)
上の中で pointList->xyPointArray 関数は三次元の頂点のリストを XY の二次元に変換した後、浮動小数点のセーフ配列のバリアント型に変換する関数です。詳しくは、別稿の「AutoLISP の ActiveX」を参照してください。