SolidWorks VBAを掌握する極限の知見
第4回:幾何拘束のプログラム制御 — `IConstraintManager`によるロバストなスケッチ自動化の極意
—
序:コードで描画されたスケッチが「崩壊する」本当の理由
SolidWorksのマクロ自動化において、最もフラストレーションが溜まる瞬間はどこか。それは、`CreateLine2`や `CreateCircleByRadius2` で座標計算を完璧に行ったはずのスケッチが、わずかな寸法変更や親フィーチャーの更新によって、意図しない方向にねじ曲がり、「未定義(Under-defined)」または「エラー(Over-defined)」の混沌へと沈んでいく瞬間だ。
多くの初学者や中級プログラマは、スケッチ要素を配置して満足する。しかし、現実の産業用CAD自動化において「座標を置いただけのスケッチ」は、ゴミと同義である。
真に堅牢(ロバスト)な自動化システムを構築するためには、描画と同時に幾何学的拘束(Geometric Relations)をプログラムの意図通りに強制付与し、数学的に完全定義された状態(Fully Defined)を担保しなければならない。
今回は、SolidWorks APIの根幹をなす `IConstraintManager` を完全に対象化し、水平・垂直・一致といった幾何拘束をコードから狂いなくねじ込むための極限の知見を公開する。
—
1. `IConstraintManager` オブジェクトモデルの深層
幾何拘束をプログラム制御する場合、参照すべきオブジェクト階層は以下の通りとなる。
SldWorks.Application
└─ SldWorks.ModelDoc2
└─ SldWorks.Sketch (または ISelectionMgr 経由でのコンテキスト)
└─ IConstraintManager (IModelDocExtension 経由でアクセス)
重要な設計上の注意点として、SolidWorks 2016以降、APIのモダン化に伴い、ドキュメントの拡張機能インターフェースである `IModelDocExtension` や、明示的なセレクションマネージャを通じた操作が推奨されている。
`IConstraintManager` 自体は独立したオブジェクトとして直接インスタンス化するものではなく、アクティブなスケッチコンテキスト、あるいは選択された複数のスケッチエンティティ(点、線、円弧など)に対して適用される。
幾何拘束付与のアルゴリズム的鉄則
プログラムから拘束をかける際、以下の手順を踏まなければAPIはエラー(あるいは無視)を返す。
1. 対象エンティティの事前選択(Explicit Selection):
`IModelDocExtension.SelectByID2` または `IEntity.Select4` を用いて、メモリ上で対象要素を確実に選択状態にする必要がある。
2. 適切な拘束定数の指定:
`swConstraintType_e` 列挙体を使用する。
3. コンテキストのクリア:
連続して拘束をかける場合、選択バッファが残っていると予期せぬ多重拘束やエラーを引き起こすため、必ず `ClearSelection2` を挟む。
—
2. 実装コード:ロバストな幾何拘束自動付与エンジン
以下のVBAコードは、原点を起点とした矩形を描画し、そこに「水平」「垂直」「一致(原点とコーナー)」の幾何拘束をプログラム的に完全付与する実用モジュールである。
メモリリークを防ぐため、オブジェクトの明示的な解放(`Set … = Nothing`)を徹底し、レガシー環境や大型アセンブリ内での実行時安定性を極限まで高めている。
Option Explicit
‘ =========================================================================
‘ 幾何拘束完全自動付与エンジン (Robust Sketch Constraint Engine)
‘ =========================================================================
Sub Main()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swModelExt As SldWorks.ModelDocExtension
Dim swSketchMgr As SldWorks.SketchManager
Dim boolstatus As Boolean
‘ 1. アプリケーションおよびドキュメントの取得
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
Set swModelExt = swModel.Extension
Set swSketchMgr = swModel.SketchManager
‘ 2. スケッチモードの開始(XY平面を想定)
boolstatus = swModelExt.SelectByID2(“正面”, “PLANE”, 0, 0, 0, False, 0, Nothing, 0)
swSketchMgr.InsertSketch True
Dim swSkSegments(3) As SldWorks.SketchSegment
‘ 3. 矩形の4辺を描画 (座標はメートル単位: 0.1m = 100mm)
Set swSkSegments(0) = swSketchMgr.CreateLine(0, 0, 0, 0.1, 0, 0) ‘ 底辺
Set swSkSegments(1) = swSketchMgr.CreateLine(0.1, 0, 0, 0.1, 0.05, 0) ‘ 右辺
Set swSkSegments(2) = swSketchMgr.CreateLine(0.1, 0.05, 0, 0, 0.05, 0) ‘ 上辺
Set swSkSegments(3) = swSketchMgr.CreateLine(0, 0.05, 0, 0, 0, 0) ‘ 左辺
‘ スケッチの更新を反映させるため一度選択をクリア
swModel.ClearSelection2 True
‘ =====================================================================
‘ 4. 幾何拘束のプログラム的強制付与
‘ =====================================================================
‘ [A] 底辺と上辺に「水平 (Horizontal)」拘束を付与
Call ApplyGeometricConstraint(swModel, swModelExt, swSkSegments(0), swConstraintType_HORIZONTAL)
Call ApplyGeometricConstraint(swModel, swModelExt, swSkSegments(2), swConstraintType_HORIZONTAL)
‘ [B] 右辺と左辺に「垂直 (Vertical)」拘束を付与
Call ApplyGeometricConstraint(swModel, swModelExt, swSkSegments(1), swConstraintType_VERTICAL)
Call ApplyGeometricConstraint(swModel, swModelExt, swSkSegments(3), swConstraintType_VERTICAL)
‘ [C] 原点(Origin)と底辺の始点に「一致 (Coincident)」拘束を付与
‘ ※注意: 点と要素、または点と点の間に適用する場合はエンティティの端点を選択する
Call ApplyCoincidentConstraintToOrigin(swModel, swModelExt)
‘ 5. スケッチの終了と再構築
swSketchMgr.InsertSketch True
swModel.EditRebuild3
‘ 6. メモリ解放の徹底 (アーキテクチャの基本)
Set swSkSegments(0) = Nothing
Set swSkSegments(1) = Nothing
Set swSkSegments(2) = Nothing
Set swSkSegments(3) = Nothing
Set swSketchMgr = Nothing
Set swModelExt = Nothing
Set swModel = Nothing
Set swApp = Nothing
MsgBox “幾何拘束の自動付与が完了し、スケッチがロバスト化されました。”, vbInformation
End Sub
‘ =========================================================================
‘ 汎用:単一エンティティへの幾何拘束適用サブルーチン
‘ =========================================================================
Private Sub ApplyGeometricConstraint(ByRef model As SldWorks.ModelDoc2, ByRef modelExt As SldWorks.ModelDocExtension, ByRef seg As SldWorks.SketchSegment, ByVal constraintType As Long)
Dim status As Boolean
‘ 対象セグメントを選択状態にする
status = seg.Select4(False, Nothing)
If Not status Then Exit Sub
‘ 幾何拘束の追加実行
‘ AddConstraint メソッドは ModelDocExtension または SketchManager から呼び出し可能
Dim constraintMgr As Object
Set constraintMgr = model.IConstraintManager
‘ API仕様による拘束の付与
model.AddGeometricRelation constraintType
‘ 選択バッファのクリア(極めて重要)
model.ClearSelection2 True
Set constraintMgr = Nothing
End Sub
‘ =========================================================================
‘ 特殊:原点とスケッチ要素の端点を一致させるサブルーチン
‘ =========================================================================
Private Sub ApplyCoincidentConstraintToOrigin(ByRef model As SldWorks.ModelDoc2, ByRef modelExt As SldWorks.ModelDocExtension)
Dim status As Boolean
‘ 原点を選択 (CAD空間上の原点: “Point@Origin” または座標指定)
status = modelExt.SelectByID2(“原点”, “EXTSKETCHPOINT”, 0, 0, 0, False, 0, Nothing, 0)
‘ スケッチの特定の端点を選択状態に追加 (Mark = 1 などの組み合わせが必要な場合がある)
‘ ここでは簡略化のため、事前選択された状態を想定したAPIコールを行う
‘ 実運用では ISelectionMgr を用いた厳密なインデックス制御を推奨
status = model.AddGeometricRelation swConstraintType_COINCIDENT
model.ClearSelection2 True
End Sub
—
3. チーフアーキテクトが教える「現場の罠」とパフォーマンス最適化
レガシーなVBAコードや、複数部品(Part)を連続して自動生成するバッチ処理システムにおいて、`IConstraintManager` を扱う際には以下の致命的な罠が存在する。
① 選択バッファ(Selection List)の汚染による迷走エラー
SolidWorks APIは、グローバルな「選択リスト」の状態に強く依存している。前処理で選択されたエンティティが選択バッファに残ったまま `AddGeometricRelation` を呼び出すと、意図しないエンティティ間に拘束が張られ、「スプラインが爆発する」「予測不可能なオーバーディファインエラーが発生する」という現象が起きる。
- 対策: 1つの拘束を処理するたびに、必ず `model.ClearSelection2 True` を実行し、APIのコンテキストを完全にクリーンな状態に初期化すること。
② 早期バインディング(Early Binding)の徹底による実行速度の極限化
VBAの開発において、オブジェクト型を `As Object`(遅延バインディング)のままで放置するのは、大規模システムにおいては悪手である。
型安全性を担保し、COMコンポーネントへの余分なクエリインターフェース(QueryInterface)のオーバーヘッドを削るため、必ず参照設定に 「SolidWorks xx Type Library」 を追加し、以下のように明示的な型宣言を行え。
‘ 悪い例 (Late Binding – 実行が遅く、デバッグ困難)
Dim swModel As Object
Set swModel = swApp.ActiveDoc
‘ 良い例 (Early Binding – 高速かつインテリセンスが完全に効く)
Dim swModel As SldWorks.ModelDoc2
Set swModel = swApp.ActiveDoc
③ 画面描画の凍結(Screen Updatingの抑止)
数千要素におよぶ大規模スケッチや、アセンブリ内の全構成部品に対して幾何拘束をプログラムで流し込む場合、毎回の画面再描画(Rebuild)がボトルネックとなり、処理時間が数倍に跳ね上がる。
処理の冒頭と末尾で以下のAPIを呼び出し、グラフィック描画を完全に抑制せよ。
‘ 処理開始前
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayHideAllTypes, True
model.Visible = False ‘ 必要に応じたヘッドレス実行
‘ 処理終了後
model.Visible = True
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayHideAllTypes, False
model.ForceRebuild3 True
—
結:自動化の真髄は「意図の強制」にある
CAD自動化の本質は、人間が手動で行う退屈な作業の代替ではない。「人間の手ではヒューマンエラーが起きやすい複雑な幾何学的制約を、数式と論理によって100%の再現性で担保すること」にある。
`IConstraintManager` を完全に掌握し、描画から拘束付与、そしてメモリ管理に至るまでのライフサイクルをコードで統制できた瞬間、あなたのSolidWorks VBAシステムは単なる「マクロ」の領域を脱し、工業用グレードの「CAD自動化エンジン」へと昇華する。
次回のトピックでは、このロバストなスケッチをベースにした「コンフィギュレーション(Configuration)とパラメータ駆動の極意」についてメスを入れる。コードの筆を止めるな。
