【実務・中級編】【実務中級】AcadDocument.Utility.GetSubEntityによる「ブロック内図形」の直接取得とプロパティ解析 – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBAを極める:ブロックを「分解」せずに内部を制する技術

AutoCAD開発の現場で、初心者がまずぶつかる壁が「ブロック参照(`AcadBlockReference`)」だ。
「ブロックの中にある線分の座標が欲しい」と考えたとき、多くのエンジニアは安易に`Explode`メソッドを叩く。断言しよう。それは最悪の設計だ。

ブロックを分解するということは、図面の整合性を破壊し、Undoスタックを汚染し、再描画のオーバーヘッドを増大させる行為に他ならない。真のプロフェッショナルは、ブロックを分解することなく、`GetSubEntity`を用いてその深淵へとアクセスする。

今回は、AutoCADのオブジェクトモデルを掌握するための「ブロック内図形抽出」の極意を伝授する。

なぜ GetSubEntity なのか?

`GetEntity`はトップレベルの図形しか取得できない。しかし、`GetSubEntity`はユーザーのポインティングデバイスと交差する「ネストされたオブジェクト」を直接拾い上げることができる。

このメソッドが返すのは、単なる図形オブジェクトではない。`ObjectPath`という、ブロック参照から目的の図形まで辿り着くための「航海図」だ。これを利用すれば、複雑なネスト構造を持つブロックであっても、その内部のジオメトリを正確に抽出できる。

【実践コード】ブロック内図形を安全に射抜く

このコードは、単に情報を取得するだけでなく、選択されたオブジェクトが本当にブロック内にあるのかを検証し、堅牢に処理を行うためのプロダクションレベルの実装だ。

Public Sub GetNestedEntityInfo()
Dim entObj As AcadEntity
Dim pickPt As Variant
Dim transMat As Variant
Dim contextEnts As Variant

‘ ユーザーにブロック内の要素を選択させる
On Error Resume Next
ThisDrawing.Utility.GetSubEntity entObj, pickPt, transMat, contextEnts, “ブロック内の要素を選択してください:”

If Err.Number <> 0 Then
MsgBox “選択がキャンセルされたか、無効な図形です。”
Exit Sub
End If
On Error GoTo 0

‘ 取得したオブジェクトの型を確認し、必要に応じた解析を行う
Debug.Print “選択された図形タイプ: ” & entObj.ObjectName

‘ 重要: contextEntsには、トップレベルのブロック参照が含まれる
‘ これにより、ブロックの属性や名前を取得可能
If IsArray(contextEnts) Then
Dim i As Integer
For i = LBound(contextEnts) To UBound(contextEnts)
Dim parentRef As AcadBlockReference
Set parentRef = contextEnts(i)
Debug.Print “親ブロック名: ” & parentRef.Name
Next i
End If

‘ ここでエンティティのプロパティ(色、画層、座標等)を抽出する
‘ GetSubEntityで取得したオブジェクトは直接変更も可能だが、
‘ データベースへの影響を考慮し、まずは読み取りから始めるのが定石。
Call AnalyzeGeometry(entObj)
End Sub

Private Sub AnalyzeGeometry(ent As AcadEntity)
‘ 型ごとの詳細解析ロジック
Select Case ent.ObjectName
Case “AcDbLine”
Dim line As AcadLine
Set line = ent
Debug.Print “始点: ” & line.StartPoint(0) & “, ” & line.StartPoint(1)
Case “AcDbCircle”
‘ 円の半径や中心を取得するロジック
End Select
End Sub

実務で「死なない」ためのアーキテクチャ設計

1. 変換行列(Transformation Matrix)の呪縛

`GetSubEntity`が返す`transMat`は、ブロックの挿入点や尺度、回転を反映した変換行列だ。もしあなたが取得した座標をそのまま外部CSVやデータベースに書き出すなら、この行列を適用して「グローバル座標」に変換しなければならない。
この計算を怠ると、図面上の見た目とデータ上の座標が食い違う「エンジニアとして恥ずべきバグ」が生まれる。

2. ファイル・DB連携時の注意

抽出したデータを外部ファイルやデータベースに保存する場合、「ブロックのネスト」を考慮せよ。ブロックの中にブロックが入っている場合、`contextEnts`の配列を再帰的に辿る必要がある。これを怠ると、親ブロックの座標系のみに依存した脆弱なツールになる。

3. パフォーマンスへの配慮

AutoCADのCOMインターフェースは、大量の図形をループで回すと極端に遅くなる。`GetSubEntity`で取得したオブジェクトをループ処理する際は、必ず`Set`キーワードを適切に使い、メモリリークを避けること。また、`On Error`のハンドリングを甘く見ないこと。ユーザーは必ず「想定外の場所」をクリックする。

結論:ツールは「破壊」ではなく「洞察」のためにある

AutoCAD VBAは、単なるマクロの寄せ集めではない。AutoCADという巨大なデータベースに対する「クエリ言語」であると認識せよ。

ブロックを分解して力技で解決するツールは、誰にでも書ける。しかし、ブロックの構造を維持したまま、静かに、確実に必要な情報だけを抽出するツールこそが、現場を救うプロの仕事だ。

さあ、このコードをベースに、君の現場の「非効率」を根絶やしにしてくれ。技術的な深淵に挑む者だけが、CAD自動化の本当の果実を得ることができる。

タイトルとURLをコピーしました