>どこかのサイトにサンプルなどご存知ないでしょうか。
trans 関数は、尺度、回転、平行移動の計算を内部的に処理してくれます。
(trans point from_coord_sys to_coord_sys [displacement_vector])
point: 変換したい点のリスト
from_coord_sys: 変換元の座標系。ブロック内のエンティティの場合、ブロックのローカル座標系を表すエンティティ名 (block_ename) を指定します。
to_coord_sys: 変換先の座標系。モデル空間のワールド座標系を表す場合は 1 を指定します。
displacement_vector: (オプション) 変位ベクトル。ブロック参照の場合、挿入点、尺度、回転角度が暗黙的に適用されるため、通常は指定しません。
具体的なAutoLISPコードは次の様になります。
(defun C:GetBlockLineCoordsNoExplode (/ ss i ent block_data block_name insertion_point block_def_ename
block_def_ent block_def_ent_data
line_start_mcs line_end_mcs
line_start_wcs line_end_wcs)
(vl-load-com) ; 必要に応じてロード
(princ "\n線分の座標を取得したいブロック参照を選択してください: ")
(setq ss (ssget '((0 . "INSERT")))) ; ブロック参照のみを選択
(if ss
(progn
(setq i 0)
(repeat (sslength ss)
(setq ent (ssname ss i)) ; 選択セットからブロック参照のエンティティ名を取得
(setq block_data (entget ent))
(setq block_name (cdr (assoc 2 block_data))) ; ブロック名を取得
(setq insertion_point (cdr (assoc 10 block_data))) ; 挿入点 (WCS)
(princ (strcat "\n--- ブロック名: " block_name " (ハンドル: " (cdr (assoc 5 block_data)) ") ---"))
; ブロック名からブロック定義のエンティティ名を取得
; (tblobjname "BLOCK" block_name) はブロック定義のエンティティ名を返します
(setq block_def_ename (tblobjname "BLOCK" block_name))
(if block_def_ename
(progn
; ブロック定義内のエンティティを走査
; (entnext block_def_ename) で最初のエンティティを取得
; その後 (entnext current_ent_in_block_def) で次のエンティティを取得
(setq block_def_ent (entnext block_def_ename))
(while (and block_def_ent (not (eq (cdr (assoc 0 (setq block_def_ent_data (entget block_def_ent)))) "ENDBLK")))
; 現在のエンティティが線分かどうかをチェック
(if (eq (cdr (assoc 0 block_def_ent_data)) "LINE")
(progn
; 線分の始点と終点の座標をブロックのローカル座標系で取得
(setq line_start_mcs (cdr (assoc 10 block_def_ent_data))
line_end_mcs (cdr (assoc 11 block_def_ent_data))
)
; trans関数を使ってモデル空間座標に変換
; 変換元の座標系としてブロック参照のエンティティ名 'ent' を指定
; これにより、挿入点、尺度、回転角度が自動的に適用される
(setq line_start_wcs (trans line_start_mcs ent 1))
(setq line_end_wcs (trans line_end_mcs ent 1))
(princ (strcat "\n 線分始点 (WCS): " (vl-princ-to-string line_start_wcs)))
(princ (strcat "\n 線分終点 (WCS): " (vl-princ-to-string line_end_wcs)))
)
)
; 次のエンティティへ
(setq block_def_ent (entnext block_def_ent))
)
)
(princ (strcat "\n ブロック定義 '" block_name "' が見つかりません。"))
)
(setq i (1+ i))
)
)
(princ "\nブロックが選択されませんでした。")
)
(princ)
)
このコードは、選択されたブロック参照(親ブロック)の直下の線分には対応できますが、
ネストされたブロック(ブロックの中にさらにブロックが含まれている場合) の中の線分には直接対応していません。
ネストされたブロック内の線分も取得したい場合は、親ブロック内のエンティティを走査中に、
別のブロック参照 (INSERT エンティティ) を見つけたら、そのネストされたブロック参照の情報を(挿入点、尺度、回転角度など)取得します。
そのネストされたブロックの定義を再帰的に走査します。
最下層の線分のローカル座標に、親ブロック、その中のネストされたブロック…というように、
全ての階層の変換行列(挿入点、尺度、回転)を累積的に適用していく 必要があります。
- Hamu
- 2025/06/05 (Thu) 09:28:23