【テクニカル・上級編】【上級プロ向け】大規模アセンブリ図面の自動生成における「軽量表現(Lightweight)」と「解像度」の動的最適化 – SolidWorks VBA解析バイブル

スポンサーリンク
スポンサーリンク

巨大アセンブリ図面生成におけるメモリ・アーキテクチャ:軽量表現と解像度の動的制御

設計現場において、数千、数万のコンポーネントを含む超大規模アセンブリの図面化は、単なる「自動化」の範疇を超えた「リソース管理の戦い」へと変貌する。

多くの開発者が陥る罠がある。それは、`CreateDrawViewFromModelView` を呼び出す際、SolidWorksがモデルをどのようにメモリ上に展開するかを制御せず、OSの仮想メモリとSolidWorksのヒープ領域の限界にすべてを委ねてしまうことだ。その結果、システムはスラッシング(Disk Swapping)を起こし、最終的には `Out of Memory` または応答なしのフリーズへと至る。

本稿では、単にビューを作成するコードではない。Windows APIを用いてプロセスのメモリ圧力を監視し、コンポーネントの「軽量表示(Lightweight)」状態を動的に制御することで、極限までメモリ消費を抑制しつつ、図面の品質(解像度)を担保する、プロフェッショナル向けのアーキテクチャを提示する。

1. 概念的基盤:Lightweight 状態の戦略的運用

SolidWorksにおける「軽量表示(Lightweight)」は、単なる表示モードではない。それは、コンポーネントのフィーチャツリーの大部分をメモリから排出し、ジオメトリの境界ボックスと最小限のグラフィックスデータのみを保持する「低解像度プロキシ」の状態である。

大規模図面生成における黄金律は以下の通りである:
1. Assembly Open: 全コンポーネントを `Lightweight` モードで開く。
2. View Creation: 図面ビューの生成は `Lightweight` 状態で実行する。
3. Selective Resolution: 断面図や詳細図が必要な箇所、あるいは特定の重要部品のみを `Resolved`(完全解決)状態へ昇格させる。
4. Garbage Collection: 各オブジェクトの参照を明示的に破棄し、COMの生存期間を管理する。

2. 実装:メモリ監視と動的制御の統合

以下に、Windows APIを用いたメモリ使用量監視機能を組み込んだ、堅牢な図面生成エンジンのコアロジックを示す。

Option Explicit

' --- Windows API Declarations for Memory Monitoring ---
Private Type PROCESS_MEMORY_COUNTERS
    cb                         As Long
    PageFaultCount             As Long
    PeakWorkingSetSize         As LongPtr
    WorkingSetSize             As LongPtr
    QuotaPeakPagedPoolUsage    As LongPtr
    QuotaPagedPoolUsage        As LongPtr
    QuotaPeakNonPagedPoolUsage As LongPtr
    QuotaNonPagedPoolUsage     As LongPtr
    PagefileUsage              As LongPtr
    PeakPagefileUsage          As LongPtr
End Type

If VBA7 Then

Private Declare PtrSafe Function GetCurrentProcess Lib "kernel32" () As LongPtr Private Declare PtrSafe Function GetProcessMemoryInfo Lib "psapi.dll" ( _ ByVal hProcess As LongPtr, _ ByRef lpCounters As PROCESS_MEMORY_COUNTERS, _ ByVal cb As Long) As Long

Else

Private Declare Function GetCurrentProcess Lib "kernel32" () As Long Private Declare Function GetProcessMemoryInfo Lib "psapi.dll" ( _ ByVal hProcess As Long, _ ByRef lpCounters As PROCESS_MEMORY_COUNTERS, _ ByVal cb As Long) As Long

End If

