【テクニカル・上級編】【実務中級】アセンブリ座標系を基準にした相対座標計算と、オフセット付き距離合致の動的プログラミング – SolidWorks VBA解析バイブル

スポンサーリンク

SolidWorks VBAを掌握する極限の知見:アセンブリ座標系を基準にした相対座標計算と動的合致プログラミング

アセンブリの自動化において、最も開発者の精神をすり減らすのは「合致(Mate)の破綻」と「座標系の錯覚」だ。
画面上のマウス操作であれば、フィーチャーマネージャツリーをドラッグし、適当な面を選んで「距離合致」を入力すれば済む話に見える。しかし、APIの世界に足を踏み入れた途端、それは幾何学的拘束のパズルと、SolidWorksの重厚長大なCOMオブジェクトライフサイクルとの孤独な戦いに変わる。

今回は、アセンブリのルート座標系(Origin)を絶対基準とし、コンポーネントの配置空間座標を数理的に算出しながら、変数によってオフセット距離を動的に制御する「距離合致(Distance Mate)」の自動定義について、実務の最前線で培った知見を余すところなく共有する。

—

1. 座標系(Transform)の厳密な把握とコンポーネント行列

多くの初学者、あるいは中級者のコードがなぜ脆弱なのか。それは「コンポーネントの位置」を単なるプロパティ値の読み書きだと誤解しているからだ。

SolidWorksアセンブリ内において、各コンポーネント(`Component2`)は、親アセンブリの原点に対する4×4の同次変換行列(Transform)を保持している。
`IMate2` インターフェースを用いて距離合致をプログラムで生成する際、単に「オフセット値を指定すればいい」と考えていると、モデルの向き(方向ベクトル)が反転したり、予期せぬソリューションエラー(`swMateError_`)を引き起こす。

特に、基準座標系からの相対計算を行う場合、以下の鉄則を遵守しなければならない。

1. トランスフォームの取得: `IComponent2::Transform2` または `IGetTransform` を使用し、ルートアセンブリ座標系における絶対位置と姿勢を抽出する。
2. ベクトル演算の分離: 座標値(X, Y, Z)と回転行列を混同しない。
3. オブジェクトの即時解放: 取得したTransformやMathTransformオブジェクトは、VBAのガベージコレクションの気まぐれに任せず、必ず明示的にメモリから解放する。

—

2. 実務仕様:基準原点からの相対計算と動的オフセット合致マクロ

以下のコードは、アセンブリ内に配置された特定の部品(例:「Block-1」)に対し、アセンブリの原点からの相対位置を計算しつつ、指定した変数に基づいて距離合致を動的に再定義する実務レベルのプロシージャだ。

単に動くだけではない。エラーハンドリング、COMオブジェクトの適切な解放、そしてSolidWorksの再構築(Rebuild)サイクルを最適化した設計となっている。

Option Explicit

‘ ==============================================================================
‘ 処理名: アセンブリ座標系基準の動的距離合致生成システム
‘ 概要 : ルート原点からの相対位置を評価し、変数オフセットを持つ距離合致をプログラムで完結させる
‘ ==============================================================================
Sub ExecuteDynamicDistanceMate()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swAssy As SldWorks.AssemblyDoc
Dim swMathUtil As SldWorks.MathUtility

‘ アプリケーションインスタンスの取得
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 <> swDocASSEMBLY Then
MsgBox “対象はアセンブリである必要があります。”, vbCritical
Exit Sub
End If

Set swAssy = swModel
Set swMathUtil = swApp.GetMathUtility

‘ 性能維持のための画面描画停止(UIフリーズ防止)
swModel.Extension.UseExtraDrawingThreads = True
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayDisableUpdateDuringRebuild, True

On Error GoTo ErrorHandler

‘ — 1. ターゲットコンポーネントとエンティティの特定 —
Dim compName As String
compName = “Block-1-1” ‘ 処理対象のコンポーネント名(インスタンス名)

Dim swComp As SldWorks.Component2
Set swComp = swAssy.GetComponentByName(compName)
If swComp Is Nothing Then
Err.Raise vbObjectError + 1000, “ExecuteDynamicDistanceMate”, “指定されたコンポーネントが見つかりません: ” & compName
End If

‘ — 2. トランスフォーム(行列)の取得と解析 —
Dim swXform As SldWorks.MathTransform
Set swXform = swComp.Transform2

‘ トランスフォームがNullでないことを確認
If Not swXform Is Nothing Then
Dim transArray As Variant
transArray = swXform.ArrayData

‘ transArray(9), transArray(10), transArray(11) がルート座標系におけるX, Y, Z平行移動成分
Debug.Print “— ” & compName & ” の絶対位置 —”
Debug.Print “X: ” & transArray(9) 1000 & ” mm”
Debug.Print “Y: ” & transArray(10) 1000 & ” mm”
Debug.Print “Z: ” & transArray(11) 1000 & ” mm”
End If

