【入門編】【上級プロ】IMateEntity2インターフェースの動的構築:面IDの変更に一切依存しない、形状特徴量ベースのロバスト合致生成エンジン – SolidWorks VBA解析バイブル

スポンサーリンク

こんにちは!SolidWorks自動化の現場で、日々泥臭く、かつエレガントなマクロと格闘している先輩エンジニアです。

「マクロの記録」ボタンを押して生成されたコードをそのまま動かしてみたものの、設計変更でモデルの形を変えた途端にエラーが爆発した……そんな経験はありませんか?

「面IDが変更されました」「エンティティが見つかりません」というお馴染みのエラー。これ、実は合致(Mate)の自動化における永遠の呪縛なんです。

今回は、その呪縛を断ち切り、モデルの形状特徴量(トポロジー)を読み解いてダイナミックに合致を組み上げる『IMateEntity2インターフェースの動的構築』という最高峰の技術を伝授します。ここをクリアすれば、あなたのVBAスキルは間違いなくプロの領域に到達します。一緒にマスターしていきましょう!

—

なぜ「マクロの記録」の合致コードは実務で使えないのか?

まず、敵を知ることから始めましょう。
マクロの記録を使うと、以下のようなコードが出力されます。

‘ マクロの記録が吐き出す典型的なコード(危険な例)
boolstatus = swModel.Extension.SelectByID2(“Face1@Part1-1@Assembly”, “FACE”, 0, 0, 0, True, 0, Nothing, 0)
boolstatus = swModel.Extension.SelectByID2(“Face2@Part2-1@Assembly”, “FACE”, 0, 0, 0, True, 0, Nothing, 0)
swModel.AddMate2 0, 0, False, 0, 0, 0, 0, 0, 0, 0, 0, False, 0

お気づきでしょうか? `Face1` や `Face2` という「名前(内部ID)」を名指しで指定していますよね。
しかし、CADの設計変更でフィーチャーの順番が変わったり、フィレットを追加したりすると、SolidWorksは容赦なく内部IDを振り直します。結果、「Face1なんてもう無いよ!」と怒られ、マクロが盛大にクラッシュするわけです。

救世主「IMateEntity2」の考え方

プロが目指すべきアプローチは、「名前で選ぶな、特徴(幾何情報)で探せ」です。
`IMateEntity2` インターフェースを使うと、選択した面やエッジを「抽象化された合致エンティティ」としてラップし、SolidWorksのAPIに直接渡すことができます。さらに、APIの裏側で形状のトポロジー(面のタイプ、法線方向、穴の中心座標など)を評価させることで、名前の変動に一切依存しないロバスト(堅牢)な自動化エンジンが構築できるのです。

—

【実践】面IDに依存しない動的合致生成エンジン

それでは、実際のコードを見ていきましょう。
今回は、アセンブリ内に配置された部品の「円柱面(軸)」と「平坦な座面」を、形状特徴量をコード内でスキャンして自動で見つけ出し、一発で同軸&一致合致を組む実用スクリプトを書いてみました。

開発環境(VBAエディタ)を開き、以下のコードを標準モジュールに貼り付けてみてください。

‘ ==============================================================================
‘ 【上級プロ向け】IMateEntity2によるロバスト合致生成エンジン
‘ ==============================================================================
Sub CreateRobustMate()
Dim swApp As SldWorks.SldWorks
Dim swAssm As SldWorks.AssemblyDoc
Dim swModel As SldWorks.ModelDoc2

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

‘ アクティブドキュメントがアセンブリかチェック
If swModel Is Nothing Then
MsgBox “ドキュメントが開かれていません。”, vbCritical
Exit Sub
End If
If swModel.GetType() <> swDocASSEMBLY Then
MsgBox “アセンブリ文書を開いた状態で実行してください。”, vbCritical
Exit Sub
End If

Set swAssm = swModel

‘ 【ステップ1】合致させたい構成部品のコンポーネントを取得
‘ ※ここでは例として “PartA-1” と “PartB-1” という名前の部品を対象にします
Dim compA As SldWorks.Component2
Dim compB As SldWorks.Component2

Set compA = swAssm.GetComponentByName(“PartA-1”)
Set compB = swAssm.GetComponentByName(“PartB-1”)

If compA Is Nothing Or compB Is Nothing Then
MsgBox “指定されたコンポーネントが見つかりません。”, vbCritical
Exit Sub
End If

‘ 【ステップ2】形状特徴量(例:円柱面と平面)をコードから動的に特定する
‘ 実際の現場では、ここでコンポーネント内のBodyやFaceを走査(EnumFaces)し、
‘ 「半径〇mmの円柱」や「最大の平面」といった幾何条件で面を動的にHUNTします。
Dim faceA As SldWorks.Face2
Dim faceB As SldWorks.Face2

