【テクニカル・上級編】【マルチボディ対応】Body2.GetBodyTypeとBody2.DeleteBodyを用いた、不要な接触ボディの自動判別とクリーンアップ処理 – SolidWorks VBA解析バイブル

スポンサーリンク

【SolidWorks VBA極限の知見】第42回:マルチボディの呪縛を断つ。Body2.GetBodyTypeとDeleteBodyによる「デッドボディ」自動クリーンアップの極意

SolidWorks APIを用いた自動化設計の現場において、最も見落とされがちであり、かつシステムの健常性を最も蝕む癌(がん)――それが、ブーリアン演算の過程で意図せず生成される「ゼロ体積ソリッド」や「微小デッドボディ(ゴミ形状)」である。

コンテキストフィーチャやアセンブリからのボディ結合(Combine)、あるいは複雑なサーフェス縫い合わせ(KnitSurface)の果てに、パーツファイル内には人間が視認できないレベルの微小なマルチボディが残存することがある。これらはファイルサイズを肥大化させるだけでなく、後続の図面化処理、MassProperties(質量特性)の計算エラー、さらには下流のCAM・CAFE工程における致命的なデータ破損を引き起こす。

今回は、シニアエンジニアおよび社内システム管理者が避けて通れない、`Body2.GetBodyType` と `Body2.DeleteBody` を駆使したマルチボディのクリーンアップ処理の極限を解説する。

1. 根底にあるAPIの挙動:なぜデッドボディは生まれるのか?

SolidWorksのモデラー(Parasolid)は非常に高精度だが、許容差(Tolerance)の境界線上で行われる幾何学演算では、しばしば「掠(かす)っただけの微小な孤立ソリッド」や「体積が完全にゼロのトポロジー」が生成される。

VBAからこれらを制御する際、以下のAPI階層の厳密な理解が不可欠となる。

  • `PartDoc.GetBodies2`: パーツ内のすべてのボディ(ソリッド、サーフェス、シート)を配列として取得する。
  • `Body2.GetBodyType`: 取得したボディの種別(Solid, Sheet, Gizmoなど)を判定する。
  • `Body2.IsSolid`: 純粋なソリッドボディであるかを高速に判定する。
  • `Body2.GetMassProperties`: 密度の影響を排し、真の体積(Volume)や表面積を取得する。

これらを組み合わせ、「ソリッドであるが、実質的に体積を持たない、あるいは設計意図から外れた微小なしきみ値以下のボディ」をプログラムによって動的に炙り出し、削除(DeleteBody)するのが本アーキテクチャの核心である。

2. メモリ最適化とCOMオブジェクトのライフサイクル管理

VBAにおけるSolidWorks API開発で最も多いバグは、COMオブジェクトの解放漏れによるメモリリーク、そしてそれ起因する「ハンドル枯渇エラー」である。

`GetBodies2` のような配列を返すメソッドを叩くとき、返されたオブジェクト群(`Body2`)は確実にローカル変数へ格納され、ループ終了時、あるいは処理の節目で明示的に `Set xxx = Nothing` を行わなければならない。特にマルチボディを数千回走査するような大規模アセンブリやパーツ群のバッチ処理では、この規律がシステムの生死を分ける。

3. 実装コード:デッドボディ自動クリーンアップ・エンジン

以下のコードは、アクティブなパーツドキュメントを走査し、ゼロ体積、あるいは指定した微小しきみ値(例: 0.001 mm³未満)を下回る不要なソリッドボディを自動判別して完全消去する、実戦投入仕様のVBAプロシージャである。

Option Explicit

‘ =================================================================================
‘ 処理名: ゼロ体積・微小デッドボディ自動クリーンアップ処理
‘ 概要: アクティブパーツ内の全マルチボディを走査し、指定しきみ値以下の
‘ 不要なソリッドボディを安全に削除する。
‘ 依存関係: SldWorks, MathUtility
‘ =================================================================================
Sub CleanUpDeadBodies()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swPart As SldWorks.PartDoc

Set swApp = Application.SldWorks
If swApp Is Nothing Then Exit Sub

Set swModel = swApp.ActiveDoc
If swModel Is Nothing Then
MsgBox “ドキュメントが開かれていません。”, vbCritical, “API Error”
Exit Sub
End If

‘ パーツドキュメント以外は弾く
If swModel.GetType <> swDocPART Then
MsgBox “このマクロはパーツドキュメントでのみ実行可能です。”, vbExclamation, “型不一致”
Exit Sub
End If

Set swPart = swModel

‘ 編集セッションの開始(パフォーマンス向上とUndoのまとめ)
swModel.Extension.EnableCommandState = False

Dim vBodies As Variant
‘ swAllBodies (0) を指定してすべてのボディを取得
vBodies = swPart.GetBodies2(swAllBodies, False)

If IsEmpty(vBodies) Then
MsgBox “処理対象のボディが存在しません。”, vbInformation, “情報”
GoTo CleanUp
End If

Dim i As Long
Dim swBody As SldWorks.Body2
Dim bodyType As Long
Dim isSolid As Boolean
Dim vMassProp As Variant
Dim bodyVolume As Double