‘ — 3. 合致エンティティの選択と動的オフセット適用 —
‘ ここではアセンブリ原点側の面(あるいは参照平面)と、部品側の面を選択状態にする前提
‘ 実務では ISelectionMgr を用いて事前にクリアランスを計算・検証する

‘ 選択クリア
swModel.ClearSelection2 True

‘ エンティティの選択(例として面2つを選択状態にするロジックを想定)
‘ ※実際のコードでは SelectByID2 等で正確にエンティティを指定する
Dim boolstatus As Boolean
boolstatus = swModel.Extension.SelectByID2(“FrontPlane”, “PLANE”, 0, 0, 0, True, 1, Nothing, 0)
boolstatus = swModel.Extension.SelectByID2(“Face1@” & compName, “FACE”, 0, 0, 0, True, 1, Nothing, 0)

‘ — 4. 距離合致の追加(動的変数・オフセットの指定) —
Dim distValue As Double
distValue = 0.05 ‘ 50mm のオフセット(内部単位はメートル)

Dim mateError As Long
Dim swMate As SldWorks.Mate2

‘ AddDistanceMate2 (Distance, Flip, MateAlignment, DistanceMaximum, DistanceMinimum, …)
‘ シニアエンジニアはマジックナンバーを避け、列挙体(swMateType_e等)を明示する
Set swMate = swAssy.AddDistanceMate2( _
distValue, _
False, _
swMateAlign_e.swMateAlignALIGNED, _
0.1, 0.0, _
0, 0, 0, 0, _
False, _
mateError)

If mateError <> 0 Then
Err.Raise vbObjectError + 1001, “ExecuteDynamicDistanceMate”, “合致の作成に失敗しました。エラーコード: ” & mateError
End If

‘ 変更の反映と強制再構築
swModel.ForceRebuild3 True

ErrorHandler:
‘ — 5. 厳格なメモリ管理とオブジェクトの解放 —
‘ COMオブジェクトの参照リークを防ぐため、逆順に明示的解放を行う
Set swMate = Nothing
Set swXform = Nothing
Set swMathUtil = Nothing
Set swComp = Nothing
Set swAssy = Nothing
Set swModel = Nothing

‘ 描画・更新フラグの復元
If Not swApp Is Nothing Then
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayDisableUpdateDuringRebuild, False
End If

If Err.Number <> 0 Then
MsgBox “致命的なエラーが発生しました: ” & Err.Description, vbCritical
End If
End Sub

—

3. チーフアーキテクトが教える:実務での罠とパフォーマンス最適化の極意

上記のコードを見て、「なぜここまで厳密にオブジェクトを解放し、画面描画を止めるのか」と疑問に思うかもしれない。
数百点、数千点規模の大規模アセンブリをVBAで制御するシステムにおいて、メモリ管理と処理速度の最適化は生死を分ける問題だ。

1. COMオブジェクトの参照カウントとメモリリーク

VBAは自動ガベージコレクションを備えているが、それはVBAランタイム内部のメモリの話であって、SolidWorksの裏側で動いているC++製のCOMコンポーネントのライフサイクル管理とは別次元の話だ。
`Transform2` や `MathUtility` などのオブジェクト変数をそのまま放置すると、SolidWorksプロセス内にゾンビオブジェクトが残り続け、処理を繰り返すうちにSolidWorks自体がフリーズ(あるいはメモリ不足で強制終了)する。コードの最後で `Set xxx = Nothing` を徹底することは、プロフェッショナルの最低限の責務である。

2. 単位系の罠(内部単位は常に「メートル」)

SolidWorks APIの根底にある数学的計算は、すべてSI単位系(メートル、ラジアン、キログラム)で行われる。
図面や画面上で「50mm」と見えていても、APIに渡す数値は `0.05` でなければならない。これをミリメートル単位のまま `50` で渡すと、モデルが突然宇宙の彼方へ吹き飛ぶか、ジオメトリ崩壊を起こす。相対座標計算を行う際は、必ず単位変換のレイヤーを意識すること。

3. 再構築(Rebuild)のコスト管理

動的合致をループ処理の中で連続して作成・変更する場合、その都度 `ForceRebuild3` を呼び出すのは愚行の極みだ。
アセンブリの再構築はSolidWorksにとって最も重い処理の一つである。オフセット値の算出や複数コンポーネントの変位計算はメモリ上で完結させ、合致の定義が終わった最後に一度だけ一括して再構築を実行するアーキテクチャに設計し直すべきだ。

—

終わりに:自動化の先にあるもの

SolidWorks VBAによるアセンブリ自動配置と動的合致の制御は、単なる「手作業の代行」ではない。それは、CADの数理モデルとプログラムロジックを完全に同期させる高度なシステムエンジニアリングだ。

座標系の仕組みを咀嚼し、メモリのライフサイクルを支配した者だけが、破綻のない、実用に耐えうる真の自動化システムを構築できる。
あなたの書くコードが、単なるマクロの域を脱し、堅牢な基幹システムの一部として稼働することを期待する。

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