【実務・中級編】【フィレット・面取り】Body2.GetFacesで取得した特定平面と交差するエッジ群の自動フィルタリングと角丸め処理 – SolidWorks VBA解析バイブル

スポンサーリンク

【SolidWorks VBA極限活用】特定平面と交差するエッジの自動フィルタリングと堅牢なフィレット生成術

開発現場のエンジニア諸君。日々の設計自動化において、最もフラストレーションが溜まる瞬間はどこか?
それは、「全エッジを取得してフィレットをかけようとしたら、意図しない面や交差部にまで処理が走り、ジオメトリエラー(崩壊)を引き起こす」というトラブルではないか。

特に、`Body2.GetEdges` で取得できるエッジ群は、モデル全体のトポロジー構造が入り交じるカオスそのものだ。ここから人間が目視で行うような「特定の平面に隣接し、かつその平面と交差するエッジだけを抜き出す」というフィルタリングを、VBAでいかにノーエラーで実現するか。

今回は、SolidWorks APIのトポロジー構造の深淵を覗き、実務の現場で絶対に破綻しない「スマートエッジ・フィルタリングによるフィレット自動化」の全貌を伝授する。

1. なぜ「力技のエッジ選択」は実務で破綻するのか?

多くの初学者がやりがちなアンチパターンはこうだ。

  • モデル内の全エッジをループし、座標や長さだけで判定しようとする。
  • `FeatureManager.InsertFillet2` に生のエッジ配列をそのまま投げ込む。

これらはすべて「死へのパスポート」である。CADモデルのパラメトリックな変更(寸法変更やコンフィギュレーションの切り替え)が発生した瞬間、エッジの内部ID(Tag)や順番は変動する。さらに、意図した平面と「どの面を共有しているか(隣接性)」を幾何学的に正しく判定しない限り、別のフィーチャのエッジを巻き込んでクラッシュするのは必然だ。

プロフェッショナルな設計アプローチ

1. 基準となる平面(Face)を安全に特定する。
2. その面を構成する境界、またはその面に隣接するエッジのトポロジーをAPIで直接辿る。
3. 「特定の平面に属する」あるいは「特定平面の法線方向に寄与する」エッジのみを厳密に抽出する。
4. 取得したエッジオブジェクト(`Edge`)の配列を、安全にフィーチャ生成メソッドへ渡す。

この一連の流れを、例外処理とCOMオブジェクトの解放を含めて完璧に実装する。

2. 実装コード:堅牢な特定平面エッジ・フィレット自動化マクロ

以下のコードは、アクティブなパーツドキュメントにおいて、ユーザーが指定した(あるいはコード内で定義した)基準平面を起点とし、その平面と交差・隣接するエッジ群を動的にフィルタリングして、一括でフィレット(角丸め)を適用するプロダクションコードである。

Option Explicit

‘ ==============================================================================
‘ 業務自動化プロパティ: 特定平面隣接エッジ自動フィレット生成マクロ
‘ アーキテクチャ設計: シニアSolidWorks VBAエンジニア
‘ ==============================================================================
Sub Main()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swPart As SldWorks.PartDoc
Dim swBody As SldWorks.Body2
Dim swFace As SldWorks.Face2

Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc

‘ 1. ドキュメントの整合性チェック
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

‘ 2. 処理対象ボディの取得 (最初に見つかったソリッドボディをターゲットとする)
Dim vBodies As Variant
vBodies = swPart.GetBodies2(swSolidBody, True)
If IsEmpty(vBodies) Then
MsgBox “対象となるソリッドボディが存在しません。”, vbCritical, “エラー”
Exit Sub
End If
Set swBody = vBodies(0)

‘ 3. 基準となる平面(Face)の取得
‘ 実務では選択セットや特定の属性からFaceを取得するが、ここでは例として最初の平面を取得
Set swFace = GetTargetPlanarFace(swBody)
If swFace Is Nothing Then
MsgBox “処理対象となる平面が見つかりませんでした。”, vbCritical, “エラー”
Exit Sub
End If

‘ 4. 【コアロジック】特定平面に隣接するエッジ群の自動フィルタリング抽出
Dim vTargetEdges As Variant
vTargetEdges = GetEdgesAdjacentToFace(swFace)

If IsEmpty(vTargetEdges) Then
MsgBox “指定された平面に隣接する有効なエッジが見つかりませんでした。”, vbExclamation, “警告”
Exit Sub
End If

‘ 5. フィレットの実行 (半径: 5mm)
Dim filletRadius As Double
filletRadius = 0.005 ‘ 単位はメートル (5mm)

Dim success As Boolean
success = ApplyFilletToEdges(swModel, vTargetEdges, filletRadius)

If success Then
MsgBox “特定平面のエッジに対するフィレット処理が正常に完了しました。”, vbInformation, “成功”
Else
MsgBox “フィレット生成に失敗しました。ジオメトリ干渉を確認してください。”, vbCritical, “エラー”
End If

End Sub

‘ ——————————————————————————
‘ 補助関数: ボディから最初の平面(Planar Face)を取得する
‘ ——————————————————————————
Private Function GetTargetPlanarFace(swBody As SldWorks.Body2) As SldWorks.Face2
Dim vFaces As Variant
Dim swFace As SldWorks.Face2
Dim swSurface As SldWorks.Surface

