DrawingDocとModelDoc2の双方向トラバーサル:図面から参照モデルの寸法を逆駆動する極限の知見
設計自動化の領域において、多くのエンジニアが「図面を作成する」あるいは「モデルから寸法を抽出する」という単方向のフローで満足してしまう。しかし、真に堅牢なPLM(Product Lifecycle Management)システムや、高度な設計支援ツールを構築するアーキテクトに求められるのは、2D図面(DrawingDoc)と3Dモデル(ModelDoc2)の間の「意味的結合(Semantic Link)」を、APIレベルで完全に制御することである。
図面上の寸法、あるいは投影ビューは、単なるグラフィックデータではない。それは3Dモデル内の特定のフィーチャー、あるいは特定の幾何学的拘束の「投影された写し」に過ぎない。本稿では、図面ビューから背後の3Dモデルへとトラバース(走査)し、図面上の選択情報をトリガーとしてモデル側のフィーチャーや寸法を操作・ハイライトする、高度な双方向制御手法について詳説する。
1. 階層構造の深層:DrawingViewからModelDoc2への橋渡し
図面操作において、最も基本的な、しかし誤解されやすい概念が「View」の正体である。`DrawingView`オブジェクトは、特定の`ModelDoc2`(PartまたはAssembly)を投影するための「窓」として機能する。
図面上の要素(寸法、注釈、ビュー)を操作する場合、我々は常に`DrawingDoc`のコンテキストにいる。しかし、その背後にある実体(Source of Truth)にアクセスするためには、`DrawingView`を経由してモデルのポインタを奪取しなければならない。
オブジェクト・トラバーサルの論理フロー
1. `SelectionMgr` を介して、図面上の選択オブジェクト(`DisplayDimension` または `View`)を特定する。
2. 選択されたオブジェクトが `DisplayDimension` であれば、その `GetModelDimension` メソッドを呼び出し、3Dモデル側の `Dimension` オブジェクトを取得する。
3. 選択されたオブジェクトが `View` であれば、`GetModelDoc2` を呼び出し、モデルのルート(`PartDoc` または `AssemblyDoc`)へアクセスする。
ここで重要なのは、「図面の寸法(DisplayDimension)」と「モデルの寸法(Dimension)」は、メモリ上では全く異なるクラスであるという事実だ。この乖離を理解していないコードは、ランタイムエラーを頻発させる。
2. 実装:図面選択をトリガーとしたモデルフィーチャーの逆駆動
以下に、図面上の寸法を選択した際、そのソースとなる3Dモデルのフィーチャーを特定し、モデルをアクティブにしてハイライトする、実戦的なVBAモジュールを示す。
Option Explicit
' ======================================================================================
' Module: TraversalEngine
' Description: DrawingDocからModelDoc2への双方向トラバーサルを実現する
' Author: Legendary Chief Architect
' ======================================================================================
Public Sub ReverseDriveModelFromDrawing()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swDraw As SldWorks.DrawingDoc
Dim swSelMgr As SldWorks.SelectionMgr
Dim swSelObj As Object
Dim swDispDim As SldWorks.DisplayDimension
Dim swModelDim As SldWorks.Dimension
Dim swView As SldWorks.View
Dim targetModel As SldWorks.ModelDoc2
Dim targetFeature As SldWorks.Feature
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
' 1. コンテキストチェック: アクティブなドキュメントは図面か?
If swModel Is Nothing Then Exit Sub
If swModel.GetType <> swDocDRAWING Then
MsgBox "図面ドキュメントを開いた状態で実行してください。", vbCritical
Exit Sub
End If
Set swDraw = swModel
Set swSelMgr = swModel.SelectionManager
' 2. 選択オブジェクトの解析
Set swSelObj = swSelMgr.GetSelectedObject6(1, -1)
If swSelObj Is Nothing Then
MsgBox "図面上の寸法またはビューを選択してください。", vbExclamation
Exit Sub
End If
' 3. トラバーサル・ロジック
' パターンA: 図面寸法(DisplayDimension)が選択されている場合
If TypeOf swSelObj Is SldWorks.DisplayDimension Then
Set swDispDim = swSelObj
Set swModelDim = swDispDim.GetModelDimension ' 3Dモデル側の寸法を取得
If Not swModelDim Is Nothing Then
' モデルのコンテキストを取得
Set targetModel = swModelDim.ModelDoc
Set targetFeature = swModelDim.GetFeature
' モデル側へジャンプし、ハイライトを実行
Call ExecuteModelJump(targetModel, targetFeature)
End If
' パターンB: ビュー(View)が選択されている場合
ElseIf TypeOf swSelObj Is SldWorks.View Then
Set swView = swSelObj
Set targetModel = swView.GetModelDoc2
If Not targetModel Is Nothing Then
' ビューが参照するモデルのルートをハイライト(例として)
Call ExecuteModelJump(targetModel, targetModel.FirstFeature)
End If
Else
MsgBox "対象となるオブジェクトが特定できません。", vbInformation
End If
' --- メモリ管理: COMオブジェクトの明示的解放 ---
' 大規模アセンブリを扱う場合、これを行わないとメモリリークの原因となる
Set swDispDim = Nothing
Set swModelDim = Nothing
Set swView = Nothing
Set swSelMgr = Nothing
Set swDraw = Nothing
Set swModel = Nothing
End Sub
' --------------------------------------------------------------------------------------
' Sub: ExecuteModelJump
' Purpose: モデルを前面に出し、特定フィーチャーを選択状態にする
' --------------------------------------------------------------------------------------
Private Sub ExecuteModelJump(ByRef targetDoc As SldWorks.ModelDoc2, ByRef targetFeat As SldWorks.Feature)
' モデルをアクティブにする(Windows APIレベルの制御が必要な場合もあるが、APIで完結)
' ここでは、対象ドキュメントを可視化し、フィーチャーを選択させる
' 1. モデル側のウィンドウをフォーカス
' 注意: SolidWorksの内部状態を強制的に切り替えるため、
' 複雑なアセンブリでは、モデルのドキュメントを一度開く、またはActivateする必要がある
' 2. フィーチャーの選択
' SelectionManagerのコンテキストが図面にあるため、targetDocに対してSelectByID2を明示的に呼ぶ
Dim status As Boolean
status = targetDoc.Extension.SelectByID2(targetFeat.Name, "=", False, 0, 0, 0)
If status Then
' モデル側の画面を更新し、ユーザーに提示
targetDoc.ViewZoomToSelection2
MsgBox "モデル側のフィーチャー [" & targetFeat.Name & "] を特定しました。", vbInformation
Else
MsgBox "フィーチャーの選択に失敗しました。", vbCritical
End If
End Sub
3. アーキテクトの視点:パフォーマンスと安定性の極限
このコードを実用的なプロダクション環境(数千個の部品を持つ大規模アセンブリ)に投入する場合、単なる「動くコード」では不十分である。以下の3点について、設計思想に組み込む必要がある。
A. メモリ管理とCOM参照カウント
VBAはガベージコレクションが緩慢である。特に `DrawingDoc` から `ModelDoc2` へとオブジェクトの参照を渡す際、循環参照が発生しやすい。`Set obj = Nothing` による明示的な解放は、単なる作法ではなく、長時間稼働する自動化サーバーにおいては「必須の生存戦略」である。
B. コンテキスト・スイッチングのコスト
`targetDoc.Extension.SelectByID2` を呼び出す際、SolidWorksの内部エンジンは「図面コンテキスト」から「モデルコンテキスト」への切り替えを試みる。この際、大規模アセンブリではグラフィックスの再構築(Regenerate)が走り、処理が数秒停止することがある。
これを回避するためには、「操作が必要になるまでモデル側へのアクセスを遅延させる(Lazy Loading)」設計が不可欠である。
C. Windows APIによるウィンドウ制御の必要性
API経由でモデルを操作しても、ユーザーの画面(GUI)が図面のまま残る場合がある。これは、SolidWorksがマルチドキュメント環境において、アクティブなウィンドウの管理をAPIの呼び出しと同期させていないことが原因だ。
極限のユーザー体験を求めるならば、`user32.dll` の `SetForegroundWindow` を呼び出し、モデル側のウィンドウハンドルを強制的に最前面へ持ってくる実装を検討せよ。
結語
図面とモデルの双方向トラバーサルをマスターすることは、単なるプログラミングスキルの向上ではない。それは、CADデータが持つ「幾何学的な意味」を、デジタル空間において完全に再定義する行為である。
この知見を武器に、単なる「作業の自動化」を超え、「設計意図の自動制御」へと踏み込んでほしい。