‘ 削除対象ボディを格納する動的配列
Dim deleteBodies() As Object
Dim deleteCount As Long
deleteCount = 0

‘ 許容する最小体積しきみ値 (単位: m^3 -> 0.001 mm^3 = 1.0E-12 m^3)
‘ ※環境のドキュメント単位系に合わせて調整すること
Const VOLUME_THRESHOLD As Double = 0.000000000001 ‘ 1e-12 m^3

Dim progressCounter As Long
progressCounter = 0

‘ — 第1パス:条件判定と削除対象の抽出 —
For i = LBound(vBodies) To UBound(vBodies)
Set swBody = vBodies(i)

If Not swBody Is Nothing Then
‘ テンポラリーボディや非表示・モデリングエラー状態のものを除外
If swBody.IsVisible Then
isSolid = swBody.IsSolid

If isSolid Then
‘ 質量特性(体積)の取得
‘ GetMassProperties2(Parameters) -> 0: Volume, 1: Area, etc.
vMassProp = swBody.GetMassProperties(0)

If Not IsEmpty(vMassProp) Then
‘ vMassProp(5) が体積 (Volume)
bodyVolume = vMassProp(5)

‘ 体積がしきみ値未満、あるいは完全に0の場合をデッドボディと判定
If bodyVolume < VOLUME_THRESHOLD Then ReDim Preserve deleteBodies(deleteCount) Set deleteBodies(deleteCount) = swBody deleteCount = deleteCount + 1 End If End If End If End If ' 個別ボディオブジェクトの解放 Set swBody = Nothing End If Next i ' --- 第2パス:デッドボディの実行削除 --- If deleteCount > 0 Then
Dim swFeatMgr As SldWorks.FeatureManager
Set swFeatMgr = swModel.FeatureManager

‘ DeleteBody2 フィーチャ作成による削除
‘ 引数: (ObjectArray, KeepSurface)
Dim bRet As Boolean
bRet = swPart.DeleteBody2(deleteBodies)

If bRet Then
swModel.EditRebuild3
MsgBox deleteCount & ” 個のデッドボディ(ゼロ/微小体積ソリッド)を正常にクリーンアップしました。”, vbInformation, “完了”
Else
MsgBox “デッドボディの削除処理に失敗しました。フィーチャの依存関係を確認してください。”, vbCritical, “エラー”
End If

Set swFeatMgr = Nothing
Else
MsgBox “削除対象となるデッドボディは検出されませんでした。”, vbInformation, “正常終了”
End If

CleanUp:
‘ 状態の復元とメモリ解放
If Not swModel Is Nothing Then
swModel.Extension.EnableCommandState = True
swModel.GraphicsRedraw2
End If

Set swPart = Nothing
Set swModel = Nothing
Set swApp = Nothing

End Sub

4. シニアエンジニアが押さえるべき実装の急所

上記のコードを実務環境に導入する際、以下のインフラ的・幾何学的な「罠」に注意されたし。

1. 単位系のトラップ
SolidWorks APIが内部で扱う数値は、すべてSI単位系(メートル、キログラム、ラジアン等)を基準としている。モデルの表示単位が「ミリメートル (mm)」であっても、APIから返る体積(`vMassProp(5)`)の単位は $\text{m}^3$ である。そのため、しきみ値(`VOLUME_THRESHOLD`)のオーダー計算を誤ると、意図した形状まで根こそぎ消去される大惨事を招く。事前のテスト環境での検証は絶対に怠ってはならない。
2. フィーチャーツリーの整合性
`DeleteBody2` メソッドは、フィーチャーツリーに「削除(DeleteBody)」フィーチャを明示的に追加する。これにより、タイムスタンプ順序における後続フィーチャへの影響(参照切れ)が発生するリスクがある。純粋な一時的ブーリアン演算の直後であれば安全だが、アセンブリ文脈や外部参照を持つパーツでの無差別な実行は避け、バッチ処理パイプラインの一環として適用範囲を制限すべきである。
3. コマンドの有効化制御(`EnableCommandState`)
大規模なマルチボディの走査・削除中、SolidWorksのUIはイベントのたびに画面再描画やコマンドの有効/無効判定を行おうとする。これを `swModel.Extension.EnableCommandState = False` によって一時的に遮断することで、処理速度を劇的に(時によっては数倍〜数十倍)向上させることが可能だ。プロシージャの最後での `True` への復帰とエラーハンドリング時の担保は、チーフアーキテクトとしての最低限の責務である。

総括

「動けばいい」という次元のコードは、現場のエンジニアリングを疲弊させる。
無駄なデッドボディを内包したパーツファイルは、将来的なシステム拡張や他システム(PLM/ERP)連携の大きな足かせとなる。

`Body2.GetBodyType` と適切な幾何学検証を組み合わせた自動クリーンアップ・ルーチンを社内標準ライブラリとして組み込むこと。それこそが、持続可能でロバストなCAD自動化エコシステムを構築するための唯一にして最大の近道である。

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