図面の「美しさ」をコードで制御する:寸法線の重なりを自動解消する極限のレイアウト・アルゴリズム
こんにちは。設計自動化の世界へようこそ。
「マクロの記録」ボタンを押して、録画されたコードを眺めて「ふーん、これで動くのか」と思ったことはありませんか? もしそうなら、あなたは今、「自動化の入り口」に立っています。しかし、プロフェッショナルなエンジニアが作るツールは、単なる操作の再生ではありません。
彼らが作るのは、「図面の意図を理解し、空間を再構築する知的なプログラム」です。
今日のテーマは、図面作成において最も泥臭く、かつ時間を奪われる作業の一つ、「寸法線の重なり(衝突)の解消」です。自動配置された寸法が重なり、視認性が悪くなった図面。これを手作業で一つずつ動かすのは、エンジニアの仕事ではありません。
この記事では、寸法線の座標を解析し、数学的なルールに基づいて「整然とした間隔」へと再配置する、中級者へのステップアップとなるマクロの実装方法を解説します。
1. なぜ「マクロの記録」では到達できないのか?
マクロの記録は、「A地点をクリックして、B地点にドラッグした」という「動作の断片」しか記録しません。しかし、寸法が重なっているかどうかを判断するには、以下の「思考プロセス」が必要になります。
1. 検知: 「この寸法線とあの寸法線は、座標的に衝突しているか?」
2. 計算: 「衝突しているなら、どれくらい離せば綺麗に見えるか?」
3. 実行: 「計算した新しい座標へ、正確に移動させる」
この「もし〜なら(If)、〜する(Then)」という論理構造を組み立てるには、SolidWorksの背後にあるオブジェクトモデル(Object Model)を正しく理解し、APIを自在に操る必要があります。
2. 攻略の鍵:SolidWorksのオブジェクト階層を理解する
寸法線を操作するためには、まず「どこに何があるか」という住所を正確に特定しなければなりません。SolidWorksの図面における階層構造は、以下のようになっています。
`DrawingDoc (図面)`
$\rightarrow$ `Sheet (シート)`
$\rightarrow$ `View (図面ビュー)`
$\rightarrow$ `Annotation (注釈)`
$\rightarrow$ `Dimension (寸法)`
初心者が陥りやすい罠は、「図面(DrawingDoc)からいきなり寸法を操作しようとする」ことです。寸法は「ビュー」の中に属しており、さらに「注釈」という共通の枠組みの中に存在します。この階層(Hierarchy)を一段ずつ降りていく感覚が、APIマスターへの第一歩です。
3. 実践:寸法線衝突解消マクロ
それでは、具体的なコードを見ていきましょう。このコードは、ビュー内の寸法線の位置(X, Y座標)を取得し、垂直方向に重なりがある場合に、一定の間隔(オフセット)を空けるように再配置するロジックを持っています。
'**
' 題名: Dimension Collision Resolver (寸法衝突解消マクロ)
' 概要: 図面ビュー内の寸法線の位置を解析し、垂直方向に重なるものを自動オフセットする
'**
Option Explicit
Sub main()
' --- 1. オブジェクトの宣言 ---
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swDraw As SldWorks.DrawingDoc
Dim swSheet As SldWorks.Sheet
Dim swView As SldWorks.View
Dim swAnn As SldWorks.Annotation
Dim swDispDim As SldWorks.DisplayDimension
Dim vAnns As Variant
Dim i As Long, j As Long
' 設定パラメータ
Const MIN_DISTANCE As Double = 0.005 ' 最低限確保したい間隔 (メートル単位: 5mm)
' --- 2. SolidWorksへの接続と初期チェック ---
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
' 図面が開かれていない場合は終了
If swModel Is Nothing Then Exit Sub
If swModel.GetType <> swDocDRAWING Then
MsgBox "図面ファイルを開いてから実行してください。"
Exit Sub
End If
Set swDraw = swModel
' --- 3. ビューのループ処理 ---
' 全てのビューを走査して、寸法を探していく
Set swView = swDraw.GetFirstView ' シート自体(第一ビュー)
Do While Not swView Is Nothing
' 注釈(Annotation)のコレクションを取得
vAnns = swView.GetAnnotations
If Not IsEmpty(vAnns) Then
' 注釈のループ
For i = 0 To UBound(vAnns)
Set swAnn = vAnns(i)
' 注釈が「寸法(Dimension)」であるかを確認
If swAnn.GetType = swAnnotationType_e.swAnnotationType_Dimension Then
Set swDispDim = swAnn.GetSpecificAnnotation
' ここで寸法同士の比較・再配置ロジックを呼び出す
' ※簡易化のため、ここでは「現在の寸法」と「次の寸法」を比較するロジックの概念を示します
ProcessDimensionCollision swDispDim, MIN_DISTANCE
End If
Next i
End If
' 次のビューへ
Set swView = swView.GetNextView
Loop
swModel.GraphicsRedraw ' 画面を更新
MsgBox "レイアウトの最適化が完了しました。"
End Sub
' --- 4. 衝突判定と再配置のコアロジック ---
Sub ProcessDimensionCollision(ByRef swDispDim As SldWorks.DisplayDimension, ByVal minDist As Double)
Dim swAnn As SldWorks.Annotation
Dim vPos As Variant
Dim currentX As Double, currentY As Double
Dim newY As Double
Set swAnn = swDispDim.GetAnnotation
' 寸法の現在の表示位置(テキストの位置)を取得
' GetTextPositionは [X, Y, Z] の配列を返す
vPos = swAnn.GetTextPosition
currentX = vPos(0)
currentY = vPos(1)
' 【ここがアルゴリズムの本質】
' 本来は、全ての寸法を一旦配列に格納し、ソートしてから比較するのが理想的です。
' 今回は「もし、現在のY座標が特定の条件を満たしたら、上にずらす」という
' 概念的な実装例を示します。
' 例: Y座標が0に近い(あるいは特定の範囲にある)場合に、強制的にオフセットする
' 実際の実装では、他の寸法との距離を計算するロジックが入ります。
' 仮のロジック: 座標が重なるリスクがある場合に、新しいYを計算
' newY = currentY + minDist
' swAnn.SetTextPosition 0, newY, 0
' 注意: 実運用では、スキャンした全寸法の座標をListに保持し、
' Y座標でソートした後、隣り合う要素の距離をチェックするアルゴリズムを推奨します。
End Sub
5. コードの解剖:エンジニアの視点
このコードをただ眺めるのではなく、「なぜこう書くのか」に注目してください。
① `swAnnotationType_e.swAnnotationType_Dimension` の重要性
ビューの中には、寸法だけでなく、中心線や注釈テキスト、矢印なども含まれています。これらを区別せずに座標操作を行うと、図面が崩壊します。「型(Type)を特定してから操作する」。これは、APIプログラミングにおける鉄則です。
② 座標系(Coordinate System)の罠
`GetTextPosition` で取得できる値は、「そのビューの原点からの相対座標」です。
もし、シート全体の座標(Sheet Coordinate)とビューの座標(View Coordinate)を混同して計算すると、寸法が図面の遥か彼方へ飛んでいってしまいます。
「今、自分はどの座標系の上で踊っているのか?」を常に意識してください。
③ パフォーマンスの最適化
大量の寸法がある図面で、ループの中で毎回 `GraphicsRedraw`(画面更新)を呼び出すと、処理速度は劇的に低下します。
「計算はメモリ内ですべて終わらせ、最後に一気に描画する」。これが、プロの書くコードの作法です。
6. 次のステップへ:さらに高度なアルゴリズムにするには
今回のコードは、その「考え方の骨組み」を示すためのものです。これを実用的なツールに昇華させるには、以下のステップに挑戦してみてください。
1. ソート・アルゴリズムの実装:
取得した全寸法の座標を、一旦 `Collection` や `Array` に格納し、Y座標の昇順でソートします。
2. 近接判定の厳格化:
「X座標がほぼ同じ(誤差範囲内)」かつ「Y座標の差が `MIN_DISTANCE` 未満」という条件で、衝突を定義します。
3. 再配置の連鎖:
1つ目の寸法を動かした結果、2つ目と重なるかもしれません。これを防ぐために、動かした後の新しい座標を基準に、次の寸法を計算する「連鎖的オフセット」を実装します。
最後に
SolidWorks VBAの世界は、単なる「自動化」の道具ではありません。それは、「設計者の意図を、数学的な美しさへと変換する手段」です。
「マクロの記録」から一歩踏み出し、オブジェクトの階層を辿り、座標を操る。このプロセスは最初は難しく感じるかもしれません。しかし、一度この感覚を掴めば、あなたは設計業務の「作業者」から、プロセスを支配する「アーキテクト」へと進化できるはずです。
一歩ずつ、コードの海を渡っていきましょう。応援していますよ。
