【実務・中級編】【フィレット・面取り】Body2.GetFacesとEdge.GetCurveを用いた、特定の曲率を持つエッジのみを抽出して一括フィレットをかける応用マクロ – SolidWorks VBA解析バイブル

スポンサーリンク

SolidWorks VBAを掌握する極限の知見:特定の曲率を持つエッジのみを自動抽出して一括フィレットをかける高度なオブジェクト走査術

開発現場において、図面指示に基づくフィレットや面取りの自動化は、工数削減のキラーコンテンツである。しかし、多くのプログラマが「すべてのエッジを一括選択してバグる」「モデル変更でマクロが破綻する」という壁にぶ当たる。

特に、`FeatureManager::InsertFillet` あたりのAPIを安易に叩き、モデルのトポロジー変更(面やエッジの増減)に耐えられない脆弱なコードを量産してしまうケースが後を絶たない。

今回は、SolidWorks APIの深層である `Body2` オブジェクトの走査`Edge` の幾何情報(数学的定義)の評価 を組み合わせ、「特定の曲率を持つエッジだけをプログラムで動的にフィルタリングし、一括でフィレットを適用する」 堅牢なプロダクションコードを解説する。

1. なぜ「全選択」や「名前指定」のフィレットは実務で破綻するのか?

実務の現場で最もやってはいけないアンチパターンが、固定的なエッジ名(例: `Edge<1>`)のハードコーディングや、モデル内の全エッジを無差別に取得してフィレットをかけるアプローチだ。

  • トポロジーの変動: 設計変更によってフィーチャのツリー構造が変わると、内部ID(Persistent ID)やエッジのインデックスは容易に変わる。
  • APIの重み: ジオメトリを不必要に再評価させると、複雑なモデルではSolidWorksがフリーズするか、巨大なメモリリークを引き起こす。

チーフアーキテクトからの提言

「モデルの見た目」に頼るな。「数学的定義(Curve)」でエッジを捉えろ。
エッジが持つ円弧の半径(曲率)をAPI経由で直接算出し、条件に合致するエンティティだけを動的に配列(またはコレクション)として収集する。このアプローチこそが、幾何公差やモデル改版にビクともしない「真に保守性の高い自動化」への唯一の道である。

2. 幾何情報(Curve)評価のメカニズム

SolidWorks VBAにおいて、エッジから曲率を抽出するルートは以下の通りである。

1. `PartDoc` からアクティブな `Body2` を取得する。
2. `Body2::GetEdges` で、そのボディを構成するすべての `Edge` オブジェクトの配列を取得する。
3. 各 `Edge` に対して `Edge::GetCurve` を実行し、そのエッジが持つ数学的曲線(`Curve` オブジェクト)を取得する。
4. `Curve::IsCircle` や `Curve::GetCircleParams` を用い、それが円弧であるか、かつ指定した半径と一致するかを判定する。

この一連のプロセスにより、UI上でユーザーがポチポチと手動選択していた手間を、一瞬で、かつロジカルに代替できる。

3. 【プロダクションコード】特定曲率エッジ抽出・一括フィレットマクロ

以下のコードは、エラーハンドリング、オブジェクトの適切な解放(VBAにおけるCOMオブジェクトのメモリ管理)、そして条件判定を網羅した実戦投入可能なモジュールである。

Option Explicit

‘ ==============================================================================
‘ 領域: SolidWorks VBA / パーツジオメトリ自動化
‘ テーマ: 特定の曲率(半径)を持つエッジのみを動的に抽出し、一括フィレットを適用する
‘ ==============================================================================
Sub ApplyTargetCurvatureFillet()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swPart As SldWorks.PartDoc
Dim swBodyArr As Variant
Dim swBody As SldWorks.Body2
Dim swEdgeArr As Variant
Dim swEdge As SldWorks.Edge
Dim swCurve As SldWorks.Curve

‘ アプリケーションの取得
Set swApp = Application.SldWorks
If swApp Is Nothing Then Exit Sub

Set swModel = swApp.ActiveDoc
If swModel Is Nothing Then
MsgBox “アクティブなドキュメントが存在しません。”, vbCritical, “エラー”
Exit Sub
End If

‘ パーツドキュメントかどうかの型チェック
If swModel.GetType <> swDocPART Then
MsgBox “このマクロはパーツドキュメントでのみ実行可能です。”, vbCritical, “エラー”
Exit Sub
End If

Set swPart = swModel

‘ ターゲットとするフィレット半径(単位:メートル法前提の場合はメートル指定 / ここでは例として 5mm = 0.005m)
‘ ※SolidWorks APIの内部単位は常に「メートル(MKS)」であることに注意せよ。
Const TARGET_RADIUS As Double = 0.005
Const FILLET_RADIUS As Double = 0.002 ‘ 適用するフィレット半径

‘ 選択バッファをクリア
swModel.ClearSelection2 True

Dim selectedEdgeCount As Long
selectedEdgeCount = 0

‘ ソリッドボディの取得 (B-Rep構造の根幹)
swBodyArr = swPart.GetBodies2(swSolidBody, True)
If IsEmpty(swBodyArr) Then
MsgBox “処理対象となるソリッドボディが存在しません。”, vbExclamation, “警告”
Exit Sub
End If