' --- Global Constants --- Private Const MEMORY_THRESHOLD_MB As Long = 8192 ' 8GBを超えたら警告/停止する閾値 ''' <summary> ''' 現在のプロセスのWorking Set(物理メモリ使用量)をMB単位で取得する ''' </summary> Private Function GetCurrentMemoryUsageMB() As Long Dim counters As PROCESS_MEMORY_COUNTERS Dim hProcess As LongPtr Dim ret As Long hProcess = GetCurrentProcess() ret = GetProcessMemoryInfo(hProcess, counters, LenB(counters)) If ret <> 0 Then GetCurrentMemoryUsageMB = counters.WorkingSetSize / 1024 / 1024 Else GetCurrentMemoryUsageMB = 0 End If End Function ''' <summary> ''' 大規模アセンブリ図面生成のメインルーチン ''' </summary> Public Sub GenerateLargeAssemblyDrawing() Dim swApp As SldWorks.SldWorks Dim swModel As SldWorks.ModelDoc2 Dim swAssy As SldWorks.AssemblyDoc Dim swDraw As SldWorks.DrawingDoc Dim swView As SldWorks.View Dim swComp As SldWorks.Component2 Dim vComps As Variant Dim i As Long On Error GoTo ErrorHandler Set swApp = Application.SldWorks ' 1. アセンブリを軽量モードで開く(重要:OpenDoc6の引数で制御) ' ※ここでは既存の開いているモデルを対象とする例 Set swModel = swApp.ActiveDoc If swModel Is Nothing Then Exit Sub If swModel.GetType <> swDocASSEMBLY Then Exit Sub Set swAssy = swModel ' 2. メモリ監視開始 Debug.Print "Initial Memory Usage: " & GetCurrentMemoryUsageMB() & " MB" ' 3. 全コンポーネントを強制的にLightweightに設定 ' これにより、図面作成時のメモリスパイクを劇的に抑制する vComps = swAssy.GetComponents(False) For i = 0 To UBound(vComps) Set swComp = vComps(i) ' Lightweight状態への移行 swComp.SetLightweight swTrue Next i ' 4. 新規図面作成 Dim drwTemplate As String drwTemplate = "C:\Templates\LargeAssembly_Standard.drwdot" Set swDraw = swApp.NewDocument(drwTemplate, 0, 0, 0) If swDraw Is Nothing Then Err.Raise 1001, , "Template not found." End If ' 5. ビューの配置 ' 軽量モードのままビューを作成 Set swView = swDraw.CreateDrawViewFromModelView3(swModel.GetPathName, "*Front", 0.1, 0.1, 0) If Not swView Is Nothing Then ' 6. 特定のコンポーネントのみを「Resolved」に昇格させる(動的最適化) ' 例えば、中心となる主要部品だけを解像させることで、メモリを節約しつつ精度を保つ ' ここでは例として、最初のコンポーネントのみを対象とする If UBound(vComps) >= 0 Then Set swComp = vComps(0) swComp.SetLightweight False ' Resolved状態へ Debug.Print "Component " & swComp.Name2 & " resolved." End If End If ' 7. メモリチェック Debug.Print "Post-Processing Memory Usage: " & GetCurrentMemoryUsageMB() & " MB" If GetCurrentMemoryUsageMB() > MEMORY_THRESHOLD_MB Then MsgBox "Critical Memory Usage Detected: " & GetCurrentMemoryUsageMB() & " MB. Please optimize or increase RAM.", vbCritical End If ' --- Cleanup: 明示的なオブジェクト解放 --- ' VBAのGCに頼らず、COM参照を確実に断ち切る Set swView = Nothing Set swDraw = Nothing Set swAssy = Nothing Set swModel = Nothing Set swApp = Nothing MsgBox "Process Completed Successfully.", vbInformation Exit Sub ErrorHandler: MsgBox "Error " & Err.Number & ": " & Err.Description, vbCritical ' エラー時も可能な限り解放を試みる Set swView = Nothing Set swDraw = Nothing Set swAssy = Nothing Set swModel = Nothing Set swApp = Nothing End Sub

3. アーキテクチャの核心:なぜこの手法が「極限」なのか

3.1 Windows APIによる「外からの監視」

VBA内部の変数(`swApp` 等)の状態だけを見ていても、OSレベルでのメモリ圧力を把握することは不可能だ。`GetProcessMemoryInfo` を用いることで、SolidWorksプロセスが物理メモリ(Working Set)をどれだけ食いつぶしているかをリアルタイムに数値化できる。これは、バッチ処理などで長時間稼働させる自動化システムにおいて、プロセスの異常終了を未然に防ぐための「防波堤」となる。

3.2 コンポーネント・ライフサイクルの制御

通常の自動化スクリプトは、アセンブリを開いてそのまま図面を作る。しかし、これではSolidWorksはすべてのフィーチャを計算(Resolve)しようとする。
本コードの肝は、`swComp.SetLightweight swTrue` による強制的なプロキシ化である。図面ビューを作成する際、SolidWorksは軽量モデルのジオメトリのみを使用してビューを構築するため、メモリ消費量は指数関数的に減少する。

3.3 COMオブジェクトの明示的解放

VBAにおいて `Set obj = Nothing` は、単なる慣習ではない。大規模なループ処理や複雑な階層構造を持つオブジェクトを扱う場合、参照カウントが正しく減少しない限り、メモリは解放されない。特に `Component2` や `View` オブジェクトは、背後のC++実装側で巨大なリソースを保持しているため、これらを明示的に `Nothing` にすることは、メモリリークを防ぐための「儀式」ではなく「必須の設計要件」である。

4. 結論

大規模アセンブリの図面自動化における真のエンジニアリングとは、SolidWorksの機能を使いこなすことだけではない。OSのリソース、COMの参照カウント、そしてメモリの動的な振る舞いを予測し、制御することにある。

「動けばいい」というコードは、小規模なテスト環境では通用する。しかし、数千人のエンジニアが利用する社内標準システムや、数万点の部品を扱うプロダクト開発の現場では、こうした「メモリ・アーキテクチャ」への深い理解が、システムの信頼性を決定づけるのだ。

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