‘ 簡略化のため、ここではヘルパー関数経由で特徴量に合致する面を取得したと仮定
Set faceA = GetCylindricalFaceByRadius(compA, 10#) ‘ 半径10mmの円柱面
Set faceB = GetCylindricalFaceByRadius(compB, 10#) ‘ 半径10mmの円柱面

If faceA Is Nothing Or faceB Is Nothing Then
MsgBox “条件に合致する形状特徴量(面)が検出できませんでした。”, vbCritical
Exit Sub
End If

‘ 【ステップ3】IMateEntity2の動的構築
Dim swMateEntA As SldWorks.MateEntity2
Dim swMateEntB As SldWorks.MateEntity2

‘ 面オブジェクトをIMateEntity2としてラップする
Set swMateEntA = swAssm.CreateMateEntity(faceA, compA)
Set swMateEntB = swAssm.CreateMateEntity(faceB, compB)

‘ 【ステップ4】合致の実行(同軸合致:swMateType_CONCENTRIC = 1)
Dim errCode As Long
Dim swMate As SldWorks.Mate2

‘ AddMate3を使用して、ラッパーオブジェクト経由で堅牢に合致を定義
Set swMate = swAssm.AddMate3( _
swMateType_CONCENTRIC, _
swMateAlign_CLOSEST, _
False, _
swMateEntA, _
swMateEntB, _
0#, 0#, 0#, 0#, 0#, 0#, _
False, _
errCode)

If errCode = 0 Then
swModel.EditRebuild3
MsgBox “面IDに依存しないロバスト合致の生成に成功しました!”, vbInformation
Else
MsgBox “合致の生成に失敗しました。エラーコード: ” & errCode, vbCritical
End If

End Sub

‘ — 【ヘルパー関数】指定した半径の円柱面をボディから動的に探すロジック —
Private Function GetCylindricalFaceByRadius(comp As SldWorks.Component2, targetRadius As Double) As SldWorks.Face2
Dim swBody As SldWorks.Body2
Dim swEntity As SldWorks.Entity
Dim swFace As SldWorks.Face2
Dim swSurf As SldWorks.Surface
Dim vFaces As Variant
Dim i As Long

Set GetCylindricalFaceByRadius = Nothing

‘ コンポーネントからソリッドボディを取得
Dim vBodies As Variant
vBodies = comp.GetBodies2(swSolidBody)
If IsEmpty(vBodies) Then Exit Function

Set swBody = vBodies(0)
vFaces = swBody.GetFaces

‘ すべての面をループし、形状が「円柱」かつ「半径が一致するもの」を特定
For i = LBound(vFaces) To UBound(vFaces)
Set swFace = vFaces(i)
Set swSurf = swFace.GetSurface()

‘ 表面が円柱(Cylinder)かチェック
If swSurf.IsCylinder Then
Dim rad As Double
Dim data As Variant
data = swSurf.CylinderParams ‘ 戻り値: [中心X, Y, Z, 軸X, Y, Z, 半径]
rad = data(6)

‘ 許容誤差(0.01mm)以内で半径が一致するか
If Abs(rad – targetRadius) < 0.01 Then Set GetCylindricalFaceByRadius = swFace Exit Function End If End If Next i End Function ---

コードの核心:なぜこの方法が「最強」なのか?

上記のコードの肝は、`AssemblyDoc::CreateMateEntity` メソッドと、ヘルパー関数内で行っている `Surface::IsCylinder`(サーフェス解析) にあります。

1. 名前で選ばない(コンポーネント+面オブジェクトの直接取得)
`GetComponentByName` でアセンブリ内の部品を特定した後、その部品が持つ数理モデル(Body)を直接解析しています。
2. 幾何学的特徴(トポロジー)でのスクリーニング
「Face1」という名前を探すのではなく、「この部品のなかで、半径が10mmの円柱面はどれだ?」という数学的クエリを走らせています。これにより、設計者がモデルの形をリメイクして面名(FaceID)が「Face99」に変わろうとも、半径が10mmである限り、プログラムは一発で正しい面を捕獲し続けます。
3. IMateEntity2によるカプセル化
見つけ出した `Face2` オブジェクトを `CreateMateEntity` に通すことで、SolidWorksの合致エンジンに対して「どの部品のどの位置にある、どの幾何要素か」をコンテキスト情報ごと安全に引き渡すことができます。

—

陥りやすい罠とプロの回避術

この高度な技術を実装する際、現場でよくハマるポイントをいくつかシェアしておきます。

  • 罠1:コンポーネントのコンテキスト(マトリックス)の考慮漏れ

部品単体のローカル座標系と、アセンブリ全体(グローバル)の座標系は異なります。しかし、`CreateMateEntity` はコンポーネントのインスタンス(`Component2`)を同時に引数として受け取るため、配置ズレの計算を自動で肩代わりしてくれます。ここが `IMateEntity2` の真骨頂です。

  • 罠2:浮動小数点数の比較エラー(`Abs(rad – targetRadius) < 0.01`)

CADの内部計算ではミリメートル単位の微小な丸め誤差が発生します。厳密に `rad = 10` で判定するとヒットしないことがあるため、必ず許容誤差(イプシロン)を設けた条件分岐を組み込んでください。

—

まとめ:ここをクリアすれば、SolidWorks VBAの基本はバッチリ!

今回は、面IDの変更に一切依存しない、形状特徴量ベースのロバスト合致生成エンジンについて解説しました。

  • 「マクロの記録」の文字列依存から脱却する
  • `Body` や `Surface` のAPIを使って幾何学的に面をハントする
  • `IMateEntity2` で安全に合致オブジェクトへ昇華させる

この3ステップをモノにすれば、あなたの作る自動化マクロは、設計変更の嵐が吹いてもびくともしない「プロフェッショナル・クオリティ」へと生まれ変わります。

最初は難しく感じるかもしれませんが、この構造を一度理解してしまえば、どんなに複雑なアセンブリ構築も怖くありません。ぜひ自分の手でコードを動かし、その堅牢さを体感してみてください。
あなたのSolidWorks自動化ライフが、より一層素晴らしいものになることを応援しています!

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