【上級プロ】IMateEntity2とトポロジー変更検知を組み合わせた、形状修正に極めて強いロバスト合致定義エンジンの実装
こんにちは!SolidWorks VBAの世界へようこそ。日々の設計業務や自動化ツールの開発、本当にお疲れ様です。
「マクロの記録を使って自動合致を組んでみたけれど、部品の寸法や形状を少し変えただけでエラーで止まってしまう……」
「昨日まで動いていたコードが、モデルにフィレットを1つ追加しただけで『オブジェクトがありません』と怒られる……」
こんな経験はありませんか?
これは、SolidWorks VBAの自動化に取り組む誰もが一度はぶつかる「合致の迷子(トポロジー崩壊)問題」です。
マクロの記録が書き出すコードは、`FaceId1` や `FaceId2` といった「その瞬間の一時的な名前(ID)」を頼りに合致を組みます。しかし、3Dモデルの形状が変わると、これらのIDは容赦なく内部で再割り当てされてしまいます。これがエラーの原因です。
でも、安心してください。ここをクリアすれば、あなたのSolidWorks VBAスキルは「単なるマクロ記録の切り貼り」から「実用に耐えうるプロレベルの自動化システム」へと一気にステップアップします!
今回は、形状の変更(面の増減や寸法の変更)にビクともしない、「IMateEntity2」と「幾何特徴解析」を組み合わせたロバスト(堅牢)な自動合致定義エンジンの作り方を、優しく、かつ深く解説します。一歩ずつ、一緒に学んでいきましょう!
—
1. なぜ合致は壊れるのか?「トポロジー崩壊」の正体
まずは、問題の原因をイメージ図で理解しましょう。
【マクロ記録のやり方(壊れやすい)】
「Face35」という名前の面を選択して合致!
↓
モデルにフィレット(角丸)を追加
↓
「Face35」という名前が、新しくできたフィレットの面に移り変わってしまう、
または「Face35」自体が消滅する!
↓
【エラー発生!】合致の対象が見つからない、または意図しない場所に合致される
これに対して、プロが使う「幾何特徴解析(ジオメトリ・プロファイリング)」のアプローチはこうです。
【プロのアプローチ(壊れない)】
「この部品の中で、面積が『500〜600mm²』の間で、
かつ『Z方向を向いている平面』を探し出して合致!」
↓
モデルにフィレットを追加して面のIDが変わっても……
↓
プログラムが「面積と向き」をその場で再計算して、正しい面を自動検知!
↓
【合致成功!】形状が変わっても、常に正しい面同士が結ばれる
この「ブレない合致」を実現するための主役が、`IMateEntity2` というインターフェースと、面のトポロジー(幾何情報)を読み解くAPIです。
—
2. 救世主「IMateEntity2」とは?
SolidWorks VBAで合致を定義するとき、通常は画面上のオブジェクトを選択(Select)しますが、これだと選択状態が不安定になったり、コードが複雑化します。
`IMateEntity2` は、「合致をかけるための専用の持ち手(ハンドル)」をFace(面)やEdge(エッジ)から直接取得するためのオブジェクトです。
これを使うと、画面上の選択状態(SelectionManager)に依存することなく、メモリ上で直接「この面と、あの面を、同軸で合致させる!」というスマートな命令を送ることができます。
—
3. ロバスト合致定義エンジンの設計図
今回は、以下のような「ベース部品(Plate)」と「ボス部品(Boss)」をアセンブリに配置し、「ボスの外周円筒面」と「プレートの穴の内周面」を同軸合致(Coaxial)で自動定義するシナリオを考えます。
形状が変わっても耐えられるよう、以下のステップでエンジンを実装します。
1. アセンブリ上の各コンポーネントから、3D形状の実体(`Body2`)を取り出す。
2. ボディを構成するすべての面(`Face2`)をループ処理で調べる。
3. 面の幾何情報(`Surface`)を解析し、「円筒面(Cylinder)であり、かつ半径が指定値に最も近いもの」を自動探索する。
4. 条件に合致した面から `IMateEntity2` を生成する。
5. 2つのエンティティを組み合わせて、安全に合致を定義する。
—
4. 【実戦コード】ロバスト合致定義エンジンのフル実装
それでは、具体的なVBAコードを見てみましょう。このコードは、エラーハンドリングや、形状の揺らぎを許容する「しきい値(Tolerance)」の設計など、プロの現場で実際に使われている工夫が散りばめられています。
新規のVBAモジュールに貼り付けて、挙動を確認してみてください。
Option Explicit
‘ 形状寸法のズレを許容する許容差(10ミクロン)
Private Const TOLERANCE As Double = 0.00001
”’ ==============================================================================
”’ メイン処理:ロバスト合致エンジンの実行
”’ ==============================================================================
Sub RunRobustMateEngine()
Dim swApp As SldWorks.SldWorks
Dim swAssy As SldWorks.AssemblyDoc
Dim swModel As SldWorks.ModelDoc2
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
‘ アクティブなドキュメントがアセンブリであることを確認
If swModel Is Nothing Or swModel.GetType <> swDocASSEMBLY Then
MsgBox “アセンブリドキュメントを開いた状態で実行してください。”, vbCritical
Exit Sub
End If
Set swAssy = swModel
‘ 1. アセンブリ内のコンポーネントを取得
‘ ※ここでは簡易的に、1番目と2番目の部品を対象とします
Dim swConf As SldWorks.Configuration
Dim swRootComp As SldWorks.Component2
Set swConf = swModel.GetActiveConfiguration
Set swRootComp = swConf.GetRootComponent3(True)
Dim vChildren As Variant
vChildren = swRootComp.GetChildren
If UBound(vChildren) < 1 Then MsgBox "アセンブリ内に部品が2つ以上存在することを確認してください。", vbExclamation Exit Sub End If Dim compPlate As SldWorks.Component2 Dim compBoss As SldWorks.Component2 Set compPlate = vChildren(0) ' 1つ目の部品(例:ベースプレート) Set compBoss = vChildren(1) ' 2つ目の部品(例:丸ボス) ' 2. 幾何特徴解析を用いて、合致対象の「面(Face)」を動的に探索 ' ターゲット:半径 10mm(0.010メートル)の円筒面 Dim targetRadius As Double targetRadius = 0.01 ' SolidWorks APIの基本単位は「メートル」です Dim facePlateHole As SldWorks.Face2 Dim faceBossShaft As SldWorks.Face2 Debug.Print "--- プレート側の円筒面を探索中 ---" Set facePlateHole = FindCylindricalFace(compPlate, targetRadius) Debug.Print "--- ボス側の円筒面を探索中 ---" Set faceBossShaft = FindCylindricalFace(compBoss, targetRadius) ' 面が見つからなかった場合の安全装置 If facePlateHole Is Nothing Or faceBossShaft Is Nothing Then MsgBox "条件に合致する円筒面が見つかりませんでした。形状が変更されたか、対象外の部品です。", vbCritical Exit Sub End If ' 3. Faceから「IMateEntity2」を取得 Dim mateEntPlate As SldWorks.MateEntity2 Dim mateEntBoss As SldWorks.MateEntity2 Set mateEntPlate = facePlateHole.GetMateEntity Set mateEntBoss = faceBossShaft.GetMateEntity ' 4. 合致の定義(同軸合致:Coaxial) Debug.Print "--- 同軸合致を定義中 ---" ' 確実に合致を実行するため、一度選択をクリアする swModel.ClearSelection2 True ' MateEntity2を介して選択をシミュレート Dim selData As SldWorks.SelectData Set selData = swModel.SelectionManager.CreateSelectData mateEntPlate.Select4 False, selData mateEntBoss.Select4 True, selData ' Trueで追加選択 ' アセンブリに合致を追加 (同軸合致 = swMateCOAXIAL) Dim swMate As SldWorks.Mate2 Dim mateError As Long Set swMate = swAssy.AddMate5(swMateCOAXIAL, swAlignNATURAL, False, 0, 0, 0, 0, 0, 0, 0, 0, False, False, 0, mateError) If swMate Is Nothing Then MsgBox "合致の定義に失敗しました。エラーコード: " & mateError, vbExclamation Else MsgBox "ロバスト合致が正常に定義されました!形状変化に強い合致の完成です。", vbInformation swModel.EditRebuild3 ' モデルの再構築 End If End Sub ''' ============================================================================== ''' 関数:コンポーネント内から指定された半径を持つ円筒面を探索する ''' ============================================================================== Function FindCylindricalFace(comp As SldWorks.Component2, targetRadius As Double) As SldWorks.Face2 Set FindCylindricalFace = Nothing ' コンポーネントから3Dボディ表現を取得 Dim vBodies As Variant vBodies = comp.GetBodies3(swAllBodies, Nothing) If IsEmpty(vBodies) Then Exit Function Dim bIdx As Long For bIdx = 0 To UBound(vBodies) Dim swBody As SldWorks.Body2 Set swBody = vBodies(bIdx) ' ボディ内のすべての面をループ Dim swFace As SldWorks.Face2 Set swFace = swBody.GetFirstFace Do While Not swFace Is Nothing ' 面の幾何情報を取得 Dim swSurf As SldWorks.Surface Set swSurf = swFace.GetSurface ' 円筒面(Cylinder)かどうかを判定 If swSurf.IsCylinder Then Dim cylParams As Variant cylParams = swSurf.CylinderParams ' 戻り値: [中心点x, y, z, 軸方向x, y, z, 半径] Dim currentRadius As Double currentRadius = cylParams(6) ' 7番目の要素が半径 ' 指定した半径とほぼ一致するか(浮動小数点数の比較のため誤差を許容) If Abs(currentRadius - targetRadius) < TOLERANCE Then Debug.Print " 条件に合致する円筒面を発見! 半径: " & (currentRadius 1000) & " mm" Set FindCylindricalFace = swFace Exit Function End If End If ' 次の面へ Set swFace = swFace.GetNextFace Loop Next bIdx End Function ---
5. コードの本質解説:なぜこれで形状変更に強くなるのか?
このコードの魔法は、`FindCylindricalFace` という関数にあります。
① 「名前」ではなく「性質」で探す
従来のコードが `Face35` という「誰かが決めた名前」を探していたのに対し、このプログラムは 「円筒面(IsCylinder)であり、かつ半径が10mm(0.01m)のもの」 という「物理的な性質」をボディ全体から血眼になって探します。
これなら、面全体の数がフィレット追加で10個から20個に増えようが、ターゲットとなる穴の半径が変わらない限り、必ず正確に見つけ出すことができます。
② 浮動小数点数(Double型)の計算誤差をいなす
プログラム内で `Abs(currentRadius – targetRadius) < TOLERANCE` という書き方をしています。 コンピュータの世界では、`0.01` という数値が内部的に `0.010000000004` のように極小の誤差を含むことがあります。これを `=` で愚直に比較すると、「一致しない」と判定されてしまいます。 そこで、「差の絶対値が `0.00001` 未満なら同じとみなす」という許容差(Tolerance)設計を取り入れています。これがプロの書く堅牢なコードの隠し味です。
—
6. 陥りやすいエラーと回避のコツ
ここを乗り越えれば、SolidWorks VBAの基本はバッチリマスターしたと言える重要なポイントです。
罠1: `GetBodies3` で何も取得できない
- 原因: アセンブリ内のコンポーネントが「ライトウェイト(軽量)状態」でロードされている場合、3D形状データ(ボディ)がメモリ上に展開されないため、取得に失敗します。
- 対策: 自動化を実行する前に、モデルを「解決済み(Resolved)」にするか、コード側で `comp.SetComponentState` を使って解決状態に強制変更してください。
罠2: `AddMate5` の引数が多すぎて迷子になる
- 対策: SolidWorks APIの中でも、合致を追加する `AddMate5` は引数が14個もあり、最も複雑なメソッドの一つです。
- 今回のように「同軸(`swMateCOAXIAL`)」を定義する場合は、半径や位置関係の数値(中間の引数群)は `0` を指定し、最後の `mateError` で成否を確認するスタイルが一番シンプルで安全です。
—
まとめ:ワンランク上の自動化エンジニアへ
お疲れ様でした!
今回ご紹介した「トポロジー解析」と「IMateEntity2」を組み合わせた手法は、SolidWorksの自動合致において最も信頼性の高いプロ御用達のアプローチです。
モデルの形状変更を恐れる必要はもうありません。プログラムが「モデルの形状を理解し、自ら考えて合致を定義する」という、インテリジェントな動きを体験できたのではないでしょうか。
このように「幾何情報を動的に探る」という考え方は、合致だけでなく、自動寸法公差の付与や、自動CAMツールへの受け渡しなど、あらゆる応用分野で基礎となる最強の武器になります。
一歩一歩、楽しみながらコードを書いていきましょう。あなたのエンジニアライフがより豊かになることを心から応援しています!
