【上級プロ向け】図面ビューのバウンディングボックス演算による「ビュー同士の干渉回避」自動レイアウトエンジン
こんにちは。開発の現場へようこそ。
もしあなたが今、「マクロの記録」ボタンを押し、生成されたコードを眺めながら「なぜ、このコードはこんなに長くて読みづらいんだ?」と疑問に思っているなら、おめでとうございます。あなたはプログラミングの入り口に立ち、「自動化の本質」に触れようとしています。
マクロの記録は、あくまで「操作の録画」に過ぎません。しかし、私たちが作りたいのは「録画」ではなく、状況に応じて自ら判断して動く「知的なエンジン」です。
今回のテーマは、図面作成における究極の課題の一つ、「ビューの自動レイアウト」です。
「ビューを置いたけれど、前のビューと重なってしまった……」
そんな初歩的な問題を、数学的な「バウンディングボックス(外形矩形)」の概念を使って解決する、プロフェッショナルな設計思想を伝授しましょう。
ここをクリアすれば、あなたのSolidWorks VBAは「単なる記録」から「高度な設計ツール」へと昇華します。準備はいいですか?
1. 思考の転換:図面を「座標の集合」として捉える
多くの初心者は、図面ビューを「絵」として捉えます。しかし、エンジニアリングの視点では、図面ビューは「特定の範囲(X, Yの最小・最大値)を持つ数学的なオブジェクト」です。
バウンディングボックスとは?
図面ビューの周囲をぴったり囲む、最小の長方形のことです。
この長方形の「左端(Xmin)」「右端(Xmax)」「下端(Ymin)」「上端(Ymax)」さえ把握できれば、そのビューがどこにあり、どの程度の広さを占有しているかが完全に計算できます。
「重なり(干渉)」とは、2つのバウンディングボックスの領域が数学的に重複している状態を指します。
これを回避するアルゴリズムの基本戦略はこうです:
1. 各ビューのバウンディングボックスを取得する。
2. ビューを順番に走査する。
3. 「前のビューの右端」+「指定した余白(マージン)」の座標を、次のビューの「左端」として配置する。
2. 実装の核心:SolidWorks APIの「罠」を回避する
コードを書く前に、プロとして知っておくべき重要な仕様が2つあります。これを知らないと、計算結果がすべて狂います。
① 最初の「ビュー」は「シート」である
SolidWorksの`DrawingDoc::GetFirstView`を実行したとき、返ってくる最初のオブジェクトは、実はビューではなく「シートそのもの」です。これを見落とすと、シートの原点(0,0)を基準に全ての計算が狂い始めます。必ず「次のビュー」から処理を開始しましょう。
② 単位系の違い
SolidWorks APIの内部単位は、基本的に「メートル(m)」です。
画面上で「100mm」に見えるものは、APIの世界では `0.1` です。計算時にこのスケール感を意識しないと、マージンが「0.001mm」といった、物理的にあり得ない極小値になってしまいます。
3. 実践:自動レイアウトエンジンのソースコード
それでは、実際に動くコードを見てみましょう。このコードは、図面内の全てのビューを検出し、左から右へと重ならないように整列させる「水平レイアウトエンジン」です。
Option Explicit
' ビューの情報を格納するための構造体(プログラミングの整理術)
Private Type ViewBounds
XMin As Double
YMin As Double
XMax As Double
YMax As Double
Width As Double
Height As Double
End Type
Sub AutomaticLayoutEngine()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swDraw As SldWorks.DrawingDoc
Dim swView As SldWorks.View
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
' 1. ドキュメントが図面であるかチェック
If swModel Is Nothing Then Exit Sub
If swModel.GetType <> swDocDRAWING Then
MsgBox "図面ファイルを開いてから実行してください。"
Exit Sub
End If
Set swDraw = swModel
' レイアウト設定(単位はメートル)
Dim margin As Double
margin = 0.02 ' 20mmの余白
Dim currentX As Double
currentX = 0.05 ' 開始位置(シート端からのオフセット)
' 2. ビューの走査開始
' GetFirstViewは「シート」を返すので、GetNextViewで最初の「真のビュー」へ移動
Set swView = swDraw.GetFirstView
Set swView = swView.GetNextView
If swView Is Nothing Then
MsgBox "配置されているビューが見つかりません。"
Exit Sub
End If
' 3. レイアウト・ループ
Do While Not swView Is Nothing
Dim bounds As ViewBounds
' バウンディングボックスの取得
' GetBoundingBoxは引数に座標を受け取る「参照渡し」のスタイル
Dim vMin As Variant, vMax As Variant
swView.GetBoundingBox vMin, vMax
' 取得した座標を使いやすい形に整理
bounds.XMin = vMin(0)
bounds.YMin = vMin(1)
bounds.XMax = vMax(0)
bounds.YMax = vMax(1)
bounds.Width = bounds.XMax - bounds.XMin
bounds.Height = bounds.YMax - bounds.YMin
' --- ここがレイアウトエンジンの脳(ロジック) ---
' 現在のビューを、計算した「新しい左端(currentX)」に基づいて再配置
' 注意:ビューの配置は「中心」ではなく「左下」ではなく「位置」を指定する
' View.Positionはビューの基準点(通常は中心付近)を指定するため、
' ここでは「左端をcurrentXに合わせる」計算を行う
' 新しい中心座標を計算 (現在の中心 + 移動量)
Dim centerX As Double, centerY As Double
centerX = currentX + (bounds.Width / 2)
centerY = 0.1 ' Y軸はとりあえず固定(必要に応じて計算可能)
' 再配置の実行
swView.Position = Array(centerX, centerY)
' 次のビューのために、現在のビューの右端 + マージンを計算
currentX = currentX + bounds.Width + margin
' ----------------------------------------------
' 次のビューへ
Set swView = swView.GetNextView
Loop
' 再描画して結果を反映
swModel.EditRebuild3
MsgBox "レイアウト完了!"
End Sub
コードの解説:プロの視点
1. `Type ViewBounds` の活用:
ただ変数を使うのではなく、関連するデータを「構造体」にまとめることで、コードの可読性が劇的に上がります。これは「オブジェクト指向」への第一歩です。
2. `GetBoundingBox` の扱い:
APIの戻り値が `Variant` 型の配列であることに注意してください。`vMin(0)` が X、`vMin(1)` が Y です。
3. `currentX` による状態管理:
「次にどこに置くべきか」という状態を `currentX` という一つの変数で管理しています。これがアルゴリズムの心臓部です。
4. 陥りやすいエラーと、それを回避する「現場の知恵」
このコードを動かしたとき、もし思い通りにいかない場合は、以下の3点を疑ってください。
- ビューのスケール(Scale):
ビューのスケールが極端に大きい、あるいは小さい場合、バウンディングボックスの計算結果がシートの範囲を飛び出してしまうことがあります。実戦では、`If currentX > SheetWidth Then …` のような、改行(次の行へ移動)のロジックを組み込むのが定石です。
- 座標系の混同:
SolidWorksには「モデル空間」と「シート空間」があります。`View.Position` で操作するのは「シート空間」の座標です。常に「今、自分はどの空間の座標を触っているのか?」を自問自答してください。
- 再描画のタイミング:
ループの中で何度も `EditRebuild3`(再描画)を呼び出すと、処理速度が極端に低下します。大量のビューを扱う場合は、「計算はメモリ上で行い、最後に一括で適用する」のが、パフォーマンスを極めるエンジニアの鉄則です。
まとめ:次の一歩へ
いかがでしたでしょうか?
単に「ビューを置く」という動作を、「座標の計算によって干渉を回避する」というロジックに書き換える。これこそが、マクロを「ツール」から「ソフトウェア」へと進化させるプロセスです。
今回紹介したコードは、まだ「横一列に並べる」というシンプルなものです。ここから発展させて、「ビューの高さに合わせて2段、3段と配置する(Bin Packing問題)」や「特定の重要ビューは中央に固定する」といった機能を追加していくことができます。
「数学で空間を支配する」
この感覚を掴めれば、SolidWorks VBAの世界はあなたの思い通りになります。
さあ、コードを書き換えて、自分だけの最強のレイアウトエンジンを構築してみてください。応援していますよ!