‘ パフォーマンス向上のため画面更新を停止
swModel.Extension.EnableGraphicsUpdate = False

Dim i As Long, j As Long
Dim status As Boolean

‘ ボディを走査
For i = LBound(swBodyArr) To UBound(swBodyArr)
Set swBody = swBodyArr(i)
swEdgeArr = swBody.GetEdges

If Not IsEmpty(swEdgeArr) Then
‘ エッジを走査
For j = LBound(swEdgeArr) To UBound(swEdgeArr)
Set swEdge = swEdgeArr(j)
Set swCurve = swEdge.GetCurve

If Not swCurve Is Nothing Then
‘ 曲線が円弧(Circle / Arc)であるか判定
If swCurve.IsCircle Then
Dim vParam As Variant
vParam = swCurve.GetCircleParams()

‘ vParamの構造:
‘ (0)-(2) 中心座標 (X, Y, Z)
‘ (3)-(5) 軸ベクトル (X, Y, Z)
‘ (6) 半径 (Radius)

If Not IsEmpty(vParam) Then
Dim currentRadius As Double
currentRadius = vParam(6)

‘ 許容誤差(Floatの比較における丸め誤差を考慮)を設けて半径を比較
If Abs(currentRadius – TARGET_RADIUS) < 0.00001 Then ' 条件に合致するエッジを「マーク」として選択状態に追加 (Append = True) status = swEdge.Select4(True, Nothing) If status Then selectedEdgeCount = selectedEdgeCount + 1 End If End If End If End If Next j End If Next i ' 画面更新を再開 swModel.Extension.EnableGraphicsUpdate = True ' 該当エッジが存在する場合のみフィレットフィーチャを生成 If selectedEdgeCount > 0 Then
Dim swFeat As SldWorks.Feature
‘ 冗長なエラーを防ぐため、FeatureManagerのフィレットAPIを叩く
‘ 引数:
‘ Radius1, Propagate, FilletType, OverflowType, ConicType
Set swFeat = swModel.FeatureManager.InsertFillet( _
FILLET_RADIUS, _
1, _ ‘ swFilletPropagate_None / 1: 伝播する
0, _ ‘ swFilletType_Standard
0, _ ‘ swFilletOverflow_Default
0, _ ‘ swConicType_Standard
0, 0)

If Not swFeat Is Nothing Then
MsgBox selectedEdgeCount & “個のエッジに対して正常にフィレットを適用しました。”, vbInformation, “完了”
Else
MsgBox “エッジの選択には成功しましたが、フィレットの生成に失敗しました。(ジオメトリ干渉の可能性)”, vbCritical, “エラー”
End If
Else
MsgBox “指定された曲率を持つエッジが見つかりませんでした。”, vbInformation, “情報”
End If

‘ オブジェクトの解放(VBAにおけるメモリリーク・COM参照残り防止の鉄則)
Set swCurve = Nothing
Set swEdge = Nothing
Set swBody = Nothing
Set swModel = Nothing
Set swApp = Nothing
End Sub

4. チーフアーキテクトが教える実装上の極意と注意点

上記のコードを実務の生産ラインに組み込むにあたり、以下の「プロの視点」を必ず心に留めておいてほしい。

① SolidWorks APIの単位系(MKS)の罠

APIがやり取りする数値は、ドキュメントの表示単位(ミリメートルやインチ)に関わらず、常に「メートル (Meter)」である。
コード内で `TARGET_RADIUS = 0.005` と記述しているのは、5.0mm を意味する。ここを誤ると、永遠にエッジがヒットせずデバッグの沼にハマることになる。

② 画面描画の停止 (`EnableGraphicsUpdate = False`) による爆速化

何百、何千というエッジを `swEdge.Select4` でプログラムから選択状態にするとき、SolidWorksが都度画面を描画していると、処理が極端に遅くなる(いわゆる「画面がチラついて固まる現象」)。
処理の直前で描画を切り、処理後に戻すワンクッションを入れるだけで、実行速度は体感で数倍〜十数倍に跳ね上がる。プログラマとしての作法の良し悪しがこういう細部に出る。

③ COMオブジェクトの参照解放

VBAはガベージコレクションが強力ではない。特にSolidWorksのようなCOMラッパーを大量に扱う場合、ループ内でオブジェクト変数を使い回す際やプロシージャの抜け際において、明示的に `Set xxx = Nothing` を行わないと、SolidWorksプロセスがバックグラウンドに残留し、メモリリークやファイルロックの原因となる。

総括

今回紹介した「モデルの幾何情報を数理的に評価してフィルタリングする技術」は、フィレットだけに留まらない。
穴 (Hole) の自動面取り、特定の角度を持つ面の抽出、干渉チェックの前処理など、あらゆる高度な自動化のベースとなる 「SolidWorks APIを使いこなすためのコアキテクチャ」 である。

既製品のツールや単純なマクロ記録の延長に限界を感じたなら、今すぐこのオブジェクト走査術をあなたの武器庫に加えなさい。現場の景色が変わるはずだ。

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