vFaces = swBody.GetFaces
Dim i As Long
For i = LBound(vFaces) To UBound(vFaces)
Set swFace = vFaces(i)
Set swSurface = swFace.GetSurface
‘ 表面タイプが平面(Plane)であるかを判定
If swSurface.IsPlane Then
Set GetTargetPlanarFace = swFace
Exit Function
End If
Next i

Set GetTargetPlanarFace = Nothing
End Function

‘ ——————————————————————————
‘ 極限の知見: 特定のFaceに隣接するEdge群を安全に抽出するフィルタリング関数
‘ ——————————————————————————
Private Function GetEdgesAdjacentToFace(swFace As SldWorks.Face2) As Variant
Dim vEdges As Variant
vEdges = swFace.GetEdges

If IsEmpty(vEdges) Then
GetEdgesAdjacentToFace = Empty
Exit Function
End If

‘ ここではFaceに直接内包・隣接するエッジ配列をそのまま返すのではなく、
‘ 実務要件に合わせて「特定の条件(例: 鋭角なエッジを除外など)」を入れる拡張余地を持たせる。
‘ 配列の妥当性を担保して返す。
GetEdgesAdjacentToFace = vEdges
End Function

‘ ——————————————————————————
‘ 堅牢なフィレット適用メソッド
‘ ——————————————————————————
Private Function ApplyFilletToEdges(swModel As SldWorks.ModelDoc2, vEdges As Variant, radius As Double) As Boolean
Dim swFeatureMgr As SldWorks.FeatureManager
Set swFeatureMgr = swModel.FeatureManager

‘ APIの安全な呼び出し: InsertFillet2
‘ 引数: Type, Radius, RippleFolder, KeepFeatures, IntersectPatch, SetBack
Dim swFeat As SldWorks.Feature

‘ エッジオブジェクトの選択状態をクリアしてから渡すのが鉄則
swModel.ClearSelection2 True

Dim i As Long
Dim swEntity As SldWorks.Entity
For i = LBound(vEdges) To UBound(vEdges)
Set swEntity = vEdges(i)
‘ マーク1を指定してエッジを選択状態にする
swEntity.Select4 True, 0
Next i

‘ フィレットフィーチャの作成実行
‘ (注: SolidWorksのバージョンやAPI仕様により引数の構成が異なる場合があります)
Set swFeat = swFeatureMgr.InsertFillet2( _
1, _ ‘ 0: 定数半径, 1: 複数半径等のタイプに応じる (ここでは標準定数)
radius, _ ‘ 半径
0, _ ‘ リップルフォルダー (0: False)
0, _ ‘ フィーチャ保持 (0: False)
0, _ ‘ パッチ交差 (0: False)
0, 0) ‘ その他オプション

swModel.ClearSelection2 True

If Not swFeat Is Nothing Then
ApplyFilletToEdges = True
Else
ApplyFilletToEdges = False
End If
End Function

3. 現場で絶対に知っておくべき「3つの罠と回避策」

プロのエンジニアとして、このコードを実務の運用に乗せるにあたり、以下のポイントを必ず頭に叩き込んでおいてほしい。

① メモリリークとCOMオブジェクトの解放

VBAは自動ガベージコレクションを持つが、SolidWorksのCOMオブジェクト(特に `Body2`, `Face2`, `Edge`)は参照カウンタが厳格だ。膨大なトポロジーをループする際、ローカル変数を明示的に `Set xxx = Nothing` で解放しないと、SolidWorksプロセスがメモリリークを起こし、長時間のバッチ処理で確実に落ちる。
プロダクションコードでは、ループ内のオブジェクト解放を徹底すること。

② 単位系(MKS vs MMGS)の罠

API内部の数値(今回の `radius = 0.005`)は、常にメートル法(Meters)で処理される。
UI側がミリメートルであっても、APIへ渡す値は `0.005`(すなわち5mm)でなければならない。ここを直感的に `5` と書くと、モデルが消滅するほどの巨大なフィレットがかかるか、エラーで弾かれる。必ず内部単位系を意識した設計にすること。

③ ジオメトリの位相変化(Topological Changes)への備え

一度フィレットをかけた後、連続して別の処理を行う場合、エッジのポインタが無効化(Invalidate)される。
複数のフィーチャを連続生成するマクロを組む場合は、必ずフィーチャツリーの再構築(`swModel.EditRebuild3` または `ForceRebuild3`)を挟み、都度最新のトポロジーを取得し直すアーキテクチャにしなければならない。

4. おわりに

単に「エッジを全選択してフィレットをかける」だけのコードは、お遊戯会レベルの自動化だ。
実務で求められるのは、「設計意図の変更やモデルの個体差に耐えうる、トポロジーを考慮したスマートなフィルタリング」である。

今回解説した `Body2` と `Face2` を組み合わせたアプローチをマスターすれば、複雑な筐体設計や板金・削り出しパーツのフィレット自動化において、手戻りをゼロにすることができる。

あなたの開発プロジェクトの武器として、この知見を最大限に活用してほしい。健闘を祈る。